読者です 読者をやめる 読者になる 読者になる

Data Science by R and Python

統計学を、広く、深く、わかりやすく。

(第1回)Rを使ったグラフィック -ggplot2-

今日のテーマはRのグラフィック

Rといえば、統計解析のソフトウェアという印象が強く、回帰・判別などいろんな手法を使えるソフトウェアとして認識されています。でも、それだけではありません。グラフィックにも強みがあります。plot関数をはじめ、histogramなどもさくっと作ることができます。

ggplot2という美しい図を描くためのパッケージ

さて、そんなRにはggplot2というパッケージがあります。ggplot2は、「The Grammar of Graphics」に沿っていて、複雑なグラフを一貫したルールのもとで容易に記述することができるようになります。具体的に見ていきましょう。今回は、R言語上級ハンドブックに基づいて、ggplot2の使い方などをまとめていきます。

ggplot2の中にあるグラフを作成するためのツール

library(ggplot2)には、ggplot関数とqplot関数の2つが存在しています。qplot関数はplotに似た書き方ができて、簡単にグラフを書くことができます。まずは定番のiris(アヤメ)のデータを可視化します。

qplotを用いた可視化

library(qqplot2)
library(gridExtra)

#simple method
p1=qplot(Sepal.Width,Sepal.Length,data=iris)
p2=qplot(Sepal.Width,Sepal.Length,facets=~Species,data=iris)
p3=qplot(Sepal.Width,Sepal.Length,colour=Species,data=iris)
grid.arrange(p1,p2,p3,nrow=1)

f:id:tomoshige_n:20140802232722p:plain

ggplotを用いた可視化

#complecated method
p1=ggplot(data=iris,aes(x=Sepal.Width,y=Sepal.Length))+geom_point()
p2=ggplot(data=iris,aes(x=Sepal.Width,y=Sepal.Length))+geom_point()+facet_wrap(~Species)
p3=ggplot(data=iris,aes(x=Sepal.Width,y=Sepal.Length,colour=Species))+geom_point()
grid.arrange(p1,p2,p3,nrow=1)

この結果は上の図と同じものになります。

ggplot2のグラフィックス構成要素

「ggplot2」グラフィックオブジェクトは階層構造を持つ構成要素でできています。「ggplot」関数の呼び出しによって、「ggplot」オブジェクト生成されます。その構成要素は以下の通り。それぞれについて詳しくは述べません。知りたい方はggplot2のパッケージの説明を読んでもらうと良いかと思います。

> g=ggplot()
> class(g)
[1] "gg"     "ggplot"
> names(g)
[1] "data"        "layers"      "scales"      "mapping"     "theme"       "coordinates"
[7] "facet"       "plot_env"    "labels"

レイヤー

「ggplot2」はレイヤーという概念を持っています。1つのグラフは、1つ以上のレイヤーの集合と考えます。レイヤーの構成要素は次のようなものです。

  • data:レイヤーの描画対象となるデータ
  • mapping:変数と視覚的要素のマッピング
  • geom:グラフの種類(散布図・棒グラフなど)
  • stat:統計処理の方法
  • position:描画要素の位置指定

レイヤーは、通常「geom_*」, 「stat_*」関数によって作成されます。実際、これらの関数は内部でlayer関数を呼び出して処理をします。では、その大元になっているlayer関数ってどんなものでしょうか?以下のコマンドを打ってみるとわかります。

#layer
#レイヤーの作成
lay1=layer(data=mtcars,mapping=aes(x=factor(cyl),y=drat),geom="point",stat="identity",position="identity")

#レイヤーの内容
lay1

mapping: x = factor(cyl), y = drat 
geom_point:  
stat_identity:  
position_identity: (width = NULL, height = NULL)

#レイヤーを保存
p1=ggplot()+lay1

#別のレイヤーを作成
lay2=layer(data=mtcars,mapping=aes(x=factor(cyl),y=drat),geom="boxplot",stat="boxplot",position="identity",geom_param=list(colour="red"))

#2つのレイヤーを重ねて書いてみる
p2=ggplot()+lay2+lay1
grid.arrange(p1,p2,nrow=1)
<||
[f:id:tomoshige_n:20140803001007p:plain]


実際、geom_*関数や、stat_*関数は適当な既定値が設定されています。実際に用いる場合には、描画したいグラフの種類や行いたい統計処理に応じてこれらの関数を呼び出すことになります。

* データ
各レイヤーは、描画の対象となるデータを持つ必要があります。それぞれのレイヤーにデータが与えられない場合には、「ggplot」関数に与えられたデータが使われることになります。データはデータフレームとして与えます。
>||
> head(lay1$data)
                   mpg cyl disp  hp drat    wt  qsec vs am gear carb
Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1

データの変数と視覚的マッピング(「aes」関数)

各レイヤーはデータの変数と視覚的要素のマッピングを保持しています。

> lay1$mapping
List of 2
 $ x: language factor(cyl)
 $ y: symbol drat

データの変数と視覚的要素のマッピングを指定するには「aes」関数などを使用します。視覚的要素とは例えば、x軸上の位置、y軸上の位置、色・塗り、点の形、大きさなどが該当します。必要となる視覚的要素は、各レイヤーのグラフの種類(geom)、および、統計処理(stat)に依存します。各レイヤーに対してマッピングが与えられない場合は、「ggplot」関数に渡されたマッピングが使われます

グラフの種類の選択:「geom_*」関数

「geom_*」関数はグラフのタイプを指定して、レイヤーを作成します。通常は「geom_*」関数には適切な統計処理が設定されています。が、もし必要なら自分で統計処理を設定することもできます。具体例を見ていきましょう。

#点プロットを行う
p1=ggplot(iris,aes(x=Sepal.Width,y=Sepal.Length))+geom_point()
#loessで平滑曲線を描く
p2=ggplot(iris,aes(x=Sepal.Width,y=Sepal.Length))+geom_smooth()
#平均値をbarで表示する
p3=ggplot(iris,aes(x=Species,y=Sepal.Length))+geom_bar(stat="summary",fun.y=mean)
#プロット
grid.arrange(p1,p2,p3,nrow=1)

f:id:tomoshige_n:20140803003436p:plain

統計処理の選択:「stat_*」関数

「stat_*」関数は統計処理を指定してレイヤーを作成する関数です。それぞれの「geom_*」関数には既定の統計処理が与えられていたように、「stat_*」関数では既定のグラフの種類が与えられていますが、自分でグラフを選択することもできます。具体的な例を説明しましょう。

#xの密度推定したグラフを作成する
p1=ggplot(iris,aes(x=Sepal.Width))+stat_density()
#xの経験分布関数を作成する
p2=ggplot(iris,aes(x=Sepal.Width))+stat_ecdf()
#これは先ほどのp3と同じです!
p3=ggplot(iris,aes(x=Species,y=Sepal.Length))+stat_summary(geom="bar",fun.y=mean)
grid.arrange(p1,p2,p3,nrow=1)

f:id:tomoshige_n:20140803003952p:plain

まとめ

ggplot2のパッケージはなかなか柔軟に何でもできてしまうことがわかりました。使い方も「わかってしまえば」簡単だなと。でも、この考え方は慣れない人には相当気持ち悪いです。が、僕は奇麗な図を描いていきたいので積極的に使っていこうと思います。ちなみに、今回は第1回としていて、まだまだggplot2は深い処理ができるようなので、これから紹介していきたいと思います。