r - Showing data values on stacked bar chart in ggplot2 - Stack Overflowを見て、なんかもっと簡単にできそうな気がした。

質問者のコードは以下の通り:

Year      <- c(rep(c("2006-07", "2007-08", "2008-09", "2009-10"), each = 4))
Category  <- c(rep(c("A", "B", "C", "D"), times = 4))
Frequency <- c(168, 259, 226, 340, 216, 431, 319, 368, 423, 645, 234, 685, 166, 467, 274, 251)
Data      <- data.frame(Year, Category, Frequency)
library(ggplot2)
p <- qplot(Year, Frequency, data = Data, geom = "bar", fill = Category, theme_set(theme_bw()))
p + geom_text(aes(label = Frequency), size = 3, hjust = 0.5, vjust = 3, position ="stack")
## ymax not defined: adjusting position using y instead

回答者のコードは以下の通り(評価させてません):

library(ggplot2)

# calculate midpoints of bars (simplified using comment by @DWin)
Data <- ddply(Data, .(Year), transform, pos = cumsum(Frequency) - (0.5 * Frequency))

# plot bars and add text
p <- ggplot(Data, aes(x = Year, y = Frequency)) +
     geom_bar(aes(fill = Category), stat="identity") +
     geom_text(aes(label = Frequency, y = pos), size = 3)

たぶんもうちょっと楽な方法があるんじゃないかなぁと思い、色々試してみました。ベースは以下のbarplotです:

p <- ggplot(Data, aes(x = Year, y = Frequency)) +
  geom_bar(aes(fill = Category), stat="identity") +
  geom_text(aes(label = Frequency), size = 3, position = "stack")
p
## ymax not defined: adjusting position using y instead

まずgeom_text(aes(label = Frequency, y = hogehoge), ...)で調整できないか考えましたが、この場合たぶん上記回答者のようにやるのが一番手っ取り早いなと思いました。なのでこのアプローチは忘れます。

着目したのはvjustです。これを設定すると、ラベルの位置をずらすことができます。

p <- ggplot(Data, aes(x = Year, y = Frequency)) +
  geom_bar(aes(fill = Category), stat="identity") +
  geom_text(aes(label = Frequency), size = 3, position = "stack", vjust = 2)
p
## ymax not defined: adjusting position using y instead

このvjust = *の数値をあげていくと、どんどん下にずれていきます。でもこれだと全てのラベルが同じ幅だけ下がることになり、各棒のどまんなかに配置するのは無理です。各棒のy値にあわせて割合でずらさないといけません。てことでこうやってみました:

p <- ggplot(Data, aes(x = Year, y = Frequency)) +
  geom_bar(aes(fill = Category), stat="identity") +
  geom_text(aes(label = Frequency), size = 3, position = "stack", vjust = Frequency/75)
p
## ymax not defined: adjusting position using y instead

このようにy値の変数を定数で補正したものをvjust =に投げると、割合的にずれてくれるようになります。一覧にしてみるとこんな感じです:

q <- ggplot(Data, aes(x = Year, y = Frequency)) +
  geom_bar(aes(fill = Category), stat = "identity") +
  facet_wrap(~v) +
  lapply(c(1,30,60,90,120,150), function(i) geom_text(data = transform(Data, v=sprintf("v_%.02f", i)),aes(label = Frequency), size = 3, position = "stack", vjust = Frequency / i)
  )
q
## ymax not defined: adjusting position using y instead
## ymax not defined: adjusting position using y instead
## ymax not defined: adjusting position using y instead
## ymax not defined: adjusting position using y instead
## ymax not defined: adjusting position using y instead
## ymax not defined: adjusting position using y instead

こんな感じになります。ただ、最大の問題はその補正する定数をどう設定したらど真ん中にくるかかわからないことです。ちなみに最初Rスクリプトでテストしてた時はhoge/50で調度良かったのですが、今回Rmdにしてみたらhoge/70でそれなりの場所にきました。また、最後の例のように2行にしてみたらまた変わりました。

多分plotの領域とかその辺も関与してそうですが、これ以上深入りしてもアレなのでここまでにします。最後にこれを試すきっかけになった質問への神Hadleyのコメントリンクを付けておきます:

http://stackoverflow.com/questions/6644997/showing-data-values-on-stacked-bar-chart-in-ggplot2#comment7870900_6644997

Enjoy!