ggplot2パッケージを使って、棒グラフを作成してみる-3
R グラフィックス クックブック 6回目
ggplot2パッケージを利用して、棒グラフを作成していきます。
この2つを対象にします。
- 棒グラフにラベルを追加する
- (Cleveland)ドットプロット
棒グラフにラベルを追加する
利用するデータ
このキャベツデータを使います。
> head(cabbage_exp) Cultivar Date Weight sd n se 1 c39 d16 3.18 0.9566144 10 0.30250803 2 c39 d20 2.80 0.2788867 10 0.08819171 3 c39 d21 2.74 0.9834181 10 0.31098410 4 c52 d16 2.26 0.4452215 10 0.14079141 5 c52 d20 3.11 0.7908505 10 0.25008887 6 c52 d21 1.47 0.2110819 10 0.06674995
ラベル付きの棒グラフ
まずマッピングとグラフの種類を指定します。
#x軸に日付と品種、y軸に重さを指定する cabbageMap <- ggplot(cabbage_exp,aes(x=interaction(Date,Cultivar),y=Weight)) #幾何オブジェクトに、棒グラフを指定する chartType <- geom_bar(stat="identity")
そしてラベルを指定します。
#色が白で、位置が1.5 chartLabel <- geom_text(aes(label = Weight), vjust=1.5,colour = "white")
描画します。
> cabbageMap + chartType + chartLabel
ラベルの位置
ラベルの位置は、vjustで指定します。
vjustの基本位置は、棒の上端が基本位置になります。
#vjust=0が棒の上端を指す。正の値が棒の下/負の値が棒の上を指す geom_text(aes(label = Weight), vjust=1.5,colour = "white")
ラベルを棒の上に変更します。
#ラベル位置を棒の上部に設定し、ラベルテキストの色を黒に > chartLabelOver <- geom_text(aes(label = Weight), vjust=-0.2,colour = "black") #グラフを描画する > cabbageMap + chartType + chartLabelOver
y軸はマッピングされた値で設定されるので、棒の高さによっては、
ラベルが見切れてしまう事に注意が必要です。
ラベルを見切れない位置に設定する
このラベルを見切れないための対策は2つです。
- y軸を伸ばす
- 棒のある一定の上側に配置する
上記の2種を比較しやすくするために、
コードの重複部分を、1つのオブジェクトに格納します。
cabbageBarChart <- cabbageMap + chartType
- y軸を伸ばす方法
y軸を、重さ値の1.05倍まで表示して、ラベル位置を上端から0.2上に位置させます。
cabbageBarChart + geom_text(aes(label = Weight), vjust = -0.2) + ylim(0, max(cabbage_exp$Weight) * 1.05)
- 棒のある一定の上側に配置する
ラベル位置を重さ値の0.1多い位置に位置させます。
cabbageBarChart + geom_text(aes(label = Weight, y = Weight + 0.1))
どちらも同じに見えるかもしれませんが、
後者の棒のある一定の上側に配置するはあまりお勧めできません。
というのも、Weightの値によって、+ 0.1の部分を変更しないといけないためです。
ラベル付きのグループ化された棒グラフ
グループ化された棒グラフにラベルを付ける際には、下記2つに注意します。
- ラベルのずらしを指定する
- ラベルのフォントサイズを指定する
デフォルトのグループ化された棒グラフを作成します。
#マッピングと幾何オブジェクトを指定する cabbageGroupedBarChart <- ggplot(cabbage_exp, aes(x = Date, y=Weight, fill=Cultivar)) + geom_bar(stat = "identity", position = "dodge") #グラフを描画する cabbageGroupedBarChart
- ラベルを指定する
ずらしや、フォントサイズの指定をせずにラベルを表示させます。
cabbageGroupedBarChart + geom_text(aes(label = Weight), vjust = 1.5, colour = "white")
ラベルが、グループ化されたx軸の真ん中に来ています。
これでは何だか分からないので、ラベルのずらしを検討します。
- ラベルのずらしを指定する
ラベルをずらす前に、グループ化された棒グラフの成り立ちを考えます。
幾何オブジェクト部分
#上記コードで、幾何オブジェクトを表す部分 geom_bar(stat = "identity", position = "dodge")
この幾何オブジェクトの指定は、position="dodge"としているので、
幾何オブジェクト自体が、「ずらし」で成り立っていることが分かります。
つまり、ラベルも「ずらし」で指定すれば、棒に重ねて表示できます。
そして、この「ずらし」のデフォルト値ですが、0.9です。
#このコードは、position = "dodge"と同じ geom_bar(stat = "identity", position = position_dodge(0.9))
上記を踏まえ、ラベルのずらしを指定したグラフがこちらです。
cabbageGroupedBarChart + geom_text(aes(label = Weight), vjust = 1.5, colour = "white", position = position_dodge(0.9))
- ラベルのフォントサイズを指定する
棒が多くなりにつれ、棒の幅が狭くなっていきます。
(これは極端な例です。そもそも見えないので、可視化の目的を達成してないです。)
そのため、棒の幅に合わせて、ラベルのフォントサイズを指定する必要があります。
フォントサイズは、sizeで指定します。(デフォルトは5です。)
cabbageGroupedBarChart + geom_text(aes(label = Weight), vjust = 1.5, colour = "white", position = position_dodge(0.9), size = 10)
ラベル付きの積み上げ棒グラフ
積み上げのグループ毎に、累積和を算出する必要があります。
下のグラフは、x軸は日付で、グループ化は品種で、y軸に重さが図示しています。
下記を例にとると、日付d16でグループ化されている品種c39・c52毎の、重さ累積和が必要です。
cabbageGroupedMap <- ggplot(ce,aes(x=Date,y=Weight,fill=Cultivar)) cabbageGroupedMap + geom_bar(stat="identity")
上記のような、○○毎に△△の値を集計するためには、
この記事でも使用したplyrパッケージを利用します。
mukkujohn.hatenablog.com
library(plyr) ce <- ddply(cabbage_exp,"Date",transform,label_y=cumsum(Weight)) > ce Cultivar Date Weight sd n se label_y 1 c39 d16 3.18 0.9566144 10 0.30250803 3.18 2 c52 d16 2.26 0.4452215 10 0.14079141 5.44 3 c39 d20 2.80 0.2788867 10 0.08819171 2.80 4 c52 d20 3.11 0.7908505 10 0.25008887 5.91 5 c39 d21 2.74 0.9834181 10 0.31098410 2.74 6 c52 d21 1.47 0.2110819 10 0.06674995 4.21
label_y列が、Dateで区切り、Cultivarの累積和になります。
ラベル無しでグラフを表示します。
cabbageBuildupBarChart <- ggplot(ce,aes(x=Date,y=Weight,fill=Cultivar)) + geom_bar(stat="identity") cabbageBuildupBarChart
ラベルを付与して表示します。
cabbageBuildupBarChart + geom_text(aes(y = label_y, label = Weight), vjust = 1.5,colour = "white", size = 7)
aesのy引数に、事前に算出した累積和を指定しています。
このy引数を指定して、位置を分からせてあげないとこんなグラフになります。
ラベルを表示するy位置に、fill値に指定されたCultivar毎のweight値を使っています。
表示するy位置を変更すれば、ラベルを棒の上下真ん中に配置することができます。
ce <- ddply(ce,"Date",transform,label_y=cumsum(Weight)-0.5*Weight)
あとは、人の好みで、お好きなように外観をいじります。
cabbageBuildupBarChart + geom_text(aes(y=label_y, label=paste(format(Weight, nsmall = 2),"kg")), size=5, colour="black") + guides(fill=guide_legend(reverse = TRUE)) + scale_fill_brewer(palette = "Pastel1")
(Cleveland)ドットプロット
この様なグラフが、ドットプロットと言います。
なぜ棒グラフと、同じカテゴリで扱っているのかといいますと、
この棒グラフ代替と言えるからっぽいです。*1
確かに、塗りつぶす必要性が感じられないですね。
利用するデータ
2001年のメジャーリーグの選手データです。
ここから25人に限り、name・lg・avg列を使用します。
library(gcookbook) tophit <- tophitters2001[1:25,c("name","lg","avg")] head(tophit) name lg avg 1 Larry Walker NL 0.3501 2 Ichiro Suzuki AL 0.3497 3 Jason Giambi AL 0.3423 4 Roberto Alomar AL 0.3357 5 Todd Helton NL 0.3356 6 Moises Alou NL 0.3314
並び替えと見た目の調整
上述のグラフは,y軸の下からnameのアルファベット順になっています。
着目している値は、avgですので、avg順に並び替えます。
ggplot(tophit,aes(x=avg, y=reorder(name, avg))) + geom_point()
ドットを大きくして、背景・目盛り線を変更します。
ggplot(tophit,aes(x=avg, y=reorder(name, avg))) + #ドットサイズを指定する geom_point(size = 3) + #背景を変更する theme_bw() + #目盛り線を変更する theme(panel.grid.major.x = element_blank(), panel.grid.minor.y = element_blank(), panel.grid.major.y = element_line(colour = "grey60",linetype = "dashed"))
x軸とy軸を入れ替える
x軸とy軸は、マッピングの指定部分で入れ替えるだけです。
x軸の名前が横に表示されると重なって見えないため、角度をつけています。
#x軸とy軸にバインドしている値を入れ替える ggplot(tophit,aes(x=reorder(name, avg), y=avg)) + geom_point(size = 3) + theme_bw() + #x軸のテキストを60°つけて表示する theme(axis.text.x = element_text(angle = 60, hjust = 1), panel.grid.major.x = element_blank(), panel.grid.minor.y = element_blank(), panel.grid.major.y = element_line(colour = "grey60",linetype = "dashed"))
グループ化する
所属しているリーグ毎にグループ化したいと思います。
グループ化するためには、ファクタを使います。
まず、リーグ毎に、avg順に名前を並び替えます。
nameOrder <- tophit$name[order(tophit$lg,tophit$avg)]
次に、マッピングされるデータを、順序のレベルを持つファクタに変更します。
tophit$name <- factor(tophit$name,levels = nameOrder)
そのデータを利用して、ドットプロットを描画します。
ggplot(tophit, aes(x = avg, y = name)) + geom_point(size = 3, aes(colour = lg)) + theme_bw() + theme(panel.grid.major.y = element_blank())
ドットプロットの見た目の変更
凡例をグラフ内に押し込めます。
ggplot(tophit, aes(x = avg, y = name)) + geom_point(size = 3, aes(colour = lg)) + theme_bw() + theme(panel.grid.major.y = element_blank(), legend.position = c(1, 0.55), #凡例の位置を指定する legend.justification = c(1, 0.55))
それぞれの点にy軸から線を描画してみます。
ggplot(tophit, aes(x = avg, y = name)) + geom_point(size = 3, aes(colour = lg)) + geom_segment(aes(yend = name), xend = 0, colour = "black") + theme_bw() + theme(panel.grid.major.y = element_blank(), legend.position = c(1, 0.55), legend.justification = c(1, 0.55))
パレットを変更します。
ggplot(tophit, aes(x = avg, y = name)) + geom_segment(aes(yend = name), xend = 0, colour = "black") + geom_point(size = 3, aes(colour = lg)) + scale_colour_brewer(palette = "Set1", limits = c("NL","AL")) + theme_bw() + theme(panel.grid.major.y = element_blank(), legend.position = c(1, 0.55), legend.justification = c(1, 0.55))
グループ化について、ファセットを使う手段もあります。
ggplot(tophit, aes(x = avg, y = name)) + geom_segment(aes(yend = name), xend = 0, colour = "black") + geom_point(size = 3, aes(colour = lg)) + #凡例表示をやめる scale_colour_brewer(palette = "Set1", limits = c("NL","AL"), guide = FALSE) + theme_bw() + theme(panel.grid.major.y = element_blank()) + #ファセットグリッドを表示する facet_grid(lg ~., scales = "free_y", space = "free_y")
棒グラフの描画について、3回にかけて触れてきました。
次回からは、折れ線グラフを作成していきたいと思います。