ggplot2を使って、軸を制御する-4
R グラフィックス クックブック 25回目
ggplot2パッケージを利用して、軸を制御していきます。
今回は、軸の線を強調したり、対数軸を用いてみます。
軸の線の強調
こちらのグラフをベースにします。
x軸・y軸に線を引くためには、theme()を使い、axis.line引数を指定します。
#x軸・y軸に線を引き、強調する ベースプロット + theme(axis.line = element_line(colour="black"))
x軸・y軸に黒線が引かれ、くっきりしました。
プロット領域の境界線を持つ場合は、あえて消す指定を行う必要があります。
例えば、theme_bw()を使うような場合です。
ベースプロット + theme_bw()
上のプロットのように、境界線がある場合は、ブランクを指定してから追加します。
#panel.border引数に、ブランクを指定します #axis.line引数に、線を指定します ベースプロット + theme_bw() + theme(panel.border = element_blank(), axis.line = element_line(colour="black"))
element_line()ですが、size引数で線の太さを指定できます。
ベースプロット + theme_bw() + theme(panel.border = element_blank(), axis.line = element_line(colour="black",size=4))
左下を見ると、微妙に開いています。
重ねて表示するためには、lineend引数にsquareを指定します。
ベースプロット + theme_bw() + theme(panel.border = element_blank(), axis.line = element_line(colour="black",size=4,lineend="square"))
対数軸
対数軸を使うと、軸上の距離が割合で表現できます。
今まで扱っていたのは、線形軸と呼びます。軸上の距離は一定の変化量です。
R: Brain and Body Weights for 28 Speciesデータセットを使います。
動物の体重(kg)と脳の重さ(g)のデータセットです。
> head(Animals) body brain Mountain beaver 1.35 8.1 Cow 465.00 423.0 Grey wolf 36.33 119.5 Goat 27.66 115.0 Guinea pig 1.04 5.5 Dipliodocus 11700.00 50.0 > str(Animals) 'data.frame': 28 obs. of 2 variables: $ body : num 1.35 465 36.33 27.66 1.04 ... $ brain: num 8.1 423 119.5 115 5.5 ...
x軸に体重、y軸に脳の重さをマッピングし、行の名前をラベルに表示します。
ggplot(Animals, aes(x=body,y=brain,label=rownames(Animals))) + geom_text(size=3)
これだと、体重や脳の重さが大きいデータポイントのせいで、軸が拡張され
ほとんどのデータポイントが左下に集まってしまっています。
このような場合、軸を対数軸に変更し、軸上の距離を割合で表現した方が良いです。
対数軸を使うには、scale_x_log10()やscale_y_log10()を使います。
ベースプロット + scale_x_log10() + scale_y_log10()
データの分布が見たいので、散布図を使っています。データポイントの値が見たいわけではないです。
scale_x_log10()やscale_y_log10()を使うと、目盛りが自動で設定されます。
目盛りを指定するためには、breaks引数を指定します。
ベースプロット + scale_x_log10(breaks=10^(-1:5)) + scale_y_log10(breaks=10^(0:3))
x軸を見ると1e-01、1e+00、1e+01と表現されていますが、
指数表記に変換するためには、scalesライブラリのtrans_format()を使います。
library(scales) ベースプロット + scale_x_log10(breaks=10^(-1:5), labels=trans_format("log10",math_format(10^.x))) + scale_y_log10(breaks=10^(0:3), labels=trans_format("log10",math_format(10^.x)))
scale_x_log10()やscale_y_log10()を使い、log10の対数を扱いましたが
自然対数はlog2などの対数を扱うこともできます。
#x軸は自然対数、y軸はlog2です。軸で基数が異なります。 ベースプロット + scale_x_continuous(trans = log_trans(), breaks=trans_breaks("log",function(x) exp(x)), labels=trans_format("log",math_format(e^.x))) + scale_y_continuous(trans=log2_trans(), breaks=trans_breaks("log2",function(x) 2^x), labels=trans_format("log2",math_format(2^.x)))
散布図を使って、x軸・y軸の両方の軸に対数を使いましたが、
片方の軸だけに指定することもできます。
2010年以降は指数関数的に増えています。対数軸の出番です。
#y軸だけを対数軸にします。目盛りを指定します。 上のグラフ + scale_y_log10(breaks=c(2,10,50,250))
上のグラフより、変化が理解できますね。
対数軸の目盛り
対数軸に目盛りを追加するには、annotation_logticks()を使います。
ベースプロット + annotation_logticks() + scale_x_log10(breaks = 10^(-1:5), labels = trans_format("log10", math_format(10^.x))) + scale_y_log10(breaks = 10^(0:3), labels = trans_format("log10", math_format(10^.x)))
長い目盛り線が10の累乗、中間の長さの目盛り線が5の累乗を指しています。
プロットを見ると、目盛り記号の色(灰色?)と目盛り線の色(黒)が異なり、
補助目盛り線(薄い白い線)が5の累乗の位置からずれています。
目盛り記号の色と目盛り線の色を合わせるには、theme_bw()を使います。
ベースプロット + annotation_logticks() + scale_x_log10(breaks = 10^(-1:5), labels = trans_format("log10", math_format(10^.x))) + scale_y_log10(breaks = 10^(0:3), labels = trans_format("log10", math_format(10^.x))) + theme_bw()
目盛り記号の色と目盛り線の色が合いました!
補助目盛り線と5の累乗の位置を合わせるには、minor_breaks()を使います。
minor_breaks()の引数に、自身で計算した値を設定する必要があります。
x軸、y軸ともにlog10なので、log10(5*10^累乗値) ⇒ log10(5) + 累乗値 です。
ベースプロット + annotation_logticks() + scale_x_log10(breaks = 10^(-1:5), labels = trans_format("log10", math_format(10^.x)), minor_breaks = log10(5) + -2:5) + scale_y_log10(breaks = 10^(0:3), labels = trans_format("log10", math_format(10^.x)), minor_breaks = log10(5) + -1:3) + theme_bw() + coord_fixed()
補助目盛り線と、中間の5の累乗の位置が合いました!
今日の全部入り
ベースプロット + annotation_logticks() + scale_x_log10(breaks = 10^(-1:5), labels = trans_format("log10", math_format(10^.x)), minor_breaks = log10(5) + -2:5) + scale_y_log10(breaks = 10^(0:3), labels = trans_format("log10", math_format(10^.x)), minor_breaks = log10(5) + -1:3) + theme_bw() + coord_fixed() + theme(panel.border = element_blank(), axis.line = element_line(colour="grey60",size=.1,lineend="square"))
次回は、円形グラフを扱ってみます。
Power BIの軸や凡例の並び順を調べてみた
Power BI Desktop
2016/10/25追記
このツールですが、軸や凡例の並び順が指定できません。
できます。
powerbi.microsoft.com
並び順の指定はこちら
mukkujohn.hatenablog.com
これから下は、指定方法が分からない状況で、どうせ文字コードだよねということを
確認している内容です。
英数字を利用している部分はいいのですが、
日本語を軸や凡例にマッピングすると、何順なのかさっぱりです。
グラフの書式を確認しても、並び順を指定できそうな感じがしません。
それ以上に、目盛りラベルのフォントサイズ大きくしたいんですが、、、。
UIで提供されていないのであれば、ツール側で勝手にやっているはずで、
思いつくのが、文字コードか?なので、文字コード通りか調べてみました。
どの文字コードが調べても出てきませんでした。。。おそらくUTF-8だろうと仮定して進めます。
利用するデータ
同じデータをUTF-8とShift-JIS(ANSI)で用意しました。
名前 | 科目 | 点数 |
---|---|---|
但 | 数学 | 80 |
但 | 国語 | 60 |
但 | 社会 | 50 |
但 | 英語 | 90 |
但 | 理科 | 70 |
佐 | 数学 | 70 |
佐 | 国語 | 80 |
佐 | 社会 | 60 |
佐 | 英語 | 90 |
佐 | 理科 | 40 |
佑 | 数学 | 10 |
佑 | 国語 | 30 |
佑 | 社会 | 40 |
佑 | 英語 | 20 |
佑 | 理科 | 100 |
文字コードの並び順については、このサイトを利用させて頂きました。
ash.jp
名前列でSJISとUTF-8で並び順が異なる文字を利用しています。
区 | 点 | JIS | SJIS | EUC | UTF-8 | UTF-16 | 字 |
---|---|---|---|---|---|---|---|
26 | 20 | 3A34 | 8DB2 | BAB4 | E4BD90 | 4F50 | 佐 |
45 | 04 | 4D24 | 9743 | CDA4 | E4BD91 | 4F51 | 佑 |
35 | 02 | 4322 | 9241 | C3A2 | E4BD86 | 4F46 | 但 |
並び順は下記の順番です。
文字コード | 1 | 2 | 3 |
---|---|---|---|
UTF-8 | 但 | 佐 | 佑 |
Shift-JIS | 佐 | 但 | 佑 |
Power BI Desktop
まずは、Power BI Desktopを使って確認していきます。
軸
UTF-8版のCSVと、Shift-JIS版のCSVを両方取り込みます。
UTF-8版のインポート
Shift-JIS版のインポート
x軸に名前、y軸に点数をマッピングします。
見づらいですが、x軸の上から確認すると佐→但→佑となっています。
(目盛りラベルを大きくしたいと、すごい思いました。)
意外な感じですが、Shift-JISで並んでいるようです。
データのエクスポート
グラフからエクスポートしたデータファイルの文字コードを確認してみます。
このように、グラフの右上の…からエクスポートします。
Notepadで開いて確認してみます。
UTF-8ファイルデータのグラフからエクスポートしたファイルを選びます。
開く時に、UTF-8を指定します。
文字化けはしていません。
エクスポートするとUTF-8になるのでしょうか?
今度は、開く時にANSIを指定します。
文字化けしました。
Shift-JISファイルデータも結果は同じでした。
これまでをまとめると、Power BI Desktop上の軸や凡例はShift-JISで並んでいて、
データをエクスポートすると、UTF-8です。
Power BI Service
Power BI Desktopで作成したレポートを発行し、ブラウザで確認します。
軸
佐→但→佑となっています。
凡例
佐→但→佑となっています。
データのエクスポート
Power BI Desktopからエクスポートした時と同様、UTF-8になっています。
Shift-JISでの確認
予想に反して、軸や凡例の並び順がShift-JISで行われているそうなので、
Shift-JISコードでの前後文字で確認しました。
区 | 点 | JIS | SJIS | EUC | UTF-8 | UTF-16 | 字 |
---|---|---|---|---|---|---|---|
26 | 19 | 3A33 | 8DB1 | BAB3 | E4BA9B | 4E9B | 些 |
26 | 20 | 3A34 | 8DB2 | BAB4 | E4BD90 | 4F50 | 佐 |
26 | 21 | 3A35 | 8DB3 | BAB5 | E58F89 | 53C9 | 叉 |
些 → 佐 → 叉となるはずです。
先ほどの手順と同様に、文字コードがUTF-8版とShift-JIS版のファイルを使います。
UTF-8版
Shift-JIS版
同じグラフを使って、軸と凡例の並び順を確認します。
軸は、些 → 佐 → 叉となっています。
(目盛りラベルを大きくしたいぃぃぃぃ。)
凡例も、些 → 佐 → 叉となっています。
Power BI Serviceに発行して確認しても、同じ結果でした。
まとめ
Power BIにおける日本語データの扱いは下記のようです。
困るのがこの辺でしょうねぇ。
1つ目は、既定でShift-JIS(ANSI)になっているだけなので、
ファイルクリックからExcelを起動する事をやめましょう。
新規でExcelを起動して、データタブからインポートする形で取り込みましょう。
取り込む途中で文字コードが指定できます。
2016/10/25追記
並び順は指定できます。
2つ目は、佐藤、鈴木、田中とか、あいうえお順だと順番変わるんですよね。
- あいうえお順:佐藤 → 鈴木 → 田中
- Shift-JIS順:佐藤 → 田中 → 鈴木
なので、並び順にはこだわらない or 並び順用の列を追加する かな。
ただ、並び順用に、1.佐藤 2.鈴木 3.田中の列を用意して、マッピングすると
その値が使われるので、「1.」この部分何?となります。
並び順の指定と目盛りラベルを大きくするをしてほしいものです。
ggplot2を使って、軸を制御する-3
R グラフィックス クックブック 24回目
ggplot2パッケージを利用して、軸を制御していきます。
今回は、目盛りラベル/軸ラベルのテキストを制御します。
目盛りラベルのテキスト
こちらのグラフのy軸の目盛りラベルを対象にします。
y軸の目盛りラベルは、50、55、60、65、70で設定されています。
目盛りを変更するためには、scale_y_continuous()のbreaks引数を指定します。
#目盛りを、50,56,60,66,72に設定します。 ベースのグラフ + scale_y_continuous(breaks=c(50,56,60,66,72))
この50,56,60,66,72の目盛りのテキスト(ラベル)を変更するためには、
scale_y_continuous()のlabels引数を指定します。
ベースのグラフ + scale_y_continuous(breaks=c(50,56,60,66,72), labels=c("Tiny","Really\nshort","Short","Medium","Tallish"))
このbreaks引数とlabels引数の要素数は、同じである必要があります。
要素数が異なる場合は、エラーになります。
Error: Breaks and labels have unequal lengths
labels引数ですが、別途作成したフォーマッタ関数を指定できます。
#インチをフィートとインチの形式に変換します footinch_formatter <- function(x){ foot <- floor(x/12) inch <- x %% 12 return(paste(foot,"'",inch,"\"",sep="")) } footinch_formatter(56:64) [1] "4'8\"" "4'9\"" "4'10\"" "4'11\"" "5'0\"" "5'1\"" "5'2\"" "5'3\"" "5'4\""
上で作成した関数をlabels引数に指定します。
#ggplotが自動で設定した目盛り値を変換してグラフに設定します ベースのグラフ + scale_y_continuous(labels=footinch_formatter)
さらに目盛りのテキスト(ラベル)は、theme()のaxis.text.y引数に、
element_text()を設定することで、体裁を設定できます。
(x軸の場合は、axis.text.x引数)
設定項目 | element_text()の引数 |
---|---|
角度 | angle |
水平位置 | hjust(0:左揃え~1:右揃え) |
垂直位置 | vjust(0:下揃え~1:上揃え) |
サイズ | size |
色 | colour |
スタイル | face(bold or italic) |
フォントファミリー | family |
まとめて指定する場合は、こんな感じになります。
ベースのグラフ + scale_y_continuous(breaks=c(50,56,60,66,72), labels=c("Tiny","Really\nshort","Short","Medium","Tallish")) + theme(axis.text.y = element_text(angle = 30, hjust = 1, vjust = 0 , size = rel(1.5), colour = "darkred", face = "italic"))
軸ラベルのテキスト
軸ラベル(x軸やy軸のタイトル)を変更する方法は、3通りあります。
- xlab()やylab()を使う
- labs()にx引数とy引数を指定する
- scale_x_continuous()やscale_y_continuous()のname引数を指定する
下の3つは全て同じ結果が得られます。
ベースのグラフ + xlab("Age in years") + ylab("Height in inches") ベースのグラフ + labs(x = "Age in years", y = "Height in inches") ベースのグラフ + scale_x_continuous(name = "Age in years") + scale_y_continuous(name = "Height in inches")
軸ラベルも、目盛りラベルと同様に、テキストの体裁を変更できます。
theme()の引数が微妙に異なります。
軸ラベル | 目盛りラベル |
---|---|
axis.title.y | axis.text.y |
(x軸は、yの部分をxにします)
axis.title.y引数に、element_text()を指定します。
ベースのグラフ + ylab("Height\n(inches)") + theme(axis.title.y= element_text(angle=0, face="italic", colour="darkred", size=14))
この記事の全部入りは、こんな感じになります。
#目盛りラベルも軸ラベルも設定します ベースのグラフ + scale_y_continuous(breaks=c(50,56,60,66,72), labels=c("Tiny","Really\nshort","Short","Medium","Tallish"), name = "Height\n(inches)") + theme(axis.text.y = element_text(angle = 30, hjust = 1, vjust = 0 , size = rel(1.5), colour = "darkred", face = "italic"), axis.title.y = element_text(angle = 0, face = "bold", colour = "grey",size = 15, vjust = 1), axis.title.x = element_text(hjust = 1,size = rel(2)))
ggplot2を使って、軸を制御する-2
R グラフィックス クックブック 23回目
ggplot2パッケージを利用して、軸を制御していきます。
今回は、軸のスケール比や目盛り軸を手動で設定します。
軸のスケール
こちらのデータセットを使います。
ハーフマラソンとフルマラソンのタイムのデータです。
> str(marathon) 'data.frame': 520 obs. of 2 variables: $ Half: num 66.8 67.9 68.7 69.9 70 ... $ Full: num 141 147 148 157 147 ... > head(marathon) Half Full 1 66.80000 141.4833 2 67.88333 147.2667 3 68.70000 147.8833 4 69.90000 156.7500 5 69.95000 147.4333 6 70.11667 150.0000
sp <- ggplot(marathon, aes(x=Half, y=Full)) + geom_point() sp
x軸が30m間隔、y軸が50m間隔になっていますが、どちらの軸も同じ指標です。
同じ指標ですので、軸は同じ間隔に揃えた方が、分布が分かりやすいです。
同じ間隔に揃えるためには、coord_fixed()を使い、さらに、
scale_y_continuous()とscale_x_continuous()のbreaks引数を指定します。
#0-420の間を30間隔にします sp + coord_fixed() + scale_y_continuous(breaks=seq(0,420,30))+ scale_x_continuous(breaks=seq(0,420,30))
この散布図は、ハーフマラソンとフルマラソンのタイムの分布のため
x軸のハーフマラソン側を、y軸のフルマラソンのスケールの1/2にした方が伝わりやすいかもしれません。
スケール比率を変更するためには、coord_fixed()のratio引数を指定します。
sp + coord_fixed(ratio=1/2) + scale_y_continuous(breaks=seq(0,420,30))+ scale_x_continuous(breaks=seq(0,420,15))
目盛りの位置
ここからは、R: Results from an Experiment on Plant Growthを使います。
p <- ggplot(PlantGrowth, aes(x=group,y=weight)) + geom_boxplot() p
デフォルトで適切な位置に目盛りを設定してくれますが、手動で設定するためには、
scale_y_continuous()とscale_x_continuous()のbreaks引数を指定します。
p + scale_y_continuous(breaks=c(4,4.25,4.5,5,6,8))
指定した目盛りが適用されるのは、主目盛り線になります。
補助目盛り線は、主目盛り線の中間の位置に描かれます。
等間隔で、breaks引数を指定する際に、seq()関数や:演算子を使うと楽です。
> seq(4,7,by=.5) [1] 4.0 4.5 5.0 5.5 6.0 6.5 7.0 > 5:10 [1] 5 6 7 8 9 10
離散値の軸に対しては、scale_x_discrete()やscale_y_discrete()関数に、
limits引数を指定して、順序の設定と要素の除外を行い、
breaks引数を指定して、ラベルの表示設定を行います。
#trt2とctrl列だけを表示して、ctrlだけラベルで設定する p + scale_x_discrete(limits=c("trt2","ctrl"),breaks="ctrl")
目盛りとラベルの非表示
目盛りのラベルを非表示にする場合は、theme()のaxis.text.y引数や
axis.text.x引数に、element_blank()を指定します。
#y軸の目盛りラベルを非表示にします p + theme(axis.text.y = element_blank())
チョコっと出ている黒い目盛り記号を非表示するには、
axis.ticks引数に、element_blank()を指定します。
#軸の指定がないため、両方の軸の目盛り記号が非表示になります。 p + theme(axis.ticks = element_blank(), axis.text.y = element_blank())
主目盛り線を非表示にするには、
scale_y_continuous()やscale_x_continuous()関数の
breaks引数に、NULLを指定します。
#y軸の目盛り線を非表示にします。 p + scale_y_continuous(breaks=NULL)
目盛りに関して、制御できる項目は3か所です。
- 目盛りラベル
- 目盛り記号(黒いチョッとだけで出てる線)
- 目盛り線
軸内の位置指定は、軸が連続値か離散値で指定方法が異なります。
- 連続値:breaksで指定する(非表示にするには、NULLを指定する)
- 離散値:limitsで指定する(非表示にするには、その要素を含めない)
目盛りラベル、目盛り線は、軸ごとに制御可能ですが、
目盛り記号だけは、両軸に適用されてします。
次回は、目盛りラベルのテキストや、軸ラベルのテキストを制御します。
ggplot2を使って、軸を制御する-1
R グラフィックス クックブック 22回目
ggplot2パッケージを利用して、軸を制御していきます。
そもそもデフォルトで、適切な軸を表示してくれますが、
軸ラベルや、目盛りの数、位置を制御することで、見る人の解釈を助けます。
利用するデータ、ベースのグラフ
R: Results from an Experiment on Plant Growthデータセットを使います。
x軸にgroup、y軸にweightをマッピングした箱ひげ図をベースにします。
p <- ggplot(PlantGrowth, aes(x=group,y=weight)) + geom_boxplot() p
x軸とy軸を反転する
散布図は、x軸とy軸にマッピングしている変数を交換すれば良いですが
他の幾何オブジェクトは、交換するとグラフとして成り立ちません。
#箱ひげ図で、x軸とy軸の変数を交換してみる... > ggplot(PlantGrowth, aes(x=weight, y=group)) + + geom_boxplot() Warning messages: 1: position_dodge requires constant width: output may be incorrect 2: position_dodge requires non-overlapping x intervals
マッピングを交換した箱ひげ図…そもそも成り立ちません。
このように、x軸とy軸を同等に扱わないグラフの
x軸とy軸を交換には、coord_flip()を使います。
p + coord_flip()
ベースのグラフは、x軸の左から、"ctrl","trt1","trt2"となっていますが、
交換後のグラフは、y軸の下から、"ctrl","trt1","trt2"となっています。
交換前後で、左から始まりが、下から始まりに変わりました。
左から右へ読んでいたグラフを、下から上へ読むことを許容できれば良いのですが、
出来ない場合は、順序の並び順を制御して、上から始まりに変えられます。
#x軸に対して、並び替えを逆にします。 p + coord_flip() + scale_x_discrete(limits = rev(levels(PlantGrowth$group)))
上から始まりになりました。
連続値の軸の範囲を設定する
x軸やy軸の範囲を設定するには、xlim()やylim()を使います。
#y軸の表示範囲を0から、weightの最大値までにします。 p + ylim(0, max(PlantGrowth$weight))
3.5から6の範囲で表示されていた箱ひげ図を、0から6の範囲で表示になったため
箱がつぶれているように見えます。これでは、データ分布が分からないですね。
上のグラフは、ylim()を使いましたが、scale_y_continuous()も同じです。
#ylim(0, max(PlantGrowth$weight))と同じです。 p + scale_y_continuous(limits = c(0, max(PlantGrowth$weight)))
例えば、ylim()で範囲を設定し、scale_y_continuous()で目盛り線を消す場合など、
ylim()とscale_y_continuous()と同時に使う場合は、注意が必要です。
p + ylim(0,10) + scale_y_continuous(breaks=NULL)
目盛り線が消えていますが、y軸の範囲が設定されていません。
p + scale_y_continuous(breaks=NULL) + ylim(0,10)
y軸の範囲が設定されていますが、目盛り線が消えていません。
両方同時に利用すると、後者の関数だけ適用されます。
これを避けるためには、scale_y_continuous()だけを利用します。
p + scale_y_continuous(limits=c(0, 10), breaks=NULL)
0から10の範囲を設定していますが、目盛り線を消したので分かりません。。。
この範囲指定ですが、範囲外のデータは除去してグラフが作成されます。
#グラフは、weightが5~6.5の値だけが考慮される p + scale_y_continuous(limits=c(5,6.5)) Warning message: Removed 13 rows containing non-finite values (stat_boxplot).
13行除去されているエラーメッセージが出ています。
ylim()やscale_y_continuous()を使って、範囲を狭める場合、
範囲外のデータは除去されるため、グラフにズームインすることはできません。
データを除去せず、ズームイン・アウトする場合は、coord_cartesian()を使います。
#データは除去されず、5~6.5の範囲に寄る p + coord_cartesian(ylim = c(5,6.5))
最後に、片方向のみに範囲を拡張するには、expand_limits()を使います。
p + expand_limits(y=0)
expand_limits()ですが、拡張のため範囲を狭める関数ではありません。
そのため、データが存在するポイントを指定しても無視された感じで動きます。
#そもそもどこを基準に、y=5に拡張しているのか分からないですが、、、 p + expand_limits(y=5)
連続値を逆転する
ベースのグラフは、下から上に向けて、数値が大きくなっていきますが、
上から下に向けて、数値を大きくします。
読みづらい気もしますが、逆転するためには、scale_y_reverse()を使います。
p + scale_y_reverse()
ylim()の引数で、上限値~下限値の順で指定すると、同様の結果が得られます。
p + ylim(6.5, 3.5)
軸を逆転して、範囲も設定する場合は、scale_y_reverse()のlimits引数を指定します。
#範囲外のデータは除去されることに注意です p + scale_y_reverse(limits=c(5,3)) Removed 17 rows containing non-finite values (stat_boxplot).
離散値軸の順番を変更する
ベースのグラフのx軸は、左から"ctrl","trt1","trt2"となっています。
この並びを変更するためには、scale_x_discrete()を使います。
p + scale_x_discrete(limits=c("trt1","ctrl","trt2"))
このscale_x_discrete()ですが、一部の要素だけを図に表示することもできます。
#ctrl列を除きます p + scale_x_discrete(limits=c("trt1","trt2"))
今回は、軸の入れ替えや逆転、範囲などを制御しました。
次回は、スケール比や、目盛り軸を制御します。
ggplot2を使って、注釈を入れる-2
R グラフィックス クックブック 21回目
ggplot2パッケージを利用して、図内に注釈を入れます。
前回の記事で、annotate()を使ってテキストや線分、網掛けや
gridパッケージを使って矢印を、図内にプロットしました。
mukkujohn.hatenablog.com
今回は、色をあえて変えることでの強調表示やエラーバー - Wikipediaを扱います。
強調表示
こちらのデータセットを使います。
R: Results from an Experiment on Plant Growth
> str(PlantGrowth) 'data.frame': 30 obs. of 2 variables: $ weight: num 4.17 5.58 5.18 6.11 4.5 4.61 5.17 4.53 5.33 5.14 ... $ group : Factor w/ 3 levels "ctrl","trt1",..: 1 1 1 1 1 1 1 1 1 1 ...
強調表示を行う下準備として、group列の値が"trt1"である事を示す列を追加します。
pg <- PlantGrowth pg$h1 <- "no" pg$h1[pg$group=="trt1"] <- "yes" > str(pg) 'data.frame': 30 obs. of 3 variables: $ weight: num 4.17 5.58 5.18 6.11 4.5 4.61 5.17 4.53 5.33 5.14 ... $ group : Factor w/ 3 levels "ctrl","trt1",..: 1 1 1 1 1 1 1 1 1 1 ... $ h1 : chr "no" "no" "no" "no" ...
h1列でグループ化した箱ひげ図をプロットします。
p <- ggplot(pg,aes(x=group,y=weight,fill=h1)) + geom_boxplot() p
このグラフですと、どのグループの箱を見れば良いか分かりません。
そこであえて、塗りつぶしの色を手動で設定することで、
目につく箱を指定します。
手動で塗りつぶし色を指定するためには、scale_fill_manual()を使います。
#yes or no の2つの値であるh1をfillにマッピングしているため、 #塗りつぶし色も2色を指定する p + scale_fill_manual(values=c("grey85","#FFDDCC"))
3levelsのgroup列をfillにマッピングした場合は、
scale_fill_manual()で3色指定します。
ggplot(PlantGrowth,aes(x=group,y=weight,fill=group)) + geom_boxplot() + scale_fill_manual(values=c("grey85","lightblue","#FFDDCC"))
levels数より多く指定しても、多い部分は無視されて図がプロットされます。
逆にlevels数に満たない場合はエラーになります。
Error: Insufficient values in manual scale. 3 needed but only 1 provided.
エラーバー
こちらのデータから、Cultivarがc39であるデータセットを使います。
> str(cabbage_exp) 'data.frame': 6 obs. of 6 variables: $ Cultivar: Factor w/ 2 levels "c39","c52": 1 1 1 2 2 2 $ Date : Factor w/ 3 levels "d16","d20","d21": 1 2 3 1 2 3 $ Weight : num 3.18 2.8 2.74 2.26 3.11 1.47 $ sd : num 0.957 0.279 0.983 0.445 0.791 ... $ n : int 10 10 10 10 10 10 $ se : num 0.3025 0.0882 0.311 0.1408 0.2501 ...
subset()を使って、条件に合致するデータだけ選択・取得します。
ce <- subset(cabbage_exp, Cultivar == "c39")
棒グラフを作成します。
ggplot(ce, aes(x=Date,y=Weight)) + geom_bar(fill="white",colour="black",stat = "identity")
上のグラフにエラーバーを追加しますが、
データセット内に、平均の標準偏差であるse列があるため、
この値を、geom_errorbar()を使って、追加します。
#y軸に対して、開始値:ymin~終了値:ymaxとして指定します。 #widthは、エラーバーの幅です。良さげな値を模索して指定します。 上のグラフ + geom_errorbar(aes(ymin=Weight-se,ymax=Weight+se),width=.2)
折れ線グラフでも同様です。
#折れ線→マーク→エラーバーの順でプロットしてます。 ggplot(ce, aes(x=Date,y=Weight)) + geom_line(aes(group=1)) + geom_point(size=4) + geom_errorbar(aes(ymin=Weight-se,ymax=Weight+se),width=.2)
このエラーバーですが、グループ化された棒グラフや折れ線グラフの場合、
pisitionを横にずらす必要があります。
ずらさないと、エラーバーがどちらのグループのバーか分かりません。
エラーバーをずらす場合は、geom_errorbar()内で
positionを指定します。
ggplot(cabbage_exp, aes(x=Date,y=Weight,fill=Cultivar)) + geom_bar(position="dodge",stat="identity")+ geom_errorbar(aes(ymin=Weight-se,ymax=Weight+se), position = position_dodge(.9),width=.2)
折れ線グラフ
#複数回利用するため、オブジェクトに格納 pd <- position_dodge(.3) #エラーバー → 折れ線 → マークの順にプロット ggplot(cabbage_exp,aes(x=Date,y=Weight,colour=Cultivar,group=Cultivar))+ geom_errorbar(aes(ymin=Weight-se,ymax=Weight+se), width=.2,size=.25,colour="black",position=pd)+ geom_line(position=pd)+ geom_point(position=pd,size=2.5)
ファセット
各ファセットに注釈を入れていきます。
mpg. ggplot2 2.1.0データセットを使います。
> str(mpg) 'data.frame': 234 obs. of 11 variables: $ manufacturer: Factor w/ 15 levels "audi","chevrolet",..: 1 1 1 1 1 1 1 1 1 1 ... $ model : Factor w/ 38 levels "4runner 4wd",..: 2 2 2 2 2 2 2 3 3 3 ... $ displ : num 1.8 1.8 2 2 2.8 2.8 3.1 1.8 1.8 2 ... $ year : int 1999 1999 2008 2008 1999 1999 2008 1999 1999 2008 ... $ cyl : int 4 4 4 4 6 6 6 4 4 4 ... $ trans : Factor w/ 10 levels "auto(av)","auto(l3)",..: 4 9 10 1 4 9 1 9 4 10 ... $ drv : Factor w/ 3 levels "4","f","r": 2 2 2 2 2 2 2 1 1 1 ... $ cty : int 18 21 20 21 16 18 18 18 16 20 ... $ hwy : int 29 29 31 30 26 26 27 26 25 28 ... $ fl : Factor w/ 5 levels "c","d","e","p",..: 4 4 4 4 4 4 4 4 4 4 ... $ class : Factor w/ 7 levels "2seater","compact",..: 2 2 2 2 2 2 2 2 2 2 ...
この形でマッピングします。
- x軸:displ-ピストンが動ける容積(リットルで表現)
- y軸:hwy-ガロンあたり走れる距離(マイルで表現)(高速で実験)
- ファセット:drv-駆動方式
まずは、上記のマッピングでプロットします。
p <- ggplot(mpg, aes(x=displ,y=hwy)) + geom_point() + facet_grid(. ~ drv) p
各ファセットに注釈を追加するには、
geom_text()と注釈用のデータフレームを使います。
#上のグラフは、drvでファセットにしているので #「drv」という列名と値を合わせる必要があります。 f_labels <- data.frame(drv = c("4","f","r"), label = c("4wd","Front","Rear")) > f_labels drv label 1 4 4wd 2 f Front 3 r Rear p + geom_text(x=6, y=40,aes(label=label),data=f_labels)
ファセットに指定した"drv"列の値と
注釈用データフレームの"drv"列の値が一致させる必要があります。
一致していないとこんなグラフになってしまいます。
#あえて、FFを指定して、一致させないようにしています。 ng_lables <- data.frame(drv=c("4","FF","r"), label = c("4wd","Front","Rear")) p + geom_text(x=6, y=40,aes(label=label),data=ng_lables)
注釈に使うデータフレームですが、ファセットに指定した列以外に、
複数の列を用意して、geom_text()を複数回指定できます。
#この様に、drv列以外に、formula列とr2列を用意します > labels drv formula r2 1 4 italic(y) == 30.68 -2.88 * italic(x) italic(R^2) == 0.65 2 f italic(y) == 37.38 -3.60 * italic(x) italic(R^2) == 0.36 3 r italic(y) == 25.78 -0.92 * italic(x) italic(R^2) == 0.04 #回帰式を引いて p + geom_smooth(method=lm,se=FALSE)+ #formula列の値を数式として追加して geom_text(x=3,y=40,aes(label=formula), data=labels,parse = TRUE,hjust=0) + #r2列の値も数式として追加します geom_text(x=3,y=35,aes(label=r2), data=labels,parse = TRUE,hjust=0)
geom_text()を使って注釈を追加しましたが、
annotate()を使うとどうなるか確認してみます。
#テキスト p + annotate("text",x=6,y=42,label="label text")
#線分 p + annotate("segment",x = 3,xend = 6,y=30,yend=40)
#網掛け p + annotate("rect",xmin = 3,xmax = 6,ymin=30,ymax=40, fill="lightblue",alpha=.3)
annotate()を使うと全ての図に同じ内容が適用されますね。
前回の記事では、geom_text()を使うと、データの数だけプロットされました。
ファセットの場合は、geom_text()とデータフレームの組み合わせが正しいようです。
注釈を入れるのは、この記事で終わりです。
次回の記事からは、軸を制御する方法を扱っていきます。
ggplot2を使って、注釈を入れる-1
R グラフィックス クックブック 20回目
ggplot2パッケージを利用して、図内に注釈を入れます。
注釈
データの解釈をサポートするために、図内に注釈を入れるのですが、
注釈自体は、いろいろあります。
- テキスト(文字列、数式)
- 線(線分、矢印)
- 網掛け
- 強調
- エラーバー
これらを、1個ずつ取り上げます。
最後にファセットグリッドで、グループ化された全ての図に
注釈を入れる方法を取り上げます。
テキスト(文字列、数式)
annotate()を使います。
第1引数に、textを指定します。
まずは、注釈を入れる図を用意します。
データセットはR: Old Faithful Geyser Dataを使います。
p <- ggplot(faithful, aes(x=eruptions, y=waiting)) + geom_point() p
文字列の注釈を入れます。
#注釈を入れる位置を、x軸/y軸の値で指定します。 #文字列は、label引数に指定します。 p + annotate("text", x=3, y=48, label="Group 1") + annotate("text", x=4.5, y=65, label="Group 2")
x軸/y軸が、連続値の場合は、Infを用いて、
図のコーナーに文字列を配置することができます。
コーナーに配置する場合は、hjustやvjustで調整する必要があります。
p + annotate("text",x=-Inf,y=Inf,label="Upper Left",hjust=-.2,vjust=2) + annotate("text",x=mean(range(faithful$eruptions)),y=-Inf,label="Bottom Middle",vjust=-.4)
注釈文字列のフォントや斜体、色やサイズも指定できます。
p + annotate("text", x=3, y=48, label="Group 1", family="serif",fontface="italic",colour="darkred",size=3) + annotate("text", x=4.5, y=65, label="Group 2", family="serif",fontface="italic",colour="blue",size=10)
文字列を注釈に入れる際には、geom_text()は使わない方が良いです。
geom_text()は、データの数だけ、繰り返し実行されてしまいます。
#Group 2の文字列がオーバープロットです。 #透過を0.1に指定していますが、 #透過が分からないくらい重ねてプロットされています。 p + annotate("text", x=3, y=48, label="Group 1", family="serif",fontface="italic",colour="darkred",size=10) + geom_text(x=4.5,y=65,label="Group 2", alpha=.1)
文字列に数式表現を使う場合は、parse引数に、TRUEを指定します。
p <- ggplot(data.frame(x=c(-3,3)),aes(x=x)) + stat_function(fun = dnorm) #parse=TRUEで、labelが数式表現であることを指定します。 p + annotate("text", x=2, y=0.3, parse=TRUE, label="frac(1,sqrt(2 * pi)) * e ^ {-x^2 / 2}")
数式表現内で、プレーンテキストを使う場合は、プレーンテキスト部分を
シングルクォーテーションでくくります。
#Function: 部分がプレーンテキストです。 p + annotate("text", x=2, y=0.3, parse=TRUE, label="'Function: ' * y==frac(1,sqrt(2 * pi)) * e ^ {-x^2 / 2}")
線(線分、矢印)
線により使う関数が異なります。
- 水平線:geom_hline()
- 垂直線:geom_vline()
- 傾きがある線:geom_abline()
このデータセットを使います。
R: Risk Factors Associated with Low Infant Birth Weight
グループ化に用いる列をファクタにして、ラベルを設定します。
birthwt1 <- birthwt birthwt1$smoke <- factor(birthwt1$smoke) birthwt1$smoke <- revalue(birthwt1$smoke, c("0"="No Smoke","1"="Smoke"))
まずは、注釈なしでプロットします。
p <- ggplot(birthwt1, aes(x=age,y=bwt,colour=smoke)) + geom_point() p
水平線と、垂直線を追加します。
#線を引く位置を、水平線ならy軸の値、垂直線ならx軸の値で指定します。 p + geom_hline(yintercept=2000) + geom_vline(xintercept=20)
傾きのある線を追加します。
#y=slope * 100 + interceptの傾きのある線を図示します。 p + geom_abline(intercept=500,slope=100)
別途、算出した値の線を追加することもできます。
グループ化している項目ごとに、平均値を算出します。
library(plyr) bw_means <- ddply(birthwt1,"smoke",summarise,bwt=mean(bwt)) bw_means smoke bwt 1 No Smoke 3055.696 2 Smoke 2771.919
上で算出した、グループ化項目と平均値のデータフレームを
水平線に設定します。
p + geom_hline(aes(yintercept=bwt,colour=smoke),data=bw_means, linetype="dashed",size=1)
軸が離散値の場合は、ファクタのレベルを指定することで
水平線、垂直線を追加できます。
x軸が離散値の図を、サンプルに使います。
pb <- ggplot(birthwt1,aes(x=smoke,y=bwt)) + geom_point() pb
離散値としているsmoke列は、ファクタで、
1つ目のNo Smokeのレベルは1、2つ目のSmokeのレベルは2となっています。
> str(birthwt1$smoke) Factor w/ 2 levels "No Smoke","Smoke": 1 1 2 2 2 1 1 1 2 2 ...
ファクタのレベルを指定することで、線を引くことができます。
#ファクタのレベルを数値で指定します。 pb + geom_vline(xintercept=2)
上は、ファクタのレベルを数値で指定しましたが、
which(levels())を用いることで、名称から指定することもできます。
pb + geom_vline(xintercept = which(levels(birthwt1$smoke)=="No Smoke"))
今までは「線」を扱ってきましたが、ここからは「線分」を追加していきます。
線分は、annotate()を使い、引数に、"segment"を指定します。
この図を使います。
線分を追加するには、x軸の開始値と終了値、y軸の開始値と終了値を指定します。
#x軸は、x~xendで指定します。 #y軸は、y~yendで指定します。 上のグラフ + annotate("segment", x=1950,xend=1980, y=-.25,yend=0.25, colour="blue", size=3)
矢印や、線分の両端をT字にするためには、gridパッケージのallow()を使います。
library(grid) #矢印はarrow() p + annotate("segment",x=1850,xend=1820,y=-.8,yend=-.95,colour="blue", size=2,arrow=arrow())+ #両端がT字にするには、ends引数を指定します。 annotate("segment",x=1950,xend=1980,y=-.25,yend=-.25, arrow=arrow(ends = "both",angle = 90,length = unit(.2,"cm")))
網掛け
annotate()を使います。引数は、rectです。
範囲の指定が、線分とちょっと異なります。
#x軸は、xmin~xmaxで指定します #y軸は、ymin~ymaxで指定します p + annotate("rect",xmin=1950,xmax=1980,ymin=-1,ymax=1, alpha=.1,fill="blue") + annotate("rect",xmin=1800,xmax=2000,ymin=-1,ymax=-.5, alpha=.1,fill="green")
今までの注釈は、端から端までの線を除き、全てannotate()を使っています。
- 文字列:annotate("text",~)
- 線分:annotate("segment",~)
- 網掛け:annotate("rect",~)
注意点は、データの数だけプロットされるgeom_text()を使わないことです。
次回は、強調表示とエラーバー、グリッドで分割された図を扱います。