ggplot2でグラフを部品から組み上げる。

## knitr configuration: http://yihui.name/knitr/options#chunk_options
opts_chunk$set(comment = "", error= TRUE, warning = FALSE, message = FALSE,
               tidy = FALSE, cache = F, echo = T,
               fig.width = 6, fig.height = 6)

## R configuration
options(width = 116, scipen = 5)

References

ggplot2を読み込み。

library(ggplot2)

グラフの構成要素

ggplot2ではグラフの部品を組み合わせてグラフを描画する。具体的には下記の項目を指定してデータをグラフ化する。省略した文法も存在するが、あえていっさい省略せずに記述した方がggplot2の考え方がわかりやすい。

指定項目

データの用意

付属のダイアモンドのデータを使用する。カラット数と値段の関係をダイアモンドの透明度ごとに図示する。

data(diamonds)
head(diamonds)
  carat       cut color clarity depth table price    x    y    z
1  0.23     Ideal     E     SI2  61.5    55   326 3.95 3.98 2.43
2  0.21   Premium     E     SI1  59.8    61   326 3.89 3.84 2.31
3  0.23      Good     E     VS1  56.9    65   327 4.05 4.07 2.31
4  0.29   Premium     I     VS2  62.4    58   334 4.20 4.23 2.63
5  0.31      Good     J     SI2  63.3    58   335 4.34 4.35 2.75
6  0.24 Very Good     J    VVS2  62.8    57   336 3.94 3.96 2.48

ggplot()でdataとmappingを指定する

最初にggplot()を使用してデータと変数の配置を設定する。これをp1と名付けて置くことで再利用できるようにする。このようにggplotのグラフの部品は個別にオブジェクトとして置いておくことができる。

p1 <- ggplot(data = diamonds,
             mapping = aes(x = carat, y = price, color = clarity))

summary(p1)
data: carat, cut, color, clarity, depth, table, price, x, y, z [53940x10]
mapping:  x = carat, y = price, colour = clarity
faceting: facet_null() 

aes()という関数を通すことでggplot2が再利用できる形のmappingオブジェクトを作成して、mappingオプションに渡している。summary(p1)とすることでどのような指定がされているかをみることができる。

変数を配置できる項目には下記のようなものが存在する。グラフの種類によって必要ないものもある。ここではx, y, colorだけを使用している。

layer()でstatとgeomを指定する

layer()を使って統計処理(stat)と形態(geom)を指定する。複雑なグラフでは複数のlayer()を重ねて描画する。ここまでで最低限の要素がそろうのでグラフとして出力可能になる。

l1 <- layer(stat = "identity",
            geom = "point")
l1
geom_point:  
stat_identity:  
position_identity: (width = NULL, height = NULL)

l1として表示するとどのような指定をしているのかみることができる。さらに、グラフの構成要素を + でつないで実行するとグラフを実際に描画する。ループ内などではprint(p1 + l1)のようにする必要がある。

p1 + l1

plot of chunk unnamed-chunk-6

重ね書きによく使われるのは分布の傾向を示すsmoother。サンプル数が少ない場合はloess (Local Polynomial Regression Fitting)が、サンプル数が多い場合はGAM (Generalized additive model)によるfittingが行われる。

stat_smooth(mapping = NULL, data = NULL, geom = "smooth",
            position = "identity", method = "auto",
            formula = y ~ x, se = TRUE, n = 80, fullrange = FALSE,
            level = 0.95, na.rm = FALSE, ...)

smootherを重ねてみます。デフォルトではregressionで曲線を描くsmooth statと最適化された形態のsmooth geomの組み合わせです。colorによるグループ分けの影響を受けてしまうので、color = “blue”(カラー分けしないで一色指定)をいれています。このように定数を指定する場合はaes(color = var_name)のようなmapping = aes()は必要ないです。曲線と95%信頼区間が表示されます。

lsm1 <- layer(stat = "smooth",
              geom = "smooth",
              color = "blue")

p1 + l1 + lsm1

plot of chunk unnamed-chunk-7

point lineを使うように強制すれば、曲線のみが描画されます(さっきのlayerにse = FALSEを与えても同じ結果になります)。

lsm2 <- layer(stat = "smooth",
              geom = "line",
              color = "blue")

p1 + l1 + lsm2

plot of chunk unnamed-chunk-8

範囲を示すバンドを作成するribbon geomを強制してみます。下記のようなmappingを追加できます。

     ‘geom_ribbon’ understands the following aesthetics (required
     aesthetics are in bold):
        • ‘*x*’
        • ‘*ymax*’
        • ‘*ymin*’
        • ‘alpha’
        • ‘colour’
        • ‘fill’
        • ‘linetype’
        • ‘size’

ここでは線を青、真ん中の塗りつぶしを薄青でかつalphaをつかって80%の不透明度(20%透明)にしてみます。

lsm3 <- layer(stat = "smooth",
              geom = "ribbon",
              color = "blue", fill = "lightblue", alpha = 4/5)

p1 + l1 + lsm3

plot of chunk unnamed-chunk-9

ここで取り上げた例は実用性が微妙ですが、このように統計処理を示すstatとグラフの形態を指定するgeomを独立して扱うことにより、自在にグラフが作成できます。下記のサイトにより具体的な例が記載されています。

http://www.ling.upenn.edu/~joseff/avml2012/

geom_()やstat_()という部品をlayer()の代わりに使っていますが、これは省略した記載方法です。

scaleで変数の配置方法を調節

X軸とY軸の変数が連続変数、color軸(?)の変数がカテゴリー変数になっている。このためそれぞれ、下記のような軸指定が使われているが、これを調節することが可能。これもオブジェクトして置いておいて再利用可能である。

X軸を細かく指定する。

sX <- scale_x_continuous(name = "C A R A T",    # 軸の名前を変える
                         breaks = c(0,2,4),     # 軸の区切りを0,2,4にする
                         labels = c("zero","two","four"), # 区切りを名付ける
                         limits = c(0,4))       # 0から4までしか表示しない
sX
continuous_scale(aesthetics = c("x", "xmin", "xmax", "xend", 
    "xintercept"), scale_name = "position_c", palette = identity, 
    name = "C A R A T", breaks = ..2, labels = ..3, limits = ..4, 
    expand = expand, guide = "none")

Y軸を細かく指定する。いじらない項目は指定しなくてよい。

sY <- scale_y_continuous(name = "price (log10 axis)", # 軸の名前を変える
                         breaks = c(500,1000,5000,10000,50000), # 区切り指定
                         trans = "log10")       # 底10のlog変換軸とする
sY
continuous_scale(aesthetics = c("y", "ymin", "ymax", "yend", 
    "yintercept", "ymin_final", "ymax_final"), scale_name = "position_c", 
    palette = identity, name = "price (log10 axis)", breaks = ..2, 
    expand = expand, trans = "log10", guide = "none")

color軸を細かく指定する。

sC <- scale_color_discrete(breaks = rev(levels(diamonds$clarity)), # 配置順を逆
                           ## 上から3つまでしか色を付けない。
                           limits = rev(levels(diamonds$clarity))[1:3],
                           ## 下記はデフォルト
                           h = c(0, 360) + 15, # 色の範囲
                           c = 100,            # 色の濃さ
                           l = 65,             # 色の明るさ
                           h.start = 0,        # 色の開始位置
                           direction = 1,      # 色変化の向き
                           ## 下記だけデフォルトgrey50から変更有り
                           na.value = "white") # 色無しの時の色
sC
discrete_scale(aesthetics = "colour", scale_name = "hue", palette = hue_pal(h, 
    c, l, h.start, direction), breaks = ..1, limits = ..2, na.value = na.value)

gridExtraパッケージのgrid.arrangeを使って軸をいじる前と後とで並べて表示する。

library(gridExtra)
grid.arrange(p1 + l1,
             p1 + l1 + sX + sY + sC)

plot of chunk unnamed-chunk-13

facetでグラフを分割

点が重なってわかりにくいので、clarityごとにグラフを分割する。最初に色の指定を上三つだけでなくすべて表示するように指定。

sC2 <- scale_color_discrete(breaks = rev(levels(diamonds$clarity)))
sC2
discrete_scale(aesthetics = "colour", scale_name = "hue", palette = hue_pal(h, 
    c, l, h.start, direction), breaks = ..1, na.value = na.value)

facet_grid(行分けの変数 ~ 列分けの変数)という形で指定する。指定しない時は.を使う。ここでは行方向にcutの品質で分割、列方向に透明度で分割してみる。

f1 <- facet_grid(cut ~ clarity)
f1
facet_grid(cut ~ clarity) 

p1 + l1 + sX + sY + sC2 + f1

plot of chunk unnamed-chunk-15

themeでデザインを微調節

?themeで表示されるように、たくさん指定できる項目がある。項目ごとにelement_*()という関数を介してオプションを与えるようになっておりややこしい。

th1 <- theme(
    ## X軸のタイトルをピンクに
    axis.title.x     = element_text(color = "pink"),
    ## Y軸のタイトルをを太斜体に
    axis.title.y     = element_text(face = "bold.italic"),
    ## グラフの背景を白に
    panel.background = element_rect(fill = "white"),
    ## グラフの背景の線を紫色に
    panel.grid.major = element_line(color = "purple"),
    ## 凡例の点の後ろを黄色に
    legend.key       = element_rect(fill = "lightyellow")
             )

p1 + l1 + th1

plot of chunk unnamed-chunk-16

element_line()

  colour: line colour
    size: line size
linetype: line type
 lineend: line end
   color: an alias for ‘colour’

element_rect()

    fill: fill colour
  colour: border colour
    size: border size
linetype: border linetype
   color: an alias for ‘colour’

element_text()

  family: font family
    face: font face ("plain", "italic", "bold", "bold.italic")
  colour: text colour
    size: text size (in pts)
   hjust: horizontal justification (in [0, 1])
   vjust: vertical justification (in [0, 1])
   angle: angle (in [0, 360])
lineheight: line height
   color: an alias for ‘colour’

element_blank()は要素を空にするときに使う。