ggplot2についてちょっと勉強した(2)

前回: ggplot2についてちょっと勉強した(1) - もうカツ丼でいいよな
今回はggplot2の上の方にあるOne hour ggplot workshopっていうpdfを読んだ。
順番が逆じゃないかと思うけど前回より基本的な部分。
またしても理解したような理解してないような微妙な感じだけど理解した分だけメモっとく。微妙な部分には(たぶん)とか書いてある。

使用するデータについて

準備
install.packages(ggplot2)
library(ggplot2)
Diamonds
  • ggplot2についてくる
  • ダイアモンドのデータ
  • 53940レコード、10項目と膨大
    • price: 価格(USドル $326-$18823)
    • carat: カラット
    • cut: カットのクオリティ(Fair, Good Very Good, Premium, Ideal)
    • colour:カラー。J(worst)からD(best)
    • clarity:透明度の指標(I1(worst), SI1, SI2, VS2, VVS1, VVS2, IF(best))
    • x: 長さ(mm)
    • y: 幅(mm)
    • z: 深さ(mm)
    • depth: 直径に対する深さの比(%)。z/mean(x,y)
    • table: 最も幅が広い部分に対する頂面部分の幅の比。%。

qplot

前回もちょっと触れたけどplotと似たノリで使える。

  • スケールを自動で決めてくれる
  • どんなタイプのプロットもできる
  • marginとかも適当に決まる
  • オブジェクトはセーブも変更も自在
使い方

散布図。

## 基本はplot()みたいな感じ
qplot(carat, price, data = diamonds)
## colour = に変数を指定するとそれを基準に分類して色分けする
qplot(carat, price, data = diamonds,
      colour = clarity)
## geom = でプロットタイプが指定できる
qplot(carat, price, data = diamonds,
      geom = c("point", "smooth"),      # point(散布図)とsmooth(線)の指定
      method = lm)                      # smoothの線をどのような方法で引くか

ヒストグラムも書ける。

## ヒストグラム(defaultの区切り幅はrange/30)
qplot(carat, data = diamonds,
      geom = "histogram")
## 区切り幅の指定
qplot(carat, data = diamonds,
      geom = "histogram", binwidth = 0.1)

とまあこんな具合にqplotを使えば割と簡単にggplotのグラフが描ける。
でもqplotは簡単にグラフが描ける反面、細かい設定はしにくい。
qplotは細かいことを全部やってしまった結果を出力してくれている。

ggplot

ではggplot2でもっと基本的な作画関数は何かというとggplotである。しかし、ggplotに闇雲にデータを投げてもプロットはできない。
まず、ggplotという関数が何を作っているのかを見てみよう。

> str(ggplot())
List of 8
 $ data       :'data.frame':	0 obs. of  0 variables
 $ layers     : list()
 $ scales     :proto object 
 .. $ name: chr "Unknown" 
  ..parent: proto object 
 .. .. parent: proto object 
 .. .. .. parent: proto object 
 $ mapping    : list()
 $ options    : list()
 $ coordinates:proto object 
 .. $ limits:List of 2 
 ..  ..$ x: NULL 
 ..  ..$ y: NULL 
  ..parent: proto object 
 .. .. parent: proto object 
 .. .. .. parent: proto object 
 $ facet      :proto object 
 .. $ as.table     : logi TRUE 
 .. $ labeller     :List of 1 
 ..  ..$ : chr "label_value" 
 .. $ scales       : NULL 
 .. $ space_is_free: logi FALSE 
 .. $ free         :List of 2 
 ..  ..$ x: logi FALSE 
 ..  ..$ y: logi FALSE 
 .. $ margins      : logi FALSE 
 .. $ facets       : chr ". ~ ." 
  ..parent: proto object 
 .. .. parent: proto object 
 .. .. .. parent: proto object 
 $ plot_env   :<environment: R_GlobalEnv> 
 - attr(*, "class")= chr "ggplot"

まだ何もしていないのにずらずらと項目が並んでいる。
でもなんだかレイヤーだとかスケールだとかプロットのパラメータのような単語が目につく。
ggplotではこのパラメータに値を指定していくことでプロットの仕方や外観を決定していく。
つまり、qplotという関数はこのパラメータを適当に設定した上でggplotを実行するというような関数だったのだ。
そして、前回geom_ablineという関数を使ってablineのようなことをしたとき、元のqplot関数に+を使ってgeom_ablineをくっつけて一緒に実行していた。geom_ablineという関数は、低水準作画関数のように後から上書きしているのではなく、直線を引くような適当な設定値を生成する。その値を設定するためにqplot(というかggplot)と+でくっつけていた。
実際にどのようなものが設定されるかは

geom_abline()
str(ggplot() + geom_abline())

などとしてみると分かる。かなり項目が増えていることが分かると思う。ちなみにstrを外して実行してみてもエラーが出て描画されない。プロットのためには"data"を指定する必要もあるからだ。

プロットのために何を指定する必要があるのか?

今"data"が必要と言ったが、もちろんほかにも指定すべきものはいろいろある。大別すれば以下のようなものを指定する必要がある。

  • data: プロット、あるいは計算の対象となるデータ(ex. diamonds)
  • geom: Geometric objectの略。データをどのようにプロットするかの決定。散布図なのか、線なのか、面なのかといったこと。
  • statistics: データをどのように計算処理するのかといったこと(たぶん)
  • scale: データをどんな物差しの上に乗せるのか。対数なのか、平方根なのか。
  • 使用する座標系

たとえば次のように指定するとヒストグラムになる。

  • geom: bar
  • stat: bin
  • scale:liner
  • Coordinate system: Cartesian(直交座標系)

では、実際にプロットするときどうやって指定するかというとこんな感じになる。上記分類は概念的なもので必ずしも一致するわけではない。

 ggplot(data, mapping) +
 layer(
       stat = "",
       geom = "",
       posision = "",
       geom_parms = list(),
       stat_params = list(),
       )

ggplotに対してlayerという関数を足していく、というのが基本的な構造。
ここでmappingというものがあるが、これはパラメータ(aestheticという単語が使われているようだが適当な訳が思いつかない)に対してデータをマッピングするということを表している。マッピングにはaesという関数が使われる。ggplotの中で使っても外で使って+でくっつけてもいい。マッピングするものとされるものは同じ構造を持っていることが多いので、普通の代入のようにも見える。

aes(x = x, y = y) ## x,y軸にデータをmapping

しかし、マッピング(写像)という単語が意味するように別に両者が同じ構造、要素を持つ必要はない。たとえば上の方でやった

## colour = に変数を指定するとそれを基準に分類して色分けする
qplot(carat, price, data = diamonds,
      colour = clarity)

というこれをggplotやaesを使って基本的な方法に近いやり方で書き直すとこのようになる。

ggplot(diamonds) +
  aes(x = carat, y = price, colour = clarity) +
  geom_point()

x, yにはcarat, priceの値がそのまま代入されているように見える。プロット上でそのまま使われているように見えるからだ。しかし、colourに使われているclarityは元々の文字型がそのまま使われているわけではない。プロットの色との対応付けもなされている。この「対応付け」も行うのがaesによるmappingである。
さらに言えば、x = carat, y = priceもその場でデータが代入されている訳ではない。これはaesを単体で実行してみると分かる。

> aes(x = carat, y = price, colour = clarity)
List of 3
 $ x     : symbol carat
 $ y     : symbol price
 $ colour: symbol clarity

aesはデータの関係のみを記述する。式や変数名が評価されるのはggplotの実行時である。

geoms

reference manualの最初に"Geoms, short for geometric objects, describe the type of plot you will produce."とあるように、geoms_...という一連の関数はデータのプロット形式を指定するための一連のパラメータ、mappingを短い記述によって生成する。dataの指定と最低限必要なmappingをしたら、目的のgeom_...関数を(必要であればさらにmappingを足して)+によって足すだけで目的のプロットが得られる。たとえばすぐ上で例示した

ggplot(diamonds) +
  aes(x = carat, y = price, colour = clarity) +
  geom_point()

などはまさにそんな感じ。

stat

statはデータを元に回帰係数などの新しい値を生成する(たぶん)。
geomの中にはいくつかのgeom、statを組み合わせただけのものもいくつかある。geom_histogramなどはその例で、stat_binとgeom_barを組み合わせている。

New variables

statは新しい変数を作り出す。たとえばstat_binを使うとcount, densityという新しい変数が作成される。この値を利用するには、変数名を..で囲う。たとえば、

ggplot(diamonds, aes(x = price)) +
## y軸の単位をdensityにし、countを元に色分け
  geom_histogram(aes(y = ..density.., colour = ..count..))

Parameters

geomの外観を変えたり、statisticsによる計算を変えたりする。これまでにもすでにいくつか使っている。

  • geom_smooth(method = lm) スムージングの方法
  • stat_bin(binwidth = 100) 分割の幅

Setting vs Mapping

parameterのセッティングとmappingは似ているけど全然違う。たとえばプロットの点を緑にしたくてgeom_point(aes(colour = "green"))とやっても緑にはならない。これは"green"というデータをcolourに関係づけただけで、点が緑になるかどうかとは全然関係ない。この場合はgeom_point(colour="green")としてやらないといけない。

というわけで

このあたりまで。スライドはもうちょっと範囲広いよ。
positionのところとか実例がないのでまだよく分からない。
スライドには図の上に図を重ねたものとか出てきていたけど、ああいうのも描けるんだろうか。