Chapter 5 グラフ

データをグラフで表現する方法について学ぶ。

データの傾向をグラフによって表現することを可視化(visualization)という。この章では、ggplot2パッケージを使って、データを可視化する方法について学んでいく。

まずは、ggplot2パッケージをロードする。

library(ggplot2) 

5.1 なぜ可視化が重要か?

データを解析する際には、単に平均値など数値を確認するだけではなく、必ずデータの分布を確認する習慣を身に着けよう。

例えばデータに極端に高い値があったりする場合は、代表値として平均値を使うのは適切でないことがわかったりする。データが正規分布と違うかたちをしているか、データの中に外れ値はないかなど、分布の形状をデータ解析の前に確認しておくことは重要である。

5.2 Rのグラフィック関数

Rには標準でグラフを作成するための関数がいくつか用意されている。

5.2.1 plot

plotはグラフを作る基本となる関数である。

#サンプルデータをつくる
sample = data.frame(
  x = 1:5,
  y = c(2, 5, 7, 11, 9)
)
sample
##   x  y
## 1 1  2
## 2 2  5
## 3 3  7
## 4 4 11
## 5 5  9
plot(x = sample$x, y = sample$y)

plot()にx軸とy軸にプロットするデータをベクトルのかたちで入れると、図を作成してくれる。 更に、plot()関数では、自分の好みに合わせてグラフの体裁を変えることもできるオプションも用意されている。

5.2.1.1 オプションの指定

以下に例として、様々なオプションを変更したグラフを示す。

plot(x = sample$x, y = sample$y, 
     type = "b", #type: グラフの種類
     pch = 2, #点の種類
     cex = 1.5, #点の大きさ
     lty = "dotted", #線の種類
     lwd = 2, #線の太さ
     col = "blue", #色
     xlim = c(0,6), #x軸の範囲(最小値, 最大値)
     ylim = c(0,15), #y軸の範囲(最小値, 最大値)
     las = 1, #軸の文字の配置
     main = "Graph", #グラフのタイトル
     xlab = "x value", #x軸のラベル
     ylab = "y value" #y軸のラベル
     )

type: グラフの種類を変える(“p” = 点(デフォルト)、 “l” = 線、 “b” = 点と線の両方、“n” = 何も描画しない、など)。
pch: 点の種類を指定(0 = 四角、1 = 丸(デフォルト)、2 = 三角、など)。
cex: 点の大きさを指定。数値を入力する。
lty: 線の種類を指定(“solid” = 実線(デフォルト)、“dotted” = ドット、“dashed” = ダッシュ、など)
lwd: 線の太さの指定。数値を入力する。
col: 色を変更する。“red”, “blue”など色の名前を指定する。
xlim, ylim: それぞれx軸とy軸の最小値と最大値を指定。
las: 軸の文字の配置を指定(1 = x軸もy軸も水平方向)。
main, xlab, ylab: それぞれグラフのラベルを指定。

他にもどのようなオプションを指定できるか確認したい場合は、ヘルプを参照。?parsと入力するとヘルプが表示される。

5.2.2 その他のグラフ

以下では、Rで標準でに入っているサンプルデータ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

5.2.2.1 散布図

plot()で作成する。

plot(x = iris$Sepal.Length, y = iris$Sepal.Width) 

5.2.2.2 ヒストグラム

hist()で作成する。

hist(iris$Sepal.Length, 
     breaks = 20, #breaksでビン(棒)の数を指定できる
     col = "red",
     main = "Histgram", xlab = "Sepal Length", ylab = "Frequency") #その他のオプションも指定可能

5.2.2.3 箱ひげ図

boxplot()で作成する。

boxplot(x = iris$Sepal.Length,
     main = "Boxplot", 
     col = "red",
     xlab = "Sepal Length") #その他のオプションも指定可能

boxplot(data = iris, Sepal.Length ~ Species, 
        main = "Boxplot", 
        col = c("red", "blue", "green"),
        xlab = "Sepal Length") #グループごとに示す場合

5.2.3 グラフを重ねる

同じグラフの中でグループ別にデータを表示したい場合は、例えば以下のようにグラフを重ねて描画していくかたちで表現することができる。

以下に例として、irisデータのSpeciesごとに色や点の形を変えて散布図を示してみる。
まず、グラフの領域を作成して、その上にグループ別にpointlinesなどで点や線を重ねていくかたちで描画していく。

#該当する部分を取り出してベクトルに格納する。
Sepal.Length_setosa <- iris$Sepal.Length[iris$Species == "setosa"]
Sepal.Width_setosa <- iris$Sepal.Width[iris$Species == "setosa"]

Sepal.Length_versicolor <- iris$Sepal.Length[iris$Species == "versicolor"]
Sepal.Width_versicolor <- iris$Sepal.Width[iris$Species == "versicolor"]

Sepal.Length_virginica <- iris$Sepal.Length[iris$Species == "virginica"]
Sepal.Width_virginica <- iris$Sepal.Width[iris$Species == "virginica"]

plot(0, 0, type = "n", xlim = c(3.5, 8.5), ylim=c(0, 6), xlab = "Sepal Length", ylab = "Sepal Width")#まず、空のプロットを作る(軸の範囲やラベルを指定する)
points(x = Sepal.Length_setosa, y = Sepal.Width_setosa, col = "red", pch = 0)
points(x = Sepal.Length_versicolor, y = Sepal.Width_versicolor, col = "blue", pch = 1) 
points(x = Sepal.Length_virginica, y = Sepal.Width_virginica, col = "orange", pch = 2) 
legend("topleft", legend = c("setosa", "versicolor", "virginica"), pch = c(0, 1, 2), col = c("red", "blue", "orange")) #legendで凡例を重ねることもできる。

5.2.4 図の保存

#png形式で保存する場合
png("plot.png", height = 400, width = 400)  #ファイル名を指定する。画像サイズも任意に指定できる(特に指定しなくても出力してくれる)。
plot(x = iris$Sepal.Length, y = iris$Petal.Length) #グラフを作る
dev.off()    #描画デバイスを閉じる

RStudio ならば、右下の「Plots」ウィンドウの「Export」から保存することも可能。

5.3 ggplot2パッケージ

手っ取り早くデータの分布や相関を確認したい場合は、plotなどの関数を使えば十分である。plotなどでもオプションを駆使すれば研究報告向きのグラフを作れないこともないが、プログラムやオプションの指定の方法も複雑で、作成できるグラフの種類も少ない。

これに対し、様々なグラフを作る機能に特化したggplot2というパッケージがある。以降で、ggplot2の基本的な使い方について解説する。

早速、ggplot2を使ってグラフを作ってみよう。以下のプログラムを実行してみよう。

p = ggplot2::ggplot() + 
  geom_point(data = iris, aes(x=Sepal.Length, y=Petal.Length)) + 
  labs(x = "Length of sepal", y = "Length of petal") 
p

プログラムの解説:

ggplot():初期設定。「ggplot2を使ってグラフを書きます」という意味。必ず書く。カッコの中には何も入れなくて良い。

geom_xxxx():グラフの種類の指定。必ず書く。xxxxには、グラフの種類を入力する。この例では、散布図を書くのでgeom_pointを指定した。更に、カッコの中に必要な設定を記す。

data =でグラフを描画するデータを指定する。
更に、aes()のカッコの中に描画に必要な要素を指定する。x=y=でそれぞれ、 x軸とy軸に指定したい変数を指定する。点の大きさ、色、線の種類など、グラフの種類によって指定できる要素がある。

オプション:上での例では、labs()でx軸やy軸のラベルを指定している。他にも、軸の値の範囲、軸のラベル、グラフの色の設定などをオプションで指定することができる。オプションを加えなくてもグラフは出力される。

とりあえず、これらだけ知っておけばggplot2でグラフを作れる。

5.3.1 散布図

geom_pointで作成できる。

p = ggplot2::ggplot() + 
  geom_point(data=mpg, aes(x=cty, y=hwy, shape = fl)) 
p

この例では、shape =でグループを指定して、グループごとに点のかたちを変えた散布図を作成した。

点が重なって見えにくい場合は、geom_jitterを使うとランダムのズレを生成して表示してくれる。

p = ggplot2::ggplot() + 
  geom_jitter(data=mpg, aes(x=cty, y=hwy, shape = fl)) 
p

5.3.2 ヒストグラム

geom_histogramで作成する。

p = ggplot2::ggplot() + 
  geom_histogram(data = iris, aes(x=Sepal.Length))  #xに、横軸にしたい変数を入れる。
p

p = ggplot2::ggplot() + 
  geom_histogram(data = iris, aes(x=Sepal.Length, fill = Species))  #種類ごとに色の塗りつぶしを変えたい場合は、fillに指定する。
p

p = ggplot2::ggplot() + 
  geom_histogram(data = iris, aes(x=Sepal.Length, color = Species))  #colorだと周りの線の色を変える。
p

5.3.3 箱ひげ図

geom_boxplotで作成する。

最小値、第一分位点、中央値、第三分位点、最大値を示す(外れ値は点で示される)。

p = ggplot2::ggplot() + 
  geom_boxplot(data = InsectSprays, aes(x=spray, y=count))
p

p = ggplot2::ggplot() + 
  geom_boxplot(data = InsectSprays, aes(x=spray, y=count, fill = spray))
p

5.3.4 バイオリンプロット

データの分布を表現したグラフ。 geom_violinで作成する。

p = ggplot2::ggplot() + 
  geom_violin(data = InsectSprays, aes(x=spray, y=count))
p

p = ggplot2::ggplot() + 
  geom_violin(data = InsectSprays, aes(x=spray, y=count, fill = spray))
p

5.3.5 折れ線グラフ

geom_line()を使う。geom_line()だけだと線のみだが、geom_point()で作ったグラフを重ねることで、点もつけることができる。このように、複数のグラフを重ねて描画することもできる

#サンプルデータをつくる: 10日間の気温の変化
temperature = data.frame(
    Days  = 1:10, 
    Celsius = c(17.2, 17.5, 18.1, 18.8, 19.0, 19.2, 19.7, 20.2, 20.5, 20.1)
)
temperature
##    Days Celsius
## 1     1    17.2
## 2     2    17.5
## 3     3    18.1
## 4     4    18.8
## 5     5    19.0
## 6     6    19.2
## 7     7    19.7
## 8     8    20.2
## 9     9    20.5
## 10   10    20.1
p = ggplot2::ggplot() + 
  geom_line(data = temperature, aes(x=Days, y=Celsius)) + 
  geom_point(data = temperature, aes(x=Days, y=Celsius)) 
p

5.3.6 エラーバーつきのグラフ

geom_errorbar()でエラーバーをつけることができる。 あるいは、geom_pointrange()でも作れる。

#サンプルデータをつくる
sample_dat = data.frame(Condition=c("A", "B" ,"C"), 
                        mean=c(2, 5, 8), 
                        lower=c(1.1, 4.2, 7.5), 
                        upper=c(3.0, 6.8, 9.1))
#meanが平均、lowerとupperにそれぞれ下限値と上限値。

p = ggplot2::ggplot() + 
  geom_point(data = sample_dat, aes(x = Condition, y = mean)) + 
  geom_errorbar(data = sample_dat, aes(x = Condition, ymax = upper, ymin = lower), width = 0.1) 
#まず、geom_pointで平均を点で示したグラフを作成する。そのグラフに、ymaxとyminにそれぞれ上限値と下限値を指定したエラーバーのグラフを重ねる(widthでエラーバーの横の長さを指定できる)。
p

p2 = ggplot2::ggplot() + 
  geom_pointrange(data = sample_dat, aes(x = Condition, y = mean, ymax = upper, ymin = lower)) 
#geom_pointrangeならば、点とエラーバーの両方を一括して指定できる。
p2

5.4 オプション

5.4.1 ファセット(Facet)

グループごとにグラフを分けたい場合は、ファセット(facet)を利用すると良い。facet_wrap()を使う。

p = ggplot2::ggplot() +
  geom_point(data = iris, aes(x=Sepal.Length, y=Petal.Length)) + 
  facet_wrap(vars(Species)) 
p

5.4.2 ラベル(labs)

x軸やy軸のラベルを変えたいときは、labsを使うと良い。

p = ggplot2::ggplot() +
  geom_point(data = iris, aes(x=Sepal.Length, y=Petal.Length)) + 
  labs(x = "Length of sepal", y = "Length of petal")
p

5.4.3 テーマ(Theme)

theme()で、フォントの大きさや色などグラフのテーマも細かく変えることができる。具体的にどの部分を変えられるかは、theme()のヘルプで確認してほしい。

p = ggplot2::ggplot() +
  geom_point(data = iris, aes(x=Sepal.Length, y=Petal.Length)) 
p + theme(axis.title.x = element_text(size = 20)) #x軸のフォントサイズを変える

p + theme(panel.background = element_rect(fill = "white", colour = "black")) #背景や枠線の色を変える

手っ取り早く一括でテーマを変えたい場合は、予め用意されている既存のテーマを選ぶと良い。theme_bw(), theme_classic()などが用意されている。

p = ggplot2::ggplot() +
  geom_point(data = iris, aes(x=Sepal.Length, y=Petal.Length)) 
p + theme_bw()

p + theme_gray()

p + theme_classic(base_size = 20) #base_sizeで軸や軸ラベルなどのバランスを考慮した上でフォントサイズを整えることができる

5.5 図の保存

ggplot2パッケージのggsave()で保存できる。plotに保存した図を、filenameにファイル名を指定すると、ワーキングディレクトリに作成した図が保存される。

p = ggplot2::ggplot() + 
  geom_point(data = iris, aes(x=Sepal.Length, y=Petal.Length)) + 
  labs(x = "Sepal Length", y = "Petal Length") + 
  theme_bw()

ggplot2::ggsave(plot = p, filename = "plot.png") #ファイル名を指定する。拡張子も忘れずにつける。
ggplot2::ggsave(plot = p, filename = "plot_2.png", dpi = 300) #解像度(dpi)を指定可能。
ggplot2::ggsave(plot = p, filename = "plot_3.png", width = 8, height = 5) #幅(width)や高さ(height)を指定可能(単位はインチ)。

5.6 応用的なグラフ

その他のパッケージとの併用で、更に応用的なグラフの作成も可能である。

5.6.1 Rain-cloud plot

箱ひげ図、密度曲線、ドットプロットをあわせて表示したもの。データの分布がよりわかりやすい。

以下は、ggplot2ggdistパッケージを使って作図した例である。

library(ggdist)

ggplot2::ggplot()+
  ggdist::stat_halfeye(data = iris, aes(x = Species, y = Sepal.Length, fill = Species), width = 0.5,.width = 0, point_colour = NA, position = position_nudge(x = 0.2)) +
  geom_boxplot(data = iris, aes(x = Species, y = Sepal.Length, fill = Species), width=0.2, outlier.color = NA, position = position_nudge(x = 0)) +
  geom_jitter(data = iris, aes(x = Species, y = Sepal.Length), width = 0.05,alpha = 0.5) + 
  coord_flip() +
  labs(y = "Sepal Length", x = "Species") + 
    theme_bw() 

5.6.2 Ridge plot

密度曲線をグループ別に示したもの。

以下は、ggplot2ggridgesパッケージを使って作図した例である。

library(ggridges)

ggplot2::ggplot()+
  ggridges::geom_density_ridges(data = iris, aes(x = Sepal.Length, y = Species, fill = Species), alpha = 0.5, scale = 1)  +
  labs(x = "Sepal Length", y = "Species") + 
  theme_bw()

5.6.3 Alluvial plot

複数のカテゴリの分類をフローの形式で表現したグラフ。ggalluvialパッケージを使って作図する。

library(ggalluvial)

UCBAdmissions_2 = data.frame(UCBAdmissions) #サンプルデータUCBAdmissionsを使ってみる。データフレーム形式に修正する。
head(UCBAdmissions_2) #カテゴリ別に頻度を集計したデータフレームを用意する。
##      Admit Gender Dept Freq
## 1 Admitted   Male    A  512
## 2 Rejected   Male    A  313
## 3 Admitted Female    A   89
## 4 Rejected Female    A   19
## 5 Admitted   Male    B  353
## 6 Rejected   Male    B  207
ggplot2::ggplot(data = UCBAdmissions_2, aes(axis1 = Gender, axis2 = Dept, axis3 = Admit, y = Freq)) +
  ggalluvial::geom_alluvium(aes(fill = Admit))  +
  ggalluvial::geom_stratum() + 
  ggplot2::geom_text(stat = "stratum", aes(label = after_stat(stratum))) +
  scale_x_discrete(limits = c("Gender", "Dept", "Admit")) +
  labs(x = "", y = "Frequency") + 
  theme_bw()

5.7 その他の機能

ggplot2の機能はまだまだある。このテキストで説明しきれていないことについては、関数のヘルプやRStudioのサイトにあるggplot2のCheat sheetを見てみよう(日本語訳もある)。
https://rstudio.com/resources/cheatsheets/

確認問題

Rに標準で入っているmtcarsデータを使って、グラフを作成しよう。

問1

Rで標準で入っているhist()を使って、変数mpgのヒストグラムを作ろう。

問2

Rで標準で入っているplot()を使って、変数mpgと変数wtの散布図を作ろう。

問3

ggplot()で、変数mpgと変数wtの散布図を作ろう。グラフには以下の点を反映させること。

  • x軸をmpg、y軸をwtとする。
  • x軸のラベルは「Miles/gallon」、y軸のラベルは「Weight」とする。
  • テーマはtheme_classic()にする。