ggplot2 を用いたパブリッシュ出来る品質のグラフィックスの作成
概要
講義: 60 分
演習: 20 分質問
R でパブリッシュ出来る品質のグラフィックを作成するにはどうすればよいですか?
目標
ggplot2 を用いたパブリッシュ可能なグラフィックスの生成
ジオメトリ(点、線などの形状)、エステティック(審美)、および統計のレイヤーを ggplot プロットに適用出来るようになりましょう。
様々な色、形、線を用いた、プロットの審美面の操作が出来るようになりましょう。
スケール変換とグループ化による、より良いデータ視覚化が出来るようになりましょう。
ggplot で作成したプロットのディスク保存が出来るようになりましょう。
データをプロットすることは、データとその変数間の様々な関係をクイックに探索する最良の方法の一つです。
Rには、主に3つのプロットシステムがあります。 R組み込みplot関数、 lattice パッケージ、ggplot2 パッケージです。
今回、私たちはggplot2パッケージについて学んでいきます。 なぜなら、ggplot2パッケージは出版品質並のグラフィック作成に最も効果的だからです。
ggplot2はthe grammar of graphics(グラフィックス文法)に基づいており、 一貫した構成記述体系(データセット、座標系、そして一連の配置)でプロットを 表現することができます。
ggplot2を理解するための鍵は、レイヤーについて考えることです。 このアイディアは、Photoshop、Illustrator、Inkscapeなどの画像編集ソフトを使用する場面でお馴染みかもしれません。
それでは、例題から始めましょう。:
library("ggplot2")
ggplot(data = gapminder, aes(x = gdpPercap, y = lifeExp)) +
geom_point()
最初に行うことはggplot
関数を呼び出すことです。
この関数は、新しいプロットを作成していることをRに知らせます。
ggplot
関数に与える引数は、いずれもそのプロットのグローバルオプションであり、すべてのレイヤーに適用されます。
ggplotに2つの引数を渡しました。
一つ目の引数は、ggplot
に、どのデータを図に表示するかを示します。この例は、前に読み込んだgapminderデータです。
二つ目の引数には、aes
関数を渡しました。
この関数は、データの変数が図のエステティック属性にどのようにマッピングされるかggplot
に指示します。
この場合では、x とyを指定しています。
ここでは、ggplot
に対して、x軸にgapminderデータフレームの“gdpPercap”列を、
y軸には“lifeExp”列をプロットするように指示しました。
ggplot
がその列のデータを調べるのに十分な知識を持っているため、これらの列に明示的にaes
を渡す必要はありません。
(例えばx = gapminder [、 "gdpPercap"]
など。)
以下のように、ggplotを呼び出すだけでは図を描くことはできません。
ggplot(data = gapminder, aes(x = gdpPercap, y = lifeExp))
ggplot
にデータを視覚的に表現する方法を指示する必要があります。
これは新しいgeomレイヤを追加することで行います。
この例では、geom_point
を使用しました。
これはggplot
に点の散布図としてxとyの関係を視覚的に表現するように指示します。
ggplot(data = gapminder, aes(x = gdpPercap, y = lifeExp)) +
geom_point()
チャレンジ1
次の例を変更して、時間とともに平均余命がどのように変化しているかを図示して下さい。 changed over time:
ggplot(data = gapminder, aes(x = gdpPercap, y = lifeExp)) + geom_point()
ヒント:gapminderデータセットには「year」という列がありますので、 「year」列をx軸に指定して下さい。
チャレンジ1の回答例
これは1つの回答例です。:
ggplot(data = gapminder, aes(x = year, y = lifeExp)) + geom_point()
チャレンジ 2
先の例題とチャレンジでは、
aes
関数を使用して、各点のxとyの位置について散布図geomを指定しました。 修正できるもう1つのエステティック属性は、点の色です。 先のチャレンジのコードを修正して、“continent” 列で点に色付けして下さい。 データにどはどのような傾向が見られますか? それらの傾向は、あなたが期待したものですか?チャレンジ 2の回答例
先の例題とチャレンジでは、
aes
関数を使用して、各点のxとyの位置について散布図geomを指定しました。 修正できるもう1つのエステティック属性は、点の色です。 先のチャレンジのコードを修正して、“continent” 列で点に色付けして下さい。 データにどはどのような傾向が見られますか? それらの傾向は、あなたが期待したものですか?ggplot(data = gapminder, aes(x = year, y = lifeExp, color=continent)) + geom_point()
レイヤー
散布図を使用することは、時間経過による変化を視覚化するのに、おそらく最適ではありません。 代わりに、データを線グラフとして可視化するようggplotに指示しましょう。
ggplot(data = gapminder, aes(x=year, y=lifeExp, by=country, color=continent)) +
geom_line()
geom_point
レイヤーを追加する代わりに、geom_line
レイヤーを追加しました。
*by**エステティックを追加し、各国ごとに線を描くようggplot
に指示します。
しかし、線と点の両方をプロット上に視覚化したい場合はどうすればよいでしょうか? プロットに別のレイヤーを追加するだけです。
ggplot(data = gapminder, aes(x=year, y=lifeExp, by=country, color=continent)) +
geom_line() + geom_point()
各レイヤーは、前のレイヤーの上に描画されることに注意することが重要です。 この例では、点は線の上に描画されています。これはデモです。
ggplot(data = gapminder, aes(x=year, y=lifeExp, by=country)) +
geom_line(aes(color=continent)) + geom_point()
この例では、colorエステティックマッピングが、ggplot
のグローバルプロットオプションからgeom_line
レイヤーに移動されたため、
点には色が適用されなくなりました。
これで、点が線の上に描画されていることがわかります。
ヒント:エステティック属性に、マッピングの代わりに値を設定する
これまでは、データの変数のマッピングとしてエステティック属性(colorなど)を使用する方法を見てきました。たとえば、
geom_line(aes(color = continent))
を使用すると、ggplot
は各大陸に異なる色を与えます。 しかし、すべての線の色を青に変更したい場合はどうすればよいでしょうか? ‘geom_line(aes(color = “blue”))’で動作すると思うかもしれませんが、そうではありません。 特定の変数へのマッピングを作成したくないので、geom_line(color="blue")
のようにaes()
関数を除いて色の指定をします。
チャレンジ3
先の例の点と線のレイヤーの順序を入れ替えてみましょう。何が起こりますか?
チャレンジ 3の回答例
先の例の点と線のレイヤーの順序を入れ替えてみましょう。何が起こりますか?
ggplot(data = gapminder, aes(x=year, y=lifeExp, by=country)) + geom_point() + geom_line(aes(color=continent))
The lines now get drawn over the points!
変換と統計
ggplot2を使用すると、統計モデルをデータに適用することが容易になります。 デモのために、最初の例に戻ります。
ggplot(data = gapminder, aes(x = gdpPercap, y = lifeExp, color=continent)) +
geom_point()
現在、1人当たりGDPのいくつかの強い外れ値により、点と点の関係性を見ることが難しくなっています。 scale関数を用いて、x軸上の単位のスケールを変更することができます。 これらは、データの値とエステティックな視覚的値との間のマッピングを制御します。 また、alpha関数を使用して点の透明度を変更することができます。 これは、大量のデータが非常に密集している場合、特に役立ちます。
ggplot(data = gapminder, aes(x = gdpPercap, y = lifeExp)) +
geom_point(alpha = 0.5) + scale_x_log10()
gdpPercap列の値をプロットに描画する前に、log10
関数による変換を適用したので、
10の各倍数は変換されたスケールの1の増加に対応します。
例えば、1人当たりGDPの値1,000はy軸の3、10,000はy軸の4に対応します。
これにより、x軸上のデータの広がりを視覚化することが容易になります。
ヒントのリマインダ:エステティック属性に、マッピングの代わりに値を設定する
geom_point(alpha = 0.5)
を使用したことに注目してください。 先のヒントで触れたように、aes()
関数以外の設定を使用すると、この値がすべての点で使用されます。 この場合、この値が必要です。しかし、他のエステティック設定と同様に、alphaはデータ内の変数にマッピングすることもできます。 たとえば、geom_point(aes(alpha = continent))
を使用して、各大陸に異なる透明度を与えることができます。
geom_smooth
という別のレイヤーを追加することで、データに単純な関係を当てはめることができます。
ggplot(data = gapminder, aes(x = gdpPercap, y = lifeExp)) +
geom_point() + scale_x_log10() + geom_smooth(method="lm")
geom_smooth
レイヤーでsizeエステティック属性を設定することによって、
線を太くすることができます。
ggplot(data = gapminder, aes(x = gdpPercap, y = lifeExp)) +
geom_point() + scale_x_log10() + geom_smooth(method="lm", size=1.5)
エステティック属性を指定する方法は2つあります。
ここでは、sizeエステティック属性の設定を’geom_smooth’の引数として渡しています。
これまでのレッスンでは、データの変数とその視覚表現の間のマッピングを定義するためにaes
関数を使用しました。
チャレンジ 4a
前の例を用いて、点レイヤー上の点の色とサイズを変更して下さい。
ヒント:’aes’関数を使用しないでください。
チャレンジ 4aの回答例
前の例を用いて、点レイヤー上の点の色とサイズを変更して下さい。
ヒント:’aes’関数を使用しないでください。
ggplot(data = gapminder, aes(x = gdpPercap, y = lifeExp)) + geom_point(size=3, color="orange") + scale_x_log10() + geom_smooth(method="lm", size=1.5)
チャレンジ 4b
点を異なる形にし、また大陸毎に色分けと傾向線の描画をするために、 チャレンジ4aの回答を変更して下さい。 ヒント:color引数は、aes関数内で使用することができます。
チャレンジ 4bの回答例
点を異なる形にし、また大陸毎に色分けと傾向線の描画をするために、 チャレンジ4aの回答を変更して下さい。
ヒント:color引数は、aes関数内で使用することができます。
ggplot(data = gapminder, aes(x = gdpPercap, y = lifeExp, color = continent)) + geom_point(size=3, shape=17) + scale_x_log10() + geom_smooth(method="lm", size=1.5)
複数パネルの図
先の例では、すべての国の平均余命の変化を1つのプロットで視覚化しました。 一方、facetパネルのレイヤーを追加することで、複数のパネルに分割することができます。 名前が“A”または“Z”で始まる国にのみ焦点を当てます。
ヒント
データのサブセットからスタートします。
substr
関数を使って文字列の一部を抜き出します。 この場合、gapminder$country
ベクトルのstart
からstop
の位置にある文字が抜き出されます。 演算子%in%
では、長いサブセット条件を書き出すのではなく、複数の比較を行うことができます。 (この場合、starts.with %in% c("A", "Z")
はstarts.with == "A" | starts.with == "Z"
です。)
starts.with <- substr(gapminder$country, start = 1, stop = 1)
az.countries <- gapminder[starts.with %in% c("A", "Z"), ]
ggplot(data = az.countries, aes(x = year, y = lifeExp, color=continent)) +
geom_line() + facet_wrap( ~ country)
facet_wrap
レイヤーは引数として“formula”をとり、チルダ(~)で表記されます。
これは、gapminderデータセットのcountry列にある各々の一意な値のパネルを描画するようRに指示します。
テキストの変更
分析結果の発表に向けてこの図を整理するにあたり、いくつかのテキスト要素を変更する必要があります。 x軸はあまりにも雑然としており、y軸はデータフレームの列名ではなく、“Life expectancy”と読み替えるべきです。
これを行うには、いくつかのレイヤーを追加する必要があります。
theme レイヤーは、軸テキストと全体のテキストサイズを制御します。
軸、プロットタイトル、および任意の凡例のラベルは、labs
関数を使用して設定できます。
凡例のタイトルは、aes
関数で使用したものと同じ名前を設定します。
したがって、color凡例のタイトルはcolor = "Continent"
を用いて設定され、
fill凡例のタイトルはfill = "任意のタイトル"
を使用して設定されます。
ggplot(data = az.countries, aes(x = year, y = lifeExp, color=continent)) +
geom_line() + facet_wrap( ~ country) +
labs(
x = "Year", # x axis title
y = "Life expectancy", # y axis title
title = "Figure 1", # main title of figure
color = "Continent" # title of legend
) +
theme(axis.text.x=element_blank(), axis.ticks.x=element_blank())
プロットのエクスポート
ggsave()
関数を使用すると、ggplotで作成したプロットをエクスポートすることができます。
出版、公開のための高品質グラフィックを作成するために、
適切な引数(width
、height
、およびdpi
)を調整してプロットの寸法と解像度を指定できます。
上記のように、そのプロットを保存するには、最初にそのプロットを変数lifeExp_plot
に割り当て、
ggsave
にそのプロットをpng
形式でresults
というディレクトリに保存するよう指示します。
(作業ディレクトリに’results /’フォルダがあることを確認してください。)
lifeExp_plot <- ggplot(data = az.countries, aes(x = year, y = lifeExp, color=continent)) +
geom_line() + facet_wrap( ~ country) +
labs(
x = "Year", # x axis title
y = "Life expectancy", # y axis title
title = "Figure 1", # main title of figure
color = "Continent" # title of legend
) +
theme(axis.text.x=element_blank(), axis.ticks.x=element_blank())
ggsave(filename = "results/lifeExp.png", plot = lifeExp_plot, width = 12, height = 10, dpi = 300, units = "cm")
Error in grDevices::dev.off(): QuartzBitmap_Output - unable to open file 'results/lifeExp.png'
ggsave
には素晴らしい点が二つあります。
一つ目は、最後のプロットがデフォルトになるので、plot
引数を省略すると、ggplot
で作成した最後のプロットが自動的に保存されることです。
二つ目は、ファイル名に指定したファイル拡張子(例:.png
または.pdf
)からプロットを保存するフォーマットを決定しようとします。
必要な場合は、device
引数に明示的にフォーマットを指定できます。
これまで学んできたことは、ggplot2でできることの一部です。 RStudioは、利用可能な様々なレイヤーについて、とても便利なチートシートを提供しています。 更なる詳細なドキュメントは、ggplot2のwebサイトで入手できます。 最後に、何を変更すればよいかわからない場合、Google検索を実行してみて下さい。 大抵の場合、Stack Overflow(スタックオーバーフロー)上で適切な質問と回答が、再利用可能なコードと共に見つかります!
チャレンジ5
大陸で塗りつぶされた、1人当たりGDPの密度プロットを作成して下さい。
上級編
- データの広がりをより良く視覚化するためにx軸を変換して下さい。
- 1年毎の密度プロットをパネルに追加して下さい。
チャレンジ 5の回答例
大陸で塗りつぶされた、1人当たりGDPの密度プロットを作成して下さい。
上級編
- データの広がりをより良く視覚化するためにx軸を変換して下さい。
- 1年毎の密度プロットをパネルに追加して下さい。
ggplot(data = gapminder, aes(x = gdpPercap, fill=continent)) + geom_density(alpha=0.6) + facet_wrap( ~ year) + scale_x_log10()
まとめ
プロットを作成するために
ggplot2
を用いますエステティック、ジオメトリ、統計、スケール変換、グループ化など、レイヤー単位でグラフィックスを考えてみましょう。