7 tidyverse

7.5 ggplot2

ggplot2 はデータの可視化を行うパッケージであり、 ggplot2 のグラフの仕上がりは、R の標準関数に比べてきれい。 基本的にデータフレーム(または tibble)に保存されたデータに対して、 x 軸と y 軸となる列名を指定するだけで、簡単できれいなグラフが描けるため、様々な場面で使わる。

ggplot2 の拡張機能

ggplot2 デフォルトでもきれいなグラフを描くことができるが、 ggplot2 向けに作られた拡張機能を使うことで、さらにきれいなグラフを作成できる。 グラフ全体のスタイル構成(テーマ)を提供しているパッケージとして ggthemes が知られている。 グラフを描くときの点や線の色パターン(カラーパレット)を提供しているパッケージとして、 RColorBrewer や ggsci などが知られている。 また、ggpubr および gridExtra パッケージは複数の ggplot グラフを 1 つの画面で表示させるためのパッケージである。 これらのパッケージを予めインストールしておくとよい。

install.packages('ggthemes')
install.packages('RColorBrewer')
install.packages('ggsci')
install.packages('ggpubr')
install.packages('gridExtra)

ggplot2 を利用したグラフ作成の手順

ggplot2 でグラフを描くとき、基本的に次のような手順を踏む。

  1. ggplot2 で描きたいグラフを、手書きで紙に書いてみる。簡単なグラフは必ずしも手書きする必要はないが、複雑なグラフを描くときは必ず手書きで一度紙に書いておくとよい。
  2. 手書きのグラフを確認し、その x 軸と y 軸となるデータを、データフレームとして作成する。必要であれば、色の使い分けに関する情報もそのデータフレームに入れる。
  3. ggplot2 の関数でグラフを描く。
    • ggplot 関数で描画レイヤーを用意する。この際に、aes オプションで x 軸、y 軸、色情報などを指定する。
    • geom_pointgeom_line などの関数を使用してグラフを描く。
    • xlabylabxlimylimtheme などの関数でグラフの軸座標やカラースタイルを調整する。

ggplot2 の基本的な関数の概略は RStudio ウェブサイトで公開されている ggplot2 cheatsheet で確認できる。

ggplot2 準備

(ggplot2 パッケージを含む)tidyverse パッケージおよび グラフのテーマやカラーパレットなどを指定するためのパッケージも合わせて呼び出して準備する。

library(tidyverse)
## ── Attaching packages ─────────────────────────────────────────────────────────────────────────────────────── tidyverse 1.3.0 ──
## ✓ ggplot2 3.3.2     ✓ purrr   0.3.4
## ✓ tibble  3.0.3     ✓ dplyr   1.0.1
## ✓ tidyr   1.1.1     ✓ stringr 1.4.0
## ✓ readr   1.3.1     ✓ forcats 0.5.0
## ── Conflicts ────────────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
## x dplyr::filter() masks stats::filter()
## x dplyr::lag()    masks stats::lag()
library(ggthemes)
library(ggsci)
library(ggpubr)
library(ggExtra)

geom_point 関数

geom_point 関数は散布図を描く関数である。 ここでは、rice.txt データセットを使ってグラフを描く例を示す。 rice データセットには 7 つの列があり、 それぞれの列が標本の個体番号(replicate)、ブロック番号(block)、 根部乾燥重量(root_dry_mass)、地上部乾燥重量(shoot_dry_mass)、 系統処理(trt)、処理(fert)、系統(variety)からなる。

d <- read_tsv('data/rice.txt')
## Parsed with column specification:
## cols(
##   replicate = col_double(),
##   block = col_double(),
##   root_dry_mass = col_double(),
##   shoot_dry_mass = col_double(),
##   trt = col_character(),
##   fert = col_character(),
##   variety = col_character()
## )
head(d)
## # A tibble: 6 x 7
##   replicate block root_dry_mass shoot_dry_mass trt   fert  variety
##       <dbl> <dbl>         <dbl>          <dbl> <chr> <chr> <chr>  
## 1         1     1            56            132 F10   F10   wt     
## 2         2     1            66            120 F10   F10   wt     
## 3         3     1            40            108 F10   F10   wt     
## 4         4     1            43            134 F10   F10   wt     
## 5         5     1            55            119 F10   F10   wt     
## 6         6     1            66            125 F10   F10   wt

簡単な散布図として、各個体の根部乾燥重量(root_dry_mass)を x 軸とし、 地上部乾燥重量(shoot_dry_mass)を y 軸としてグラフを描く例を示す。 x 座標および y 座標の情報は ggplot 関数の中の aes 関数の中で指定する。 指定方法として、データフレーム d の中で x 座標にしたい列の列名(root_dry_mass)を x オプションに、 y 座標にしたい列名(shoot_dry_mass)を y オプションに指定する。

p <- ggplot(d, aes(x = root_dry_mass, y = shoot_dry_mass)) +
      geom_point()
print(p)

上で描いた散布図に wt 系統と ANU843 系統の 2 つの系統のデータが含まれている。 両方とも黒の点として描かれ、区別できない。 そこで、この散布図に対して、系統ごとに点の色を塗り分けて wt 系統と ANU843 系統を区別できるようにする。 色を指定するときは、aes 関数の color オプションを使う。 系統ごと(variety 列にある値に基づいて)色を塗り分けたいので、 ここでは color オプションに系統を表す列名 variety を指定する。

p <- ggplot(d, aes(x = root_dry_mass, y = shoot_dry_mass, color = variety)) +
      geom_point()
print(p)

rice データは、各系統(variety)に対して 3 つの処理(fert)が行われている。 具体的に言えば、wt 系統には F10 処理、NH4Cl 処理、NH4NO3 処理がある。 また、ANU843 系統にも同様に F10 処理、NH4Cl 処理、NH4NO3 処理がある。 系統と処理の違いがわかるように点の色を塗り分けたい場合は、 variety 列と fert 列の組み合わせ(interaction)に対して色を付ければよい。 そのためには、aes 関数の color オプションに interaction(variety, fert) を代入する。 なお、variety 列のラベルと fert 列のラベルの組み合わせを作るとき、 両方のラベルを結合するときの区切り文字として ’ / ’ を使うことにする。

p <- ggplot(d, aes(x = root_dry_mass, y = shoot_dry_mass,
                   color = interaction(variety, fert, sep = ' / '))) +
      geom_point()
print(p)

各系統を点の色で区別し、各処理を点の形で区別することもできる。 点の形を指定するオプションとして shape があるので、 このオプションに各処理のラベルが含まれている列名(fert)を指定する。

p <- ggplot(d, aes(x = root_dry_mass, y = shoot_dry_mass, color = variety, shape = fert)) +
      geom_point()
print(p)

散布図に描かれる点について、色と形のほか、大きさも調整することができる。 次に、trees データセットを呼び出して、点の大きさを変更する方法を示す。 このデータは 3 列からなり、それぞれ Girth、Height、Volume となっている。

data(trees)
head(trees)
##   Girth Height Volume
## 1   8.3     70   10.3
## 2   8.6     65   10.3
## 3   8.8     63   10.2
## 4  10.5     72   16.4
## 5  10.7     81   18.8
## 6  10.8     83   19.7

ここで Girth 列の値を x 座標とし、Height 列の値を y 座標として散布図を描く。 この際、点のサイズを size オプションで、デフォルトよりも少し大きめに設定して描く。

p <- ggplot(trees, aes(x = Girth, y = Height, size= 2)) +
        geom_point()
print(p)

続けて、点の大きさを固定値ではなく、 trees のデータセットの Volume 列の値に応じて大小を変化させるように指定する。 Volume の値が大きければ点のサイズも大きく、 Volume の値が小さければ点のサイズも小さくなるようにする。 このような点を描くためには、size オプションに固定値ではなく Volume 列の列名を指定すればよい。

p <- ggplot(trees, aes(x = Girth, y = Height, size= Volume)) +
        geom_point()
print(p)

点の色と同じく、color オプションに連続量である Volume を指定すると、 点の色は値の大小に応じてグラデーション色で描かれる。

p <- ggplot(trees, aes(x = Girth, y = Height, size = Volume, color = Volume)) +
        geom_point()
print(p)

ggthemes & ggsci

ggplot を使って描いたグラフは、背景色が灰色で、点や線の色は蛍光色となっている。 これらの色の組み合わせを変更することができる。 背景色を変更したい場合は、ggplot のテーマを変更すればよいし、 点や線の色を変更したい場合はカラーパレットを変更すればよい。

ggplot にはいくつかのテーマが標準で組み込まれている。 例えば、白背景のテーマに変更したい場合は theme_bw 関数を使用する。 theme_bw のほかに、theme_classictheme_lighttheme_dark などのテーマが用意されている。

d <- read_tsv('data/rice.txt')
## Parsed with column specification:
## cols(
##   replicate = col_double(),
##   block = col_double(),
##   root_dry_mass = col_double(),
##   shoot_dry_mass = col_double(),
##   trt = col_character(),
##   fert = col_character(),
##   variety = col_character()
## )
p <- ggplot(d, aes(x = root_dry_mass, y = shoot_dry_mass, color = variety)) +
      geom_point() +
      theme_bw()
print(p)

ggthemes パッケージには多様なテーマが提供されている。 例えば、経済雑誌風のテーマ、エクセル風のテーマなどのようなものがある。

p <- ggplot(d, aes(x = root_dry_mass, y = shoot_dry_mass, color = variety)) +
      geom_point() +
      theme_wsj()
print(p)

ggsci パッケージは カラーパレットを提供してるパッケージである。 点や線の色の組み合わせを変更したい場合は、ggsci パッケージのカラーパレットを使用するときれいになる。 カラーパレットを変更するとき、既存のコードにカラーパレット関数を追加するだけでよい。 例えば、ggsci パッケージ中の scale_color_npg カラーパレットを使う場合は、 次のように、グラフを描く関数の最後に scale_color_npg() を追加する。

p <- ggplot(d, aes(x = root_dry_mass, y = shoot_dry_mass, color = variety)) +
      geom_point() +
      theme_bw() +
      scale_color_npg()
print(p)

geom_line 関数

geom_line 関数は線グラフを描く関数である。 線グラフは、時系列データを視覚化するのに適しているので、 ここでは時系列データ Nile に対して線グラフを描いてみる。 Nile データセットは、1871 年から 1970 年までのナイル川の流量を記録したデータである。 Nile データセットを呼び出して、ggplot2 で使いやすいように少し整形する。

data(Nile)
d <- data.frame(Nile = as.integer(Nile), year = as.integer(time(Nile)))
head(d)
##   Nile year
## 1 1120 1871
## 2 1160 1872
## 3  963 1873
## 4 1210 1874
## 5 1160 1875
## 6 1160 1876

年を x 軸の座標とし、ナイル川の流量を y 座標として、geom_line 関数で線グラフを描く。

p <- ggplot(d, aes(x = year, y = Nile)) +
      geom_line()
print(p)

次に、1991 年から 1998 年までにおける複数の株価指数の 変化を記録したデータセットを用いて、 折れ線グラフを描いてみる。 まず、データを ggplot2 で扱いやすいように整理していく。

data(EuStockMarkets)
df <- data.frame(stock = as.matrix(EuStockMarkets), time = time(EuStockMarkets))
colnames(df) <- gsub('stock.', '', colnames(df))
head(df)
##       DAX    SMI    CAC   FTSE     time
## 1 1628.75 1678.1 1772.8 2443.6 1991.496
## 2 1613.63 1688.5 1750.5 2460.2 1991.500
## 3 1606.51 1678.6 1718.0 2448.2 1991.504
## 4 1621.04 1684.1 1708.1 2470.4 1991.508
## 5 1618.16 1686.6 1723.1 2484.7 1991.512
## 6 1610.61 1671.6 1714.3 2466.8 1991.515
df <- df %>% pivot_longer(c(DAX, SMI, CAC, FTSE), names_to = 'stock', values_to = 'value')
head(df)
## # A tibble: 6 x 3
##    time stock value
##   <dbl> <chr> <dbl>
## 1 1991. DAX   1629.
## 2 1991. SMI   1678.
## 3 1991. CAC   1773.
## 4 1991. FTSE  2444.
## 5 1992. DAX   1614.
## 6 1992. SMI   1688.

x 軸を時間、y 軸を株価指数、線の色を指数の種類にしたいので、 x = timey = value、そして color = stock と指定して geom_line 関数で線グラフを描く。

p <- ggplot(df, aes(x = time, y = value, color = stock)) +
        geom_line() +
        theme_bw() +
        scale_color_npg()
print(p)

aes 関数に linetype オプションをつけることで、 線の形(実線、ダッシュ線、点線など)を指定することができる。

p <- ggplot(df, aes(x = time, y = value, color = stock, linetype = stock)) +
        geom_line() +
        theme_bw() +
        scale_color_npg()
print(p)

geome_bar 関数

geom_bar 関数は棒グラフを描くときに使う関数である。 geom_bar 関数はデフォルトでは、座標を 1 つ受け取り、 それを頻度(stat = 'count') (棒の高さ)として棒グラフとして描く関数である。 例えば、次のようにして、乱数でいくつかの整数を生成して、棒グラフを描いてみる。

df <- data.frame(value = rpois(100, 10))
p <- ggplot(df, aes(x = value)) +
        geom_bar()
print(p)

しかし、実際に棒グラフを描くときは、横軸をカテゴリ名にして、縦軸をそのカテゴリの代表値にすることが多い。 x 軸と y 軸の両方を指定して棒グラフを描くときは、 geom_bar 関数に対して stat = 'identity' と指定する必要がある。

df <- data.frame(fruit = c('apple', 'melon', 'cherry', 'orange'),
                 weight = c(120, 400, 30, 160))
head(df)
##    fruit weight
## 1  apple    120
## 2  melon    400
## 3 cherry     30
## 4 orange    160
p <- ggplot(df, aes(x = fruit, y = weight)) +
        geom_bar(stat = 'identity')
print(p)

ここからは rice データセットを使って、少し複雑な棒グラフを描いてみる。 まずは rice データの wt 系統の root_dry_mass と shoot_dry_mass の平均値を棒グラフの高さとして棒グラフを描く。 rice データには root_dry_mass と shoot_dry_mass の平均値が記載されていないので、 平均値の計算を行ってから geom_bar 関数でグラフを描くことにする。 この平均値の計算は dplyr パッケージの様々な関数を使って行う。

d <- read_tsv('data/rice.txt')
## Parsed with column specification:
## cols(
##   replicate = col_double(),
##   block = col_double(),
##   root_dry_mass = col_double(),
##   shoot_dry_mass = col_double(),
##   trt = col_character(),
##   fert = col_character(),
##   variety = col_character()
## )
g <- d %>%
        filter(variety == 'wt') %>%
        group_by(variety) %>% 
        summarise(root_dry_mass = mean(root_dry_mass),
                  shoot_dry_mass = mean(shoot_dry_mass)) %>%
        pivot_longer(c(root_dry_mass, shoot_dry_mass), names_to = 'tissue', values_to = 'dry_mass') %>%
        ggplot(aes(x = tissue, y = dry_mass)) +
          geom_bar(stat = 'identity') +
          theme_bw()
## `summarise()` ungrouping output (override with `.groups` argument)
print(p)

次に、各系統(wt 系統と ANU843 系統)に対して、 それぞれの root_dry_mass および shoot_dry_mass の平均値を棒グラフとして描く。 この際、棒グラフの色を組織(root または shoot)ごとに塗り分ける。 なお、棒の色を指定するとき、colorfill の両方を指定できるが、 color は棒の枠線の色で、fill は棒の枠内の塗りである。 一般的に fill のみを指定すればよい。

df <- d %>%
        group_by(variety) %>% 
        summarise(root_dry_mass = mean(root_dry_mass),
                  shoot_dry_mass = mean(shoot_dry_mass)) %>%
        pivot_longer(c(root_dry_mass, shoot_dry_mass), names_to = 'tissue', values_to = 'dry_mass')
## `summarise()` ungrouping output (override with `.groups` argument)
p <- ggplot(df, aes(x = variety, y = dry_mass, fill = tissue)) +
          geom_bar(stat = 'identity') +
          scale_fill_npg() +
          theme_bw()

print(p)

項目数(色の塗りわけ)があるとき、 geom_bar 関数はデフォルトでは積み上げ棒グラフ(position = "stack")を描くように実装されている。 これを横並びに形式にしたい場合は、position の値を dodge に変更すればよい。

p <- ggplot(df, aes(x = variety, y = dry_mass, fill = tissue)) +
        geom_bar(stat = 'identity', position = "dodge") +
        scale_fill_npg() +
        theme_bw()
print(p)

また、position の値を fill にすると、積み上げグラフの合計が 1 となるような割合グラフが描かれる。

p <- ggplot(df, aes(x = variety, y = dry_mass, fill = tissue)) +
        geom_bar(stat = 'identity', position = "fill") +
        scale_fill_npg() +
        theme_bw()
print(p)

もう少し複雑な棒グラフを描く方法を示す。 横軸を系統(variety)と処理(fert)の組み合わせとしたときのグラフを描く。 まず、グラフを描くときの、データフレームを作成する。

df <- d %>%
        group_by(variety, fert) %>% 
        summarise(root_dry_mass = mean(root_dry_mass),
                  shoot_dry_mass = mean(shoot_dry_mass)) %>%
        pivot_longer(c(root_dry_mass, shoot_dry_mass), names_to = 'tissue', values_to = 'dry_mass')
## `summarise()` regrouping output by 'variety' (override with `.groups` argument)
head(df)
## # A tibble: 6 x 4
## # Groups:   variety [1]
##   variety fert   tissue         dry_mass
##   <chr>   <chr>  <chr>             <dbl>
## 1 ANU843  F10    root_dry_mass      6   
## 2 ANU843  F10    shoot_dry_mass     7.33
## 3 ANU843  NH4Cl  root_dry_mass      9.17
## 4 ANU843  NH4Cl  shoot_dry_mass    46.6 
## 5 ANU843  NH4NO3 root_dry_mass     13.8 
## 6 ANU843  NH4NO3 shoot_dry_mass    71.5

tissue 列と fert 列の値に基づいて色を塗り分けるように指定する。 このとき fill オプションに tissue と fert の組み合わせとなるように interaction(tissue, fert) と指定する。

p <- ggplot(df, aes(x = variety, y = dry_mass, fill = interaction(tissue, fert, sep = ' / '))) +
        geom_bar(stat = 'identity', position = "dodge") +
        scale_fill_npg() +
        theme_bw()
print(p)

geom_errorbar 関数

ggplot では、エラーバーを描く関数として geom_errorbar 関数が用意されている。 この関数を geom_point 関数や geom_bar 関数をとともに用いることで、 データの散らばり具合(標準偏差)あるいは母平均の推測値の散らばり具合(標準誤差)を表現できるようになる。 ここで、データの平均値と標準偏差を用いてエラーバー付きの点グラフ、およびエラーバー付きの棒グラフを描いてみる。

まず、rice データセットの wt 系統に対して、 エラーバーを描くための root_dry_mass および shoot_dry_mass の平均値および標準偏差を計算する。

df_mean <- d %>%
        filter(variety == 'wt') %>%
        group_by(variety) %>% 
        summarise(root_dry_mass = mean(root_dry_mass),
                  shoot_dry_mass = mean(shoot_dry_mass)) %>%
        pivot_longer(c(root_dry_mass, shoot_dry_mass), names_to = 'tissue', values_to = 'mean')
## `summarise()` ungrouping output (override with `.groups` argument)
df_sd <- d %>%
        filter(variety == 'wt') %>%
        group_by(variety) %>% 
        summarise(root_dry_mass = sd(root_dry_mass),
                  shoot_dry_mass = sd(shoot_dry_mass)) %>%
        pivot_longer(c(root_dry_mass, shoot_dry_mass), names_to = 'tissue', values_to = 'sd')
## `summarise()` ungrouping output (override with `.groups` argument)
df <- left_join(df_mean, df_sd)
## Joining, by = c("variety", "tissue")
head(df)
## # A tibble: 2 x 4
##   variety tissue          mean    sd
##   <chr>   <chr>          <dbl> <dbl>
## 1 wt      root_dry_mass   26.5  18.4
## 2 wt      shoot_dry_mass  77.3  32.9

geom_errorbar 関数はエラーバーとして、エラーバーの上限と下限を指定する必要がある。 その指定は aes 関数の ymax および ymin オプションで行う。 エラーバーを平均値からの標準偏差としたいので、 ymax を平均+標準偏差、ymin を平均ー標準偏差となるように指定する。

p <- ggplot(df, aes(x = tissue, y = mean,
                    ymin = mean - sd,
                    ymax = mean + sd)) +
        geom_point(size = 3) +
        geom_errorbar(width = 0.2) +
        theme_bw()
print(p)

エラーバーを棒グラフに重ねて描いてみる。

p <- ggplot(df, aes(x = tissue, y = mean, ymin = mean - sd, ymax = mean + sd)) +
        geom_bar(stat = 'identity') +
        geom_errorbar(width = 0.5) +
        theme_bw()
print(p)

次に複数の属性を持つ点グラフと棒グラフにエラーバーを重ねる方法を紹介する。 ここで、各系統(wt 系統と ANU843 系統)の各組織(root と shoot)の 乾燥重量の平均値と標準偏差を使って、エラーバーを描く。

df_mean <- d %>%
        group_by(variety) %>% 
        summarise(root_dry_mass = mean(root_dry_mass),
                  shoot_dry_mass = mean(shoot_dry_mass)) %>%
        pivot_longer(c(root_dry_mass, shoot_dry_mass), names_to = 'tissue', values_to = 'mean')
## `summarise()` ungrouping output (override with `.groups` argument)
df_sd <- d %>%
        group_by(variety) %>% 
        summarise(root_dry_mass = sd(root_dry_mass),
                  shoot_dry_mass = sd(shoot_dry_mass)) %>%
       pivot_longer(c(root_dry_mass, shoot_dry_mass), names_to = 'tissue', values_to = 'sd')
## `summarise()` ungrouping output (override with `.groups` argument)
df <- left_join(df_mean, df_sd)
## Joining, by = c("variety", "tissue")
head(df)
## # A tibble: 4 x 4
##   variety tissue          mean    sd
##   <chr>   <chr>          <dbl> <dbl>
## 1 ANU843  root_dry_mass   9.67  5.13
## 2 ANU843  shoot_dry_mass 41.8  30.4 
## 3 wt      root_dry_mass  26.5  18.4 
## 4 wt      shoot_dry_mass 77.3  32.9

複数項目が存在するので、項目を分けるために color オプションに組織別となるように指定する。 こうすることで、ggplot は自動的に項目別に色を塗り分ける。 ただし、どの項目の x 座標も同じであるため、グラフは重ねられた状態で描かれる。

p <- ggplot(df, aes(x = variety, y = mean, ymin = mean - sd, ymax = mean + sd, color = tissue)) +
        geom_point() +
        geom_errorbar() +
        theme_bw() +
        scale_fill_npg()
print(p)

そこで、root_dry_mass と shoot_dry_mass の 2 つの項目を重ねて描くのではなく、左右にずらして描くようにする。 このために、position = position_dodge() オプションを geom_bar 関数および geom_errorbar 関数に追加する。

p <- ggplot(df, aes(x = variety, y = mean, ymin = mean - sd, ymax = mean + sd, color = tissue)) +
        geom_point(position = position_dodge(0.5), size = 3) +
        geom_errorbar(aes(width = 0), position = position_dodge(0.5)) +
        theme_bw() +
        scale_fill_npg()
print(p)

このように調整できたので、さっそく棒グラフについても同様に描いてみる。 ただし、棒グラフの場合は position = position_dodge(0.9) の代わりに position = 'dodge' と指定してもよい。

p <- ggplot(df, aes(x = variety, y = mean, ymin = mean - sd, ymax = mean + sd,fill = tissue)) +
        geom_bar(stat = 'identity', position = position_dodge(0.9)) +
        geom_errorbar(aes(width = 0.3), position = position_dodge(0.9)) +
        theme_bw() +
        scale_fill_npg()
print(p)

データの平均値と標準偏差だけを描く場合、データそのものの分布を表せない。 そこで、平均値と標準偏差だけでなく、データの観測値そのものもグラフ上に重ねるて描いてみる。

df2 <- d %>%
        select(variety, root_dry_mass, shoot_dry_mass) %>%
        pivot_longer(c(root_dry_mass, shoot_dry_mass), names_to = 'tissue', values_to = 'dry_mass')
head(df2)
## # A tibble: 6 x 3
##   variety tissue         dry_mass
##   <chr>   <chr>             <dbl>
## 1 wt      root_dry_mass        56
## 2 wt      shoot_dry_mass      132
## 3 wt      root_dry_mass        66
## 4 wt      shoot_dry_mass      120
## 5 wt      root_dry_mass        40
## 6 wt      shoot_dry_mass      108

エラーバー付きの点グラフに、データの実際の値をプロットした点を重ねて描く。 この際にデータセットが 2 つ存在するので(データ観測値そのものとデータの平均・標準偏差の 2 つ)、 ggplot 関数にはデータセットを与えようにする。 その代わりに、geom_pointgeom_errobar などの関数で使うときに、初めてデータセットを与えるようにする。

p <- ggplot() + theme_bw() + scale_color_npg()

# points
p <- p + geom_point(aes(x = variety, y = dry_mass, color = tissue),
                    position = position_dodge(0.8),
                    alpha = 0.3, size = 3,
                    data = df2)

# points (the average) with errorbars
p <-  p + geom_point(aes(x = variety, y = mean, color = tissue),
                     position = position_dodge(0.8), size = 3, data = df) +
        geom_errorbar(aes(x = variety, group = tissue, ymin = mean - sd, ymax = mean + sd, width = 0),
                      position = position_dodge(0.8), data = df)

print(p)

上の例では、各項目の点の横軸が同じである。 このとき、縦軸も同じほぼ同じ値のときに、点同士が重なって、データ数を確認しにくくなる。 そこで、点のランダムに左右に少しずらして描きグラフを見やすくする。 点を左右にランダムにずらして描く関数は position_jitterdodge 関数がある。 なお、横軸座標はカテゴリ名であるため、横軸の値を左右にずらしても、可視化は不正確にならない。

p <- ggplot() + theme_bw() + scale_color_npg()

# points
p <- p + geom_point(aes(x = variety, y = dry_mass, color = tissue),
                    position = position_jitterdodge(jitter.width = 0.2, dodge.width=0.8),
                    alpha = 0.3, size = 3,
                    data = df2)

# points (the average) with errorbars / use `fill = tissue` to plot mean as black point
p <- p + geom_point(aes(x = variety, y = mean, fill = tissue), position = position_dodge(0.8), size = 3, data = df) +
        geom_errorbar(aes(x = variety, group = tissue, ymin = mean - sd, ymax = mean + sd, width = 0),
                      position = position_dodge(0.8), data = df)

print(p)

棒グラフについても同様に描くことができる。

p <- ggplot() + theme_bw() + scale_fill_npg() + scale_color_npg()

# barplot with errorbars
p <-  p + geom_bar(aes(x = variety, y = mean, fill = tissue), stat = 'identity', position = "dodge", data = df) +
        geom_errorbar(aes(x = variety, group = tissue, ymin = mean - sd, ymax = mean + sd, width = 0.3),
                      position = position_dodge(0.9), data = df)

# points / use `fill = tissue` to plot raw data as black point
p <- p + geom_point(aes(x = variety, y = dry_mass, fill = tissue),
                    position = position_jitterdodge(jitter.width = 0.2, dodge.width=0.9),
                    alpha = 0.3, size = 3,
                    data = df2)

print(p)

次に、もう少し複雑なグラフを描く方法を示す。 横軸を系統と処理の組み合わせとしたときのグラフを描く。 まず、グラフを描くときの、データフレームを作成する。

df_mean <- d %>%
        group_by(variety, fert) %>% 
        summarise(root_dry_mass = mean(root_dry_mass),
                  shoot_dry_mass = mean(shoot_dry_mass)) %>%
        pivot_longer(c(root_dry_mass, shoot_dry_mass), names_to = 'tissue', values_to = 'mean')
## `summarise()` regrouping output by 'variety' (override with `.groups` argument)
df_sd <- d %>%
        group_by(variety, fert) %>% 
        summarise(root_dry_mass = sd(root_dry_mass),
                  shoot_dry_mass = sd(shoot_dry_mass)) %>%
        pivot_longer(c(root_dry_mass, shoot_dry_mass), names_to = 'tissue', values_to = 'sd')
## `summarise()` regrouping output by 'variety' (override with `.groups` argument)
df1 <- left_join(df_mean, df_sd)
## Joining, by = c("variety", "fert", "tissue")
df2 <- d %>%
        select(variety, fert, root_dry_mass, shoot_dry_mass) %>%
        pivot_longer(c(root_dry_mass, shoot_dry_mass), names_to = 'tissue', values_to = 'dry_mass')

次にグラフを描く。 tissue と fert の色を塗り分けるように aes 関数の fill オプションで interaction(tissue, fert) と指定する。

p <- ggplot() + theme_bw() + scale_fill_npg() + scale_color_npg()

# barplot with errorbars
p <- p + geom_bar(aes(x = variety, y = mean, fill = interaction(tissue, fert)),
                   stat = 'identity', position = "dodge", data = df1) +
        geom_errorbar(aes(x = variety, group = interaction(tissue, fert), ymin = mean - sd, ymax = mean + sd, width = 0.3),
                      position = position_dodge(0.9), data = df1)

# points
p <- p + geom_point(aes(x = variety, y = dry_mass, fill = interaction(tissue, fert)),
                    position = position_jitterdodge(jitter.width = 0.2, dodge.width=0.9),
                    alpha = 0.3, size = 2,
                    data = df2)
print(p)

また、あとで紹介するが facet_wrap 関数などを用いることで、もう少しグラフを見やすく調整することができる。

geom_boxplot 関数

geom_boxplot はボックスプロットを描く関数である。 ここで、wt 系統の root_dry_mass と shoot_dry_mass のデータに対して、 ボックスプロットを描いてみる。 まず、グラフを描くためのデータを集計する。

g <- d %>%
        filter(variety == 'wt') %>%
        select(root_dry_mass, shoot_dry_mass) %>%
        pivot_longer(c(root_dry_mass, shoot_dry_mass), names_to = 'tissue', values_to = 'dry_mass') %>%
        ggplot(aes(x = tissue, y = dry_mass)) +
          geom_boxplot() +
          theme_bw()
print(p)

次に、wt 系統と ANU843 系統それぞれについて root_dry_mass および shoot_dry_mass のデータの分布を ボックスプロットで示す。 この際に、組織(root または shoot)に応じて色を塗り分けるようにする。

g <- d %>%
        select(variety, root_dry_mass, shoot_dry_mass) %>%
        pivot_longer(c(root_dry_mass, shoot_dry_mass), names_to = 'tissue', values_to = 'dry_mass') %>%
        ggplot(aes(x = variety, y = dry_mass, fill = tissue)) +
          geom_boxplot() +
          theme_bw() +
          scale_fill_npg()
print(p)

ボックスプロットに実際のデータを重ね書きするとき、 geom_boxplot 関数を実行した後に geom_point 関数を実行する。 このとき、点が重ならないようにするために、position = position_jitterdodge() オプションを指定する。

g <- d %>%
        select(variety, root_dry_mass, shoot_dry_mass) %>%
        pivot_longer(c(root_dry_mass, shoot_dry_mass), names_to = 'tissue', values_to = 'dry_mass') %>%
        ggplot() +
          geom_boxplot(aes(x = variety, y = dry_mass, color = tissue)) +
          geom_point(aes(x = variety, y = dry_mass, color = tissue),
                         position = position_jitterdodge(jitter.width = 0.2, dodge.width=0.8),
                         alpha = 0.3, size = 3) +
          theme_bw() +
          scale_color_npg()

print(p)

geom_hist 関数

geom_hist 関数はヒストグラムを描く関数である。 ここで rice データを使って、ヒストグラムを描く例を示す。

d <- read_tsv('data/rice.txt')
## Parsed with column specification:
## cols(
##   replicate = col_double(),
##   block = col_double(),
##   root_dry_mass = col_double(),
##   shoot_dry_mass = col_double(),
##   trt = col_character(),
##   fert = col_character(),
##   variety = col_character()
## )
df <- d %>% 
        filter(variety == 'wt') %>%
        select(root_dry_mass)
head(df)
## # A tibble: 6 x 1
##   root_dry_mass
##           <dbl>
## 1            56
## 2            66
## 3            40
## 4            43
## 5            55
## 6            66

ヒストグラムは 1 変量変数の分布を可視化するためのグラフであるから、 グラフを描く際に座標を指定するとき、x だけを指定すればよい。 デフォルトでは、ヒストグラムのビン(棒)の数は 30 に設定される。

p <- ggplot(df, aes(x = root_dry_mass)) +
      geom_histogram() +
      theme_bw()
print(p)
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

ビンの幅は geome_histogram 関数の binwidth で変更することができる。 例えば、ビンの幅を 1 にしたい場合は次のようにする。

p <- ggplot(df, aes(x = root_dry_mass)) +
      geom_histogram(binwidth = 1) +
      theme_bw()
print(p)

ビンの幅をスタージェスの公式にしたがって自動的に決めたいときは、 自分でビンの幅を計算する関数を定義する必要がある。

library(grDevices)

sturges.width <- function(x) {
  ceiling ((max(x)- min (x)) / nclass.Sturges(x))
}

scott.width <- function(x) {
  ceiling ((max(x)- min (x)) / nclass.scott(x))
}


p <- ggplot(df, aes(x = root_dry_mass)) +
      geom_histogram(binwidth = sturges.width) +
      theme_bw()
print(p)

geom_histgramcolor を指定するとヒストグラムの外枠の色を変更できるようになる。 また、fill を指定するとヒストグラムの中身の塗りを指定することができる。

p <- ggplot(df, aes(x = root_dry_mass)) +
      geom_histogram(binwidth = 5, color='#00B5E2', fill='#00B5E210') +
      theme_bw()
print(p)

項目数が 2 つある場合、 例えば wt 系統の root_dry_mass と shoot_dry_mass の分布を見たいとき、 fill オプションでその項目名(列名)を指定すればよい。 まず、データセットを用意する。

d <- read_tsv('data/rice.txt')
## Parsed with column specification:
## cols(
##   replicate = col_double(),
##   block = col_double(),
##   root_dry_mass = col_double(),
##   shoot_dry_mass = col_double(),
##   trt = col_character(),
##   fert = col_character(),
##   variety = col_character()
## )
df <- d %>% 
        filter(variety == 'wt') %>%
        select(root_dry_mass, shoot_dry_mass) %>%
        pivot_longer(c(root_dry_mass, shoot_dry_mass), names_to = 'tissue', values_to = 'dry_mass')
head(df)
## # A tibble: 6 x 2
##   tissue         dry_mass
##   <chr>             <dbl>
## 1 root_dry_mass        56
## 2 shoot_dry_mass      132
## 3 root_dry_mass        66
## 4 shoot_dry_mass      120
## 5 root_dry_mass        40
## 6 shoot_dry_mass      108

geom_histogram 関数をデフォルトのオプション(position = 'stack')で描くと、 次のように積み上げヒストグラムになる。

p <- ggplot(df, aes(x = dry_mass, fill  = tissue)) +
      geom_histogram(binwidth = 5) +
      theme_bw() +
      scale_fill_npg()

print(p)

position オプションを position = 'identity' に変更すると、 次のように 2 つの項目が重なった状態で描かれる。 なお、ここで重なりが見えるように透明度を 0.8 に設定してある。

p <- ggplot(df, aes(x = dry_mass, fill  = tissue)) +
      geom_histogram(binwidth = 5, position = 'identity', alpha = 0.8) +
      theme_bw() +
      scale_fill_npg()

print(p)

position オプションを position = 'dodge' に変更すると、 2 つの項目が並んでいる状態で描かれる。

p <- ggplot(df, aes(x = dry_mass, fill  = tissue)) +
      geom_histogram(binwidth = 5, position = 'dodge') +
      theme_bw() +
      scale_fill_npg()

print(p)

position オプションを position = 'fill' に変更すると、次のように 2 つの項目が積み上げた状態で描かれ、それぞれのビンの最大値が 1 となる。

p <- ggplot(df, aes(x = dry_mass, fill  = tissue)) +
      geom_histogram(binwidth = 5, position = 'fill') +
      theme_bw() +
      scale_fill_npg()

print(p)
## Warning: Removed 4 rows containing missing values (geom_bar).

facet_wrap 関数と facet_grid 関数

同じデータセットから複数のグラフを作成し、それらを一つの画像上に表示させたいときは facet_wrap 関数または facet_grid 関数を使用する。 初めに facet_wrap 関数の使い方を紹介する。 まず、データセットを読み込んで ggplot2 で取り扱いやすいように整形する。

d <- read_tsv('data/rice.txt')
## Parsed with column specification:
## cols(
##   replicate = col_double(),
##   block = col_double(),
##   root_dry_mass = col_double(),
##   shoot_dry_mass = col_double(),
##   trt = col_character(),
##   fert = col_character(),
##   variety = col_character()
## )
df <- d %>% 
        select(variety, fert, root_dry_mass, shoot_dry_mass) %>%
        pivot_longer(c(root_dry_mass, shoot_dry_mass), names_to = 'tissue', values_to = 'dry_mass')
head(df)
## # A tibble: 6 x 4
##   variety fert  tissue         dry_mass
##   <chr>   <chr> <chr>             <dbl>
## 1 wt      F10   root_dry_mass        56
## 2 wt      F10   shoot_dry_mass      132
## 3 wt      F10   root_dry_mass        66
## 4 wt      F10   shoot_dry_mass      120
## 5 wt      F10   root_dry_mass        40
## 6 wt      F10   shoot_dry_mass      108

次に、dry_mass 列の値に基づいてヒストグラムを描く。 この際に、すべてのデータを 1 つのヒストグラムに描くのではなく、 variety 列の値(wt, ANU843)ごとにヒストグラムを作成する。 このとき、ヒストグラムを variety 列ごとにサブプロットに分ければよいので、 facet_wrap 関数に variety を指定する。 また、ヒストグラムのサブセットを 2 列に並べて表示させたいので、ncol = 2 のように指定する。

p <- ggplot(df, aes(x = dry_mass, fill = fert)) +
      geom_histogram(binwidth = 5) +
      facet_wrap(~ variety, ncol = 2) +
      scale_fill_jco()
print(p)

サブプロットを 2 行に並べて描く場合は nrow = 2 と指定する。

p <- ggplot(df, aes(x = dry_mass, fill = fert)) +
      geom_histogram(binwidth = 5) +
      facet_wrap(~ variety, nrow = 2) +
      scale_fill_jco()
print(p)

次に facet_grid 関数を紹介する。 facet_wrap 関数はある 1 つの項目(1 つの列の値)に応じてサブプロットを並べる関数である。 これに対して、facet_grid 関数は 2 つの項目(2 つの列の値)に応じてサブプロットを並べる関数である。 以下に系統(variety)と処理(fert)の組み合わせでサブプロット描く例を示す。

系統(variety)と処理(fert)の組み合わせでサブプロット描く。 facet_grid 関数に variety ~ fert のように指定する。 ~ の左側に書かれた項目はサブプロットの各行の項目になり、 ~ の右側に書かれた項目はサブプロットの各列の項目となる。

p <- ggplot(df, aes(x = dry_mass)) +
      geom_histogram(binwidth = 5) +
      facet_grid(variety ~ fert)
print(p)

p <- ggplot(df, aes(x = dry_mass)) +
      geom_histogram(binwidth = 5) +
      facet_grid(fert ~ variety)
print(p)

上で、facet_wrap 関数が 1 つの項目に基づき、 facet_grid 関数が 2 つの項目に基づいてサブプロットを並べる関数であると説明したが、 実はオプションの与え方によって、 両方とも複数の列の値の組み合わせに基づいてサブプロットを並べることができる。 たとえば、facet_wrap 関数を利用して、 variety 列と fert 列の値の組み合わせでサブプロットを並べる場合は、 次のように ~ variety + fert のように指定する。

p <- ggplot(df, aes(x = dry_mass, fill = fert)) +
      geom_histogram(binwidth = 5) +
      facet_wrap(~ variety + fert, nrow = 2) +
      scale_fill_jco()
print(p)

グラフの調整

ここからは軸座標や凡例の調整について説明する。 まず、データセットを読み込んで準備する。

d <- read_tsv('data/rice.txt')
## Parsed with column specification:
## cols(
##   replicate = col_double(),
##   block = col_double(),
##   root_dry_mass = col_double(),
##   shoot_dry_mass = col_double(),
##   trt = col_character(),
##   fert = col_character(),
##   variety = col_character()
## )
head(d)
## # A tibble: 6 x 7
##   replicate block root_dry_mass shoot_dry_mass trt   fert  variety
##       <dbl> <dbl>         <dbl>          <dbl> <chr> <chr> <chr>  
## 1         1     1            56            132 F10   F10   wt     
## 2         2     1            66            120 F10   F10   wt     
## 3         3     1            40            108 F10   F10   wt     
## 4         4     1            43            134 F10   F10   wt     
## 5         5     1            55            119 F10   F10   wt     
## 6         6     1            66            125 F10   F10   wt

ggplot を使ってグラフを描くとき、 aes 関数の x および y オプションに指定した変数の名前がそのまま x 軸および y 軸のラベルになる。 このラベルを後から書き換える時は、labs 関数の中の x および y オプションを使用する。 また、aescolor あるいは fill オプションに項目(データの列名)を指定すると、 その項目の名前がそのままグラフの凡例ラベルになる。 この凡例ラベルを書き換える場合は labs 関数の該当オプション(color あるいは fill)の値を変更すればよい。 labs 関数を使用すると、さらにグラフのタイトルをつけることもできるようになる。 まず、labs 関数を使用しないでグラフを作図してみる。

p <- ggplot(d, aes(x = root_dry_mass, y = shoot_dry_mass,
                   color = interaction(variety, trt, sep = ' / '))) +
      geom_point(size = 4) +
      scale_color_npg()

print(p)

次に labs 関数を加えて描いた図を見比べてみる。 グラフのタイトル、座標軸のラベルや凡例などが書き換わっていることが確認とれる。

p <- p + labs(x = 'root dry mass [g]',
              y = 'shoot dry mass [g]',
              title = 'Relations between the dry mass of roots and shoots',
              color = 'treatments')

print(p)

座標軸やラベルの文字の大きさ、色、そしてフォントスタイル(太字、斜体など)は theme 関数のオプションを通して変更できる。

p <- ggplot(d, aes(x = root_dry_mass, y = shoot_dry_mass,
                   color = interaction(variety, trt, sep = ' / '))) +
      geom_point(size = 4) +
      scale_color_npg() +
      labs(x = 'root dry mass [g]',
           y = 'shoot dry mass [g]',
           title = 'Relations between the dry mass of roots and shoots',
           color = 'treatments') +
      theme(axis.title = element_text(face = 'bold'),
            axis.text.y = element_text(angle = 90, h = 0.5),
            plot.title = element_text(face = 'bold', size = 18, color = 'darkgrey'),
            legend.title = element_text(face = 'bold', size = 14),
            legend.text = element_text(face = 'italic', size = 10))
print(p)

グラフの判例に colorshape の両方が存在するときの調整例。

fontsize <- 16

p <- ggplot(d, aes(x = root_dry_mass, y = shoot_dry_mass, color = variety, shape = fert)) +
      geom_point(size = 4) +
      scale_color_npg() +
      labs(x = 'root dry mass [g]',
           y = 'shoot dry mass [g]',
           title = 'Relations between the dry mass of roots and shoots',
           color = 'variety',
           shape = 'treatment') +
      theme(axis.title = element_text(face = 'bold', size = fontsize),
            axis.text = element_text(size= fontsize),
            axis.text.y = element_text(angle = 90, h = 0.5),
            plot.title = element_text(face = 'bold', size = fontsize, color = 'darkgrey'),
            legend.title = element_text(face = 'bold', size = fontsize- 4),
            legend.text = element_text(face = 'italic', size = fontsize - 4))
print(p)

ggplot では、座標軸のメモリや表示方法などを自由に調整することができる。 例えば、縦軸を指数形式で表示させたり、対数で表示させたりすることができるようになる。 まず、データセットを用意する。

data(msleep)
head(msleep)
## # A tibble: 6 x 11
##   name  genus vore  order conservation sleep_total sleep_rem sleep_cycle awake
##   <chr> <chr> <chr> <chr> <chr>              <dbl>     <dbl>       <dbl> <dbl>
## 1 Chee… Acin… carni Carn… lc                  12.1      NA        NA      11.9
## 2 Owl … Aotus omni  Prim… <NA>                17         1.8      NA       7  
## 3 Moun… Aplo… herbi Rode… nt                  14.4       2.4      NA       9.6
## 4 Grea… Blar… omni  Sori… lc                  14.9       2.3       0.133   9.1
## 5 Cow   Bos   herbi Arti… domesticated         4         0.7       0.667  20  
## 6 Thre… Brad… herbi Pilo… <NA>                14.4       2.2       0.767   9.6
## # … with 2 more variables: brainwt <dbl>, bodywt <dbl>

このデータに対して、座標軸のスケールを変更しないでグラフを描いてみる。

p <- msleep %>% 
      select(name, bodywt, vore) %>%
      drop_na() %>%
      ggplot(aes(x = name, y = bodywt, fill = vore)) +
      geom_bar(stat = 'identity') +
      scale_fill_npg() +
      labs(x = '',
           y = 'body weights [kg]',
           title = 'body weight of mammals',
           color = 'vore') +
      theme_bw() +
      theme(axis.title = element_text(face = 'bold'),
            axis.text.x = element_text(angle = 90, h = 1),
            plot.title = element_text(face = 'bold'),
            legend.title = element_text(face = 'bold'))
print(p)

次に、y 軸を指数表記で描いてみる。 scale_y_continuous 関数を利用し、その labels オプションに scales::scientific を指定する。

p <- msleep %>% 
      select(name, bodywt, vore) %>%
      drop_na() %>%
      ggplot(aes(x = name, y = bodywt, fill = vore)) +
      geom_bar(stat = 'identity') +
      scale_fill_npg() +
      labs(x = '',
           y = 'body weights [kg]',
           title = 'body weight of mammals',
           color = 'vore') +
      theme_bw() +
      theme(axis.title = element_text(face = 'bold'),
            axis.text.x = element_text(angle = 90, h = 1),
            plot.title = element_text(face = 'bold'),
            legend.title = element_text(face = 'bold')) + 
      scale_y_continuous(labels = scales::scientific)
print(p)

y 軸の目盛りはデータの範囲に応じて自動的に等間隔で描かれる。 この目盛りの間隔を調整したい場合は、scale_y_continuous 関数の breaks オプションを利用する。 例えば、1, 10, 100, 1000 のところだけに目盛りの線を入れる場合は、breaks = c(1, 10, 100, 1000) のように指定する。

p <- msleep %>% 
      select(name, bodywt, vore) %>%
      drop_na() %>%
      ggplot(aes(x = name, y = bodywt, fill = vore)) +
      geom_bar(stat = 'identity') +
      scale_fill_npg() +
      labs(x = '',
           y = 'body weights [kg]',
           title = 'body weight of mammals',
           color = 'vore') +
      theme_bw() +
      theme(axis.title = element_text(face = 'bold'),
            axis.text.x = element_text(angle = 90, h = 1),
            plot.title = element_text(face = 'bold'),
            legend.title = element_text(face = 'bold')) + 
      scale_y_continuous(labels = scales::scientific,
                         breaks = c(1, 10, 100, 1000))
print(p)

y 軸を対数スケールで描くこともできる。 この場合、scale_y_continuous 関数の trans オプションに log10 を指定する。 なお、log10 のほかに log2sqrt などを指定することができる。

p <- msleep %>% 
      select(name, bodywt, vore) %>%
      drop_na() %>%
      ggplot(aes(x = name, y = bodywt, fill = vore)) +
      geom_bar(stat = 'identity') +
      scale_fill_npg() +
      labs(x = '',
           y = 'body weights [kg]',
           title = 'body weight of mammals',
           color = 'vore') +
      theme_bw() +
      theme(axis.title = element_text(face = 'bold'),
            axis.text.x = element_text(angle = 90, h = 1),
            plot.title = element_text(face = 'bold'),
            legend.title = element_text(face = 'bold')) +
      scale_y_continuous(trans = 'log10')
print(p)

デフォルトでは、軸座標の指数表記は 1e+03 のように指数部分が e となって表示される。 1e+03 を 1×103 のように「e」ではなく「10」として表示させるためには、 自分では関数を書いて「e」を「10」に置換すればよい。

scientific_notation <- function(x) {
     x <- format(x, scientific = TRUE)
     x <- gsub("^(.*)e", "'\\1'e", x)
     x <- gsub("e", "%*%10^", x)
     x <- gsub('\\+', '', x)
     parse(text = x)
}

p <- msleep %>% 
      select(name, bodywt, vore) %>%
      drop_na() %>%
      ggplot(aes(x = name, y = bodywt, fill = vore)) +
      geom_bar(stat = 'identity') +
      scale_fill_npg() +
      labs(x = '',
           y = 'body weights [kg]',
           title = 'body weight of mammals',
           color = 'vore') +
      theme_bw() +
      theme(axis.title = element_text(face = 'bold'),
            axis.text.x = element_text(angle = 90, h = 1),
            plot.title = element_text(face = 'bold'),
            legend.title = element_text(face = 'bold')) +
      scale_y_continuous(trans = 'log10', labels = scientific_notation)
print(p)

サブプロット

複数の ggplot グラフを 1 つの画面(デバイス)上で並べて表示せるときに、 ggpubr や gridExtra などのパッケージを使うと便利である。 まず、iris のデータセットを使って複数のグラフを描いてみる。

data(iris)
head(iris)
##   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1          5.1         3.5          1.4         0.2  setosa
## 2          4.9         3.0          1.4         0.2  setosa
## 3          4.7         3.2          1.3         0.2  setosa
## 4          4.6         3.1          1.5         0.2  setosa
## 5          5.0         3.6          1.4         0.2  setosa
## 6          5.4         3.9          1.7         0.4  setosa
p1 <- ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
        geom_point() + scale_color_npg()
p2 <- ggplot(iris, aes(x = Petal.Length, y = Petal.Width, color = Species)) +
        geom_point() + scale_color_npg()

ggpubr を使って 2 つのグラフ p1 および p2 を描いてみる。

ggpubr::ggarrange(p1, p2)

ggarange 関数の ncol または nrow オプションを使うことで、 グラフを並べるときの行数や列数を指定することができる。

ggpubr::ggarrange(p1, p2, nrow = 2)

ggarrange 関数の common.legend = TRUE オプションを使用することで、 同じ種類の凡例を 1 箇所にまとめることができるようになる。

ggpubr::ggarrange(p1, p2, common.legend = TRUE, legend = 'bottom')

ggpubr パッケージを使用するとき、ggplot のグラフはグリッド状に並べ替えることができる。 さらに柔軟な並べ替えを行うには、gridExtra パッケージを使用すると便利である。

layout <- matrix(c(1, 1, 2, 2, 1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 4), ncol = 4)
layout
##      [,1] [,2] [,3] [,4]
## [1,]    1    1    3    3
## [2,]    1    1    3    3
## [3,]    2    2    3    3
## [4,]    2    2    4    4
p3 <- ggplot(Orange, aes(x = age, y = circumference, color = factor(Tree))) +
          geom_line() + scale_color_npg()
p4 <- ggplot(cars, aes(x = speed, y = dist)) + geom_point()

gridExtra::grid.arrange(p1 + theme(legend.position = 'none'),
                        p2 + theme(legend.position = 'bottom', legend.title=element_blank()) +
                          guides(col = guide_legend(nrow = 1)) + 
                          labs(),
                        p3,
                        p4,
                        layout_matrix = layout)

グラフの保存

グラフの保存は ggsave 関数を利用する。 その際に、グラフの横幅と縦幅をインチで指定することができる。 解像度も合わせて指定できる。 画像サイズが大きいとき、解像度 dpi も大きめに指定することで、 グラフの座標軸ラベルや目盛り、凡例などの文字も大きくなり、きれいなグラフが仕上がる。

d <- read_tsv('data/rice.txt')
p <- ggplot(d, aes(x = root_dry_mass, y = shoot_dry_mass)) +
      geom_point()

# 7 x 5 inches
ggsave("figure-1.pdf", g)

# 10 x 8 inches
ggsave("figure-1.pdf", g, width = 10, height = 8)

# 10 x 8 inches, with 300 dpi
ggsave("figure-1.pdf", g, width = 10, height = 8, dpi = 300)

R の画像保存用の標準関数を使用して、グラフを保存することもできる。 例えば、ggplot を使ってグラフ p を作り終えたとする。 このグラフを保存したい場合は、この print(p)png および dev.off 関数で囲んで実行すればよい。 ここで、print(p) の代わりに plot(p) を使っても可能だが、 for 文の中で plot(p) を使うと、場合によってグラフを保存できない場合もあるので注意。 なお、上述通り、大きなサイズでグラフを保存したい場合は、解像度(res)も大きめに設定するとグラフがきれいに仕上がる。

d <- read_tsv('data/rice.txt')
p <- ggplot(d, aes(x = root_dry_mass, y = shoot_dry_mass)) +
      geom_point()

png('figure-1.png', width = 1024, height = 768, res = 300)
print(p)
dev.off()
CC BY 4.0