2015年5月7日木曜日

ggplotで積み上げ棒グラフ その2 負の積み上げ

棒グラフの積み上げ順序はわかりました。今度は、負の値がある利益のようなデータをプロットしてみたいと思います。
この表をExcel やCalcで棒グラフにするとこんな風になります。正の値と負の値を別々に積み上げます。(Calcで描いたものです。)

利益

2011201220132014
商品A10204080
商品B10060-1020
商品X-20-30010
商品Y-30-40-4020
Rのbarplotやggplotでは、こんなふうにはなりません。ggplotで描いてみるとこんな風になりました。2011の項目については、A,Bを100まで積み上げて、X,Yを下に-50積み上げています。考えてみると、Excelより自然な処理だと思いますが、この図、何がなんだかわかりません。
ggplotの棒グラフは基本的にカウントデータを前提にしたものなのでしょうから、最小値が0でない場合は警告を出しています。

> profit.ldf <- melt(profit.tbl, value.name = "利益")
> qplot(data = profit.ldf, x = 年, y = 利益, fill = 商品, geom = "bar",
+       stat = "identity", position = "stack") +
+   guides(fill = guide_legend(reverse = TRUE))
Warning message:
In loop_apply(n, do.ply) : Stacking not well defined when ymin != 0



私が必要としているのはExcel風の棒グラフなのでExcelで描けばよいのですが。
結局、積み上げの部分を正と負に分割して作成して合成しました。レイヤーって便利です。やっぱり警告も出ますが、意図したようになったわけだから無視します。でも、私の知らない他の良い方法がありそうな気もするのです。

> fig <- ggplot() +
+   #正の積み上げ
+   geom_bar(data = subset(profit.ldf, 利益 > 0), aes(x = 年, y = 利益, fill = 商品),
+            stat = "identity", position = "stack") +
+   #負の積み上げ
+   geom_bar(data = subset(profit.ldf, 利益 < 0), aes(x = 年, y = 利益, fill = 商品),
+            stat = "identity", position = "stack") +
+   #合計の折れ線
+   geom_line(data = melt(xtabs(利益 ~ 年, data = profit.ldf)), aes(x = 年, y = value),
+             color = "black") +
+   #合計の点グラフ
+   geom_point(data = melt(xtabs(利益 ~ 年, data = profit.ldf)), aes(x = 年, y = value),
+              color = "black", pch = 23, bg = "white") + #ggplotでもpch使えるんだ!
+   #x軸
+   geom_hline(yintercept=0, color = "black")
> fig + guides(fill = guide_legend(reverse = TRUE)) #凡例を逆転
Warning message:
In loop_apply(n, do.ply) : Stacking not well defined when ymin != 0



2015年5月3日日曜日

ggplotで積み上げ棒グラフ その1 積み上げの順序

死亡フラグが立っていたこのブログのことを思い出して、久しぶりの投稿。

今更ながら、ggplot2を使って積み上げグラフを描いてみました。


sales.ldf <- melt(sales.tbl, value.name = "売上") #長いデータフレームに変換
qplot(data = sales.ldf, x = 年, y = 売上, fill = 商品,
      geom = "bar", stat = "identity", position = "stack") +
  guides(fill = guide_legend(reverse = TRUE)) #判例の順番を逆転

商品A商品B商品X商品Y
2011101001030
201220403040
20131003040
20145002020
これは、我らリーマンがよく描くタイプのグラフです。でも、私、故あって商品をA,X,B,Yの順番に積み上げたいのです。x軸の順番を並べ替える時は、factorの水準を変えればよかったので、積み上げ順を変更するのにも、水準を変えれば良いだろう思いました。


sales.ldf$商品 <- factor(sales.ldf$商品, levels = c("商品A","商品X","商品B","商品Y"))

として、qplot(...)を実行すると、

ありゃりゃ?凡例の順番は変わっているのに、積み上げ順は元のままではないですか。商品の水準の順番と思い込んでいたので、ハマることしばし。
ということで、なんのあてもなく長いデータフレームを商品順に並べてみました。

sales.ldf <- arrange(sales.ldf, 売上) #dplyrパッケージを使って

と長いデータフレームを売り上げ順に並び替えてみて描いてみると、意図していた積み上げ順になりました。

商品 売上
1 2011商品A20
2 2012商品A20
3 2013商品A10
4 2014商品A50
5 2011商品X10
6 2012商品X30
7 2013商品X30
: :::
積み上げ順序は、水準なんかではなくて、長いデータフレームの中の並び順なのでした。より正確には、x軸の一番右の項目(この場合は2011)に関しての並び順のようでした。
というわけで、1番目の項目のところだけ並び替えれば任意の順番に積み上げられるわけですね。2番目以降順番は無視。

商品売上
42011商品Y30
32011商品X10
12011商品A20
22011商品B100
52012商品A20
62012商品B40
72012商品X30
::::
知りませんでした。私だけ?