• ここで必要な R パッケージ
library(gghighlight)
library(ggplot2)# {tidyverse} 内に含まれている
library(ggrepel)
library(magrittr)    # {tidyverse} 内に含まれている
library(patchwork)
library(plotly)
library(reactable)

1. R でグラフを描く方法

  • R 上でグラフを描く方法は次の 2 つ
1. Base R Rに内蔵されている関数
2. ggplot2 要素を「層」(layer) のように積み重ねてグラフを描く
  • Base R{ggplot2} を使って散布図を描くとこんな感じになる

  • Base R でも {ggplot2}でも同じようなグラフが描ける
  • Base R でもかなり精度の高い便利な図が描ける
  • しかし、{ggplot2} を使った方が圧倒的に便利

2. {ggplot2} とは

  • Hadley Wickham(R 作成者) が大学院生の時に開発した可視化パッケージ
  • ggplot: the grammer of graphics
  • Hadley Wickham による無料のオンラインバージョン ggplot2 が公開されている

2.1 {ggplot2} パッケージの特徴

1. Wilkinson, L. (2005) による文法を実装
2. 図の構成要素に対応する関数が存在し、それらの関数が 1 つのレイヤーとして機能する

2.2 {ggplot2} が優れている点

  1. 読みやすいコードで見た目の整ったグラフ作成が可能である
  2. グラフの見た目の変更が簡単
  3. さほど細かい調整をしなくても完成度の高いグラフが作成できる
  4. グラフ作成の再現性が保証されていて、グラフィックスの文法 (grammar) をコードとして記述できる
  5. グラフの構成要素として層(レイヤー:layer) を重ねている
  6. データ探索のツールとして優れている
  7. データを可視化するための拡張パッケージが豊富
  8. 有益な ggplot コミュニティを活用できる

2.3 {ggplot2} パッケージの準備

  • {ggplot2} パッケージを使うために、{tidyverse} をインストールしてから読み込む
  • {tidyverse} は R を使ったデータ分析に必要なパッケージが複数含まれているので大変便利
  • {tidyverse}{ggplot2} は内包されている
    {tidyverse} を読み込めば {ggplot2} は自動的に読み込まれる  

  • {tidyverse} を使うためには次の 2 つの作業が必要
{tidyverse} のインストール
  • RStudioConsole に次のように打ち込んで、Return key を押す(一度だけ実行すればよい)
install.packages("tidyverse")
{tidyverse} の読み込み
  • RStudioRmdファイル上のチャンクの中に次のように打ち込んでから、knit する
library(tidyverse)

3. ggplot2 の構造

  • ここでは、まず {ggplot2} の構造を解説
  • 一例として、散布図を描き、さらに使いやすくカスタマイズする方法を解説
  • 散布図を描くために必要な必要最小限の要素は 3 つ

{ggplot2} で散布図を描くために必要な項目

項目 関数 役割
1. データを指定 ggplot(data = ) データを選ぶ
2. 変数を指定 aes() 変数 (x, y など) を指定
3. グラフの種類(ジオメトリ)を指定 geom_*() グラフの種類を指定
1. データを選ぶ   
  • ggplot を使ってグラフを描く際には、人間にとって読みやすいデータではなく、パソコンにとって読みやすい「整然データ」 (tidy data) を使う
  • 「整然データ」 (tidy data) に関しては「1. データ・ハンドリング(応用)」 を参照
2. 変数を指定
  • x 軸や y 軸を選ぶことを「マッピング (mapping)」と呼ばれる
  • マッピングとはグラフ上の点、線、面などの情報をデータと変数に対応させること
  • データをどのような形態で出力させるということを指定する
  • マッピングでは aes関数を使う
  • aes関数の aes()aesthetics (エステティック)の略
  • 日本語では「審美的属性」と呼ばれる
  • aes() 内では複数の引数を指定することも可能
3. グラフの種類を指定
  • 適切な幾何オブジェクト geom_*() を選び描くグラフのタイプを決める
  • 良く使われる代表的なジオメトリは次のとおり

様々な geom_*() 関数 

変数 可視化の方法 幾何オブジェクト = geom_*()関数
離散変数 棒グラフ geom_bar()
連続変数 ヒストグラム geom_histogram()
連続変数 箱ひげ図 geom_box()
連続変数 散布図 geom_point()
連続変数 折れ線グラフ geom_line()
連続変数 ロリポップチャート geom_point()
  • ここでは、散布図を描くための幾何オブジェクト geom_point() 関数を使う

ggplot2 で図が完成するまでのイメージ図

  • {ggplot2} では図の要素をレイヤー(層)と捉える
  • このレイヤーを生成する関数が ggplot(), geom_point(), scale() などの関数
  • これらの関数を「+]演算子を用いてレイヤーを重ねて図を描く    
  • 最初に散布図を描くために必須要素である ggplot(), aes(), geom_point() を設定する
  • 必要に応じて、scale 関数を使ってグラフの色や形を変更したり、coord 関数を使って軸を調整したり様々なカスタマイズが可能
  • {ggplot2} を使ってグラフを描くイメージは次のとおり

{ggplot2} で図が完成するまでのイメージ図

散布図を描くための必須項目
見た目を調整するためのレイヤー(データのカスタマイズ)
見た目を調整するためのレイヤー(データを俯瞰する)

実際の架空データを使って散布図を描いてみる

  • 例えば、使うデータが df1、横軸に数学の試験点数 (math)、縦軸に統計学の試験点数 (stat) の散布図を描き、性別 gender ごとに色を変えたいとする
  • グラフ全体に審美的属性を割り当てるには 2 つ方法がある
割当の適応範囲
(1) aes関数を独立したレイヤとして指定 グラフ全体
(2) ggplot() 関数内に mapping 引数を指定 グラフ全体
(1) aes関数を独立したレイヤとして実行する場合
library(ggplot2) # ライブラリ読み込み  
ggplot(data = df1) + # データを指定
    # aes関数を独立したレイヤとして実行
  aes(x = math,   # x 軸を指定
 y = stat,        # y 軸を指定    
 color = gender) +   # 性別で色分け表示の指定
  geom_point()    # グラフは散布図と指定

(2) ggplot() 関数内に mapping 引数で実行する場合
library(ggplot2) # ライブラリ読み込み  
ggplot(data = df1,  # データを指定 
  mapping = aes(x = math,# x 軸を指定
  y = stat,    # y 軸を指定
  color = gender)) +  # 性別で色分け表示の指定
  geom_point()   # グラフは散布図と指定
  • (2) を実行すると、(1) と同様の出力が得られる

審美的属性( 「aes 関数」 = 「mapping 変数」)の指定方法 ・上では下のコードを使って散布図を描いたが、審美的属の挿入場所を変えることで、3 通りの表現が可能である

1. aes() を独立したレイヤとして位置づけた場合 

ggplot(df1) +          # df = は省略できる
  aes(x = math,# aes() は独立したレイヤ
 y = stat,       
 color = gender) +  
  geom_point()       

2. aes()ggplot() の内側に指定した場合

= aes関数を ggplot() 関数の mapping 引数に指定した場合

ggplot(df1,
  mapping = aes(x = math, # mapping = は省略できる
  y = stat,
  color = gender)) +
  geom_point()

3. aes()geom_point() の内側に指定した場合

= aes関数を geom_point() 関数の mapping 引数に指定した場合

ggplot(df1) +
  geom_point(mapping = aes(x = math, # mapping = は省略できる
y = stat,
color = gender))

  • これで簡単な散布図は描ける
  • しかし、論文で使う図としてはまだまだ不十分
  • 様々なレイヤー(層)を追加することでグラフの見た目をカスタマイズできる

見た目を調整するための代表的な 10 のレイヤー

構成要素 {パッケージ}:関数() 役割
1. 凡例・軸のラベル labs*() 凡例・軸ラベルの処理
2.テーマ theme_(), theme_*() グラフのみかけの設定
3. 座標系(Coordinate System) coord_*() グラフの座標系への処理
4. 統計処理 stat_*() データの統計処理
5. スケール scale_*()_ グラフの色や形を変更
6.点の注釈 {ggrepel} ポイントに注釈を付ける
7.ハイライト {gghighlight} データを強調して表示
8.ファセット facet_*() データとグラフの分割
9. パッチワーク {patchwork} 複数のグラフを並べる
10.グラフの対話的操作 {plotly} インターアクティブなグラフ作成
注意:
  • 3. 座標系」は {ggplot2} が自動的に設定してくれる(カスタマイズも可能)
  • 7. ハイライト」を使うためには {gghighlight}を読み込む必要がある

4. {ggplot2}で簡単な散布図を描いてみる

4.1 シンプルな散布図

  • ここでは、仮想データを作り、散布図を描いてみる
  • x 軸に「数学の試験点数」、y 軸に「統計学の試験点数」
  • 男女別に色分けして表示したいとする
  • 図を描くためには、まずデータが必要なので、データを準備する

Step 1: データの用意

  • 架空のデータフレーム (data.frame) df を作る
# まず変数を 4 つ作る  
name <- c("Joe", "Ze'ev", "David", "Mike", "Ross", "Woojin", "Inha", "Jih-wen", 
  "Mark", "Dennis", "Carol", "Shira",  "Mimi", "Amital", "Rachel", "Ariel", 
  "Kelly", "RongRong", "Kathy", "Barbara")
math <- c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 2, 4, 5, 6, 7, 9, 8, 9, 8, 10)
stat <- c(2, 4, 6, 5, 7, 9, 7, 10, 12, 15, 14, 13, 12, 13, 11, 10, 9, 8, 6, 4)
gender <- c("Male", "Male", "Male", "Male", "Male", "Male", "Male", "Male", "Male", 
    "Male", "Female", "Female", "Female", "Female", "Female", "Female", 
    "Female", "Female", "Female", "Female")

# 作成した 4 つの変数をまとめて df というデータフレームにする  

df1 <- tibble(name, math, stat, gender)
  • 上で作った架空のデータフレーム (data.frame) df1 の中身を確認してみる
df1
# A tibble: 20 × 4
   name      math  stat gender
   <chr>    <dbl> <dbl> <chr> 
 1 Joe          1     2 Male  
 2 Ze'ev        2     4 Male  
 3 David        3     6 Male  
 4 Mike         4     5 Male  
 5 Ross         5     7 Male  
 6 Woojin       6     9 Male  
 7 Inha         7     7 Male  
 8 Jih-wen      8    10 Male  
 9 Mark         9    12 Male  
10 Dennis      10    15 Male  
11 Carol        2    14 Female
12 Shira        4    13 Female
13 Mimi         5    12 Female
14 Amital       6    13 Female
15 Rachel       7    11 Female
16 Ariel        9    10 Female
17 Kelly        8     9 Female
18 RongRong     9     8 Female
19 Kathy        8     6 Female
20 Barbara     10     4 Female
  • これで図を描くために必要なデータはそろった

データを指定する: ggplot()

  • これは aes関数を使ったマッピング (Mapping) = 審美的属性の指定のこと
  • データ df1ggplot() 関数に渡し、作図の準備をする
  • ggplot() には datamapping という 2 つの引数がある
  • ここではまず、グラフを描くために使う 1 つめの引数 datadf1 に指定して、キャンバスを表示させる
    → data = df1
ggplot(data = df1) # データとして df1 を与える  

  • 何もないまっさらなキャンバスができた

Step 2: 変数を指定

  • +」を使って新たなレイヤー aes() を追加する
  • エステティックな要素とデータの紐付けを行う
  • data として与えられている df1 の中の変数から x 軸に mathy 軸に stat を割り当てる
  • ここではエステティックな要素として x 軸に mathy 軸に stat を追加し紐付けする
    → aes(x = math, y = stat)
ggplot(data = df1) +
  aes(x = math, y = stat) 

  • これで、x 軸に mathy 軸に stat が表示された

Step 3: グラフの種類(ジオメトリ)を指定

  • 散布図を描くための幾何オブジェクト geom_point() を選ぶ
  • +」を使ってジオメトリ・レイヤー geom_point() を追加する
ggplot(data = df1) +
  aes(x = math, y = stat) +
  geom_point()

  • これで、散布図が表示できた

  • 上のコードでは「+」を使って aes(マッピング) を追加している

  • 独立したレイヤである aes(マッピング)をジオメトリ geom_point() の中に入れることもできる

  • 幾何オブジェクト関数 geom_point() 内に エステティック要素 aes() をマッピングする

  • geom_point() 内では mapping = でマッピングが必要

  • aes() の中にはグラフ上に出力される点、線、面などがデータのどの変数に対応するかを記述
    → ここでは aes() の中に x 軸が mathy 軸が stat、そして点の色が gender に対応すると記述

ggplot(data = df1) +
  geom_point(mapping = aes(x = math, 
y = stat, 
color = gender))    

  • data =mapping = は第一引数で、どちらも省略できる
    → 上のコードは次のように簡略化できる  
ggplot(df1) +
  geom_point(aes(x = math, 
   y = stat, 
   color = gender))    
  • さらに、パイプ演算子 ( %>% もしくは %>%) を使って、第一引数を次のように渡すこともできる
df1 %>% 
  ggplot() +
  geom_point(aes(x = math, 
   y = stat, 
   color = gender))    

エステティック要素 aes() のマッピングと省略

エステティック要素 aes() の指定場所(まとめ)Step 2: マッピング(エステ)では、エステティック要素 aes(x = math, y = stat)ggplot(data = df1) の後ろに「+」でつないで追加している

ggplot(data = df1) +
  aes(x = math, y = stat) +
  geom_point()

aes(x = math, y = stat)ggplot()の内側だけでなく、geom_point() の内側にも 追加することができる

  • つまり、上のコードにエステティック要素 aes() を指定する方法は 2 通りあるということ
ggplot() の内側に指定する場合
df1 %>% 
  ggplot(aes(x = math, 
y = stat, 
color = gender) +
  geom_point()    
geom_plot() の内側に指定する場合
df1 %>% 
  ggplot() +
  geom_point(aes(x = math, 
   y = stat, 
   color = gender))    
  • どちらに指定するかということは、どのような分析をしたいかによって異なる

便利なパイプ %>% 演算子{tidyverse} のパッケージ群は、関数同士をパイプ %>% と呼ばれる演算子でつなぐ
→ 処理をひとつながりに記述できる
パイプ %>%{tidyverse} に含まれている {magrittr}パッケージに含まれている
→ パイプ %>% を使うためには次のいずれかの読み込みを実行する

library(magrittr)  
library(tidyverse)

・パイプ %>% 演算子の挙動は「左辺の値を右辺の関数の第一引数に引き渡す」

パイプ %>% 演算子の活用例
  • 1 から 10 までの数のベクトルを生成する
1:10
 [1]  1  2  3  4  5  6  7  8  9 10
  • 1 + 2 + .... + 10 を計算してみる
sum(1:10)
[1] 55
  • これをパイプ %>% 演算子を使うと
1:10 %>%  #「1から10までの数を生成し」  
  sum()  #「それらの数を合計する」
[1] 55
  • 得られた値の平均を求めたければ
1:10 %>%    #「1から10までの数を生成し」
  sum() %>% #「それらの数を合計する」
  sqrt()   #「そしてその合計の平方根を計算する」 
[1] 7.416198
  • 「1から10までの数を生成し」
    →「それらの数を合計する」
    →「そしてその合計の平方根を計算する」
  • これだと、記述したまま、左から右へ無理なく解釈できる
パイプ %>% 演算子を使わないと・・・
  • この一連の作業をパイプ %>% 演算子を使わないとすれば
sqrt(sum(1:10))
[1] 7.416198
  • これだと、私たちの直感に反して、思考が「右から左に(←)」逆行しなければならない
  • 「平均をとる」←「合計する」←「1から10までの数の」

パイプ %>% を使ったコマンドの解釈方法 ・上で紹介したパイプ %>% を使ったコードは次のように解釈できる

df1 %>%         # df1 というデータフレームを使って
  ggplot(aes(x = math,   # ggplot でグラフを描き(xとyを指定)
y = stat,
color = gender)) + # 性別ごとに表示する色分けし
  geom_point()    # グラフの種類は散布図

df1 %>% ggplot() は「データ df1ggplot() 関数の第一引数に渡す」という意味
ggplot() の第一引数はdf1
コードの解釈:
df1というデータフレームを使って」
ggplot でグラフを描き」
「性別ごとに色分けし」
「グラフの種類は散布図
・後戻りせずにコードの意味を理解できる
・パイプ %>% を使ったコマンドの方が直感的でわかりやすい
・ここではこれ以降、できるだけパイプ %>% を使ったコマンドを使う

5. グラフのカスタマイズ(基礎)

  • ここでは、上で作成したシンプルな散布図にエステティックな要素を指定し、良く使われる次の 9 点をカスタマイズする
カスタマイズの内容 関数
① 点に色を付ける aes(color = gender)
② 点の形を変える aes(shape = gender)
③ 点のサイズを指定 size = 3
④ 背景を白黒に変更 theme_bw()
⑤ x 軸と y 軸にラベルをつける labs(x = "math", y = "stat")
⑥ メインタイトルを付ける ggtitle("数学と統計学の試験の散布図")
⑦ 日本語表記と背景色 theme_bw(base_family = "HiraKakuProN-W3")
⑧ 凡例の位置調整 theme(legend.position = "bottom")
⑨ 回帰直線を表示させる geom_smooth(stat = "lm")

5.1 色分け・形・サイズ・背景色の変更

  • ①②③④をカスタマイズ
  • sizeshape は「全ての点に適用」したいため、aes() の外側で指定していることに注意
df1 %>% 
  ggplot() +
  geom_point(aes(x = math, 
   y = stat, 
   color = gender),
# size と shape は aes() の外に指定
size = 3, # 点のサイズを指定
shape = 17) +# 点の形を指定
  theme_bw() # 背景を白黒に変更

  • shape は次から選べる   

引数の指定位置で色表示が変わる

aes() が指定される場所で挙動が変わる

aes()「内側」color を指定 : 指定変数の値に応じて色分け
aes()「外側」color を指定 : 全ての点に適用される
aes() の内側で color = gender を指定する場合
plt_1 <- df1 %>% 
  ggplot() +
  geom_point(aes(x = math,
   y = stat, 
   color = gender)) +   # aes()の内側で指定
  ggtitle("aes()の内側で指定する場合") +
  theme_bw(base_family = "HiraKakuProN-W3")
plt_1

aes() の外側で color = "magenta" 指定する場合
plt_2  <- df1 %>% 
  ggplot() +
  geom_point(aes(x = math,
   y = stat), 
color = "magenta") +    # aes()の外側で指定
  ggtitle("aes()の外側で指定する場合") +
  theme_bw(base_family = "HiraKakuProN-W3")
plt_2

library(patchwork)
plt_1 + plt_2

5.2 x 軸と y 軸にラベルを付け加える

  • ⑤をカスタマイズ

  • x 軸と y 軸に日本語でラベルを付けたければ、labs() 関数を使う

  • labs(x = "...", y = "...")

df1 %>% 
  ggplot() +   # mapping = は省略可
  geom_point(mapping = aes(x = math, # x = は省略可
y = stat, # y = は省略可
color = gender)) + # 性別で色分け表示
  labs(x = "数学の試験点数", y = "統計学の試験点数")

  • x 軸と y 軸の変数名が文字化けしている
    → 解決方法は Step 8

5.3 メインタイトルを付け加える

  • ⑥をカスタマイズ
  • メインタイトルを付けたい場合には ggtitle("...") を使う
df1 %>% 
  ggplot() +
  geom_point(mapping = aes(x = math,    # mapping = は省略可
y = stat,
color = gender)) +
  labs(x = "数学の試験点数", y = "統計学の試験点数") +
  ggtitle("数学と統計学の試験の散布図")

  • x 軸と y 軸の「変数名」と「メインタイトル」が文字化けしている
    → 解決方法は Step 8

5.4 日本語表記と背景色

  • ⑦をカスタマイズ
  • RStudio 上で文字化けを避けるための日本語表示設定
  • この設定をしておくと
  1. フォントを設定しなくても日本語が表示できる
  2. グラフの表示が高速化し画質が改善される
RStudio 上での日本語表示設定手順
1. RStudio メニューから「Tools」 → 「Global Options」 → 「Graphics」を選ぶ
2.「Backend」欄を「AGG」に変更 → 「Apply」をクリック

:::

theme()関数を使った日本語を使えるようにする設定

  • 上の設定をした上で、theme_bw() 関数を使って設定する
  • 変数名やメインタイトルに日本語を使いたい時には次のコードを「 + 」でつないで加える
  • theme_bw(base_family = "HiraKakuProN-W3")
  • theme_bw と指定することでグラフの背景色を変更できる
df1 %>% 
  ggplot() +
  geom_point(mapping = aes(x = math,    # mapping = は省略可
y = stat,
color = gender)) + 
  labs(x = "数学の試験点数", y = "統計学の試験点数") +
  ggtitle("数学と統計学の試験の散布図") +
  theme_bw(base_family = "HiraKakuProN-W3", # 背景を Black and White に設定し日本語を表記
   base_size = 12)            # 文字サイズを 12 

  • x 軸と y 軸の「変数名」と「メインタイトル」が文字化けが解決した!
  • グラフの背景色の変更等についてはこちらを参照

図のメインタイトルの付け方 ・図にメインタイトルを付ける方法は次の二つある
1. ggtitle(".....")
2. labs(title = "....")

・従って、上の図は次のコードでも同一の結果が得られる(出力は省略)

df1 %>% 
  ggplot() +
  geom_point(mapping = aes(x = math,    # mapping = は省略可
y = stat,
color = gender)) + 
  labs(x = "数学の試験点数", 
  y = "統計学の試験点数",
  title = "数学と統計学の試験の散布図") +
  theme_bw(base_family = "HiraKakuProN-W3", # 背景を Black and White に設定し日本語を表記
   base_size = 12)            # 文字サイズを 12 

5.5 凡例の位置調整

  • ⑧をカスタマイズ
  • 凡例の位置を変更する際には theme(legend.position ="") で指定
  • ここでは theme(legend.position = "bottom") と凡例をグラフの下に指定してみる
df1 %>% 
  ggplot() +
  geom_point(mapping = aes(x = math,    # mapping = は省略可
y = stat,
color = gender)) + 
  labs(x = "数学の試験点数", y = "統計学の試験点数") +
  theme_bw(base_family = "HiraKakuProN-W3", # 背景を Black and White に設定し日本語を表記
   base_size = 12) +           # 文字サイズを 12 
  theme(legend.position = "bottom") # 凡例を図の下段に置く  

  • legend.position ="" では次の 5 つが指定できる
    "none"・・・非表示にしたいとき
    "top"
    "left"
    "right"
    "bottom"

  • 各軸の文字列とレジェンドが重ならないようにうまく配置してくれる

  • {ggplot2} のレジェンド位置の詳細に関してはこちらを参照

  • これで、{ggplot2} を使って簡単な散布図が描けた

5.6 回帰直線を表示させる

  • ⑨をカスタマイズ
  • geom_stat(stat = "lm")
  • 回帰直線を表示させる際の注意

点と線を同色にしたい場合

  • ジオメトリ内部でのマッピング
  • geom_smooth(method = lm) と指定すると、linear model の回帰直線が引ける  
  • + 」を使ってジオメトリ・レイヤー geom_smooth() を追加する
df1  %>% 
  ggplot() +
  geom_point(aes(x = math,
   y = stat, 
   color = gender)) +
  geom_smooth(method = lm) +   # 回帰直線を引く
  ggtitle("数学と統計学の散布図") +
  theme_bw(base_family = "HiraKakuProN-W3")
  • しかし、次のようなエラーメッセージが表示されてしまう

  • エラーメッセージの内容は「回帰直線を引きたいけど、xy がない」
  • 原因:審美的 (aesthetic) 要素である xy がジオメトリ・レイヤー geom_point() の内部でしか紐付けされていない
  • 解決策:回帰直線を引くためにはレイヤーの上位にある ggplot() の内部で xy を紐付けする
df1  %>% 
  ggplot(aes(x = math,   # ggplot() の内部で x と y を指定
y = stat, 
color = gender)) +
  geom_point() +
  geom_smooth(method = lm) +
  ggtitle("身長と体重の散布図") +
  theme_bw(base_family = "HiraKakuProN-W3")

  • 回帰直線が描けた

点の色は異なるが、線を同色にしたい場合

  • グラフ共通のマッピングを使って、同じ色の線(ここでは黒と指定)を引く
df1  %>% 
  ggplot(aes(x = math,   # ggplot() の内部で x と y を指定
y = stat)) +
  geom_point(aes(color = gender)) +
  geom_smooth(aes(group = gender), # gender  というグループ内で線を黒に統一
method = lm,
color = "black") +
  ggtitle("数学と統計学の散布図") +
  theme_bw(base_family = "HiraKakuProN-W3")

{ggplot2} で使える色{ggplot2} で使える色は 657 種類 !
"deeppink""skyblue""royalblue"のように文字で指定できる
aes() の外側に指定すること

df1 %>% 
  ggplot() +
  geom_point(aes(x = math, 
   y = stat),
size = 3,  
color = "deeppink", # aes() の外側に指定
shape = 8) +
  theme_bw()

・Rで使用可能な色のリストはコンソール上で colors() と打ち込むと確認できる
・ここでは最初の 6 色を示す

head(colors())
[1] "white"         "aliceblue"     "antiquewhite"  "antiquewhite1"
[5] "antiquewhite2" "antiquewhite3"

・これ以外にも RGBカラー(HEmathコード; 16進数)で指定することもできる
・たとえば赤なら "#FF0000"、ロイヤルブルーなら "#4169E1"と表記
HEmathコードを使う場合 → 非常に細かく色を指定可能
→ 16,777,216 種類!! もの色が使える   ・以下の例は R で使える色の一部

  • 好み次第で、必要に応じて適切にカスタマイズして、描きたい散布図を作り上げる

6. グラフのカスタマイズ(応用)

  • グラフの見た目を調整するための代表的な 10 のレイヤーを使ってカスタマイズする方法を紹介する

グラフの見た目を調整するための代表的な 10 のレイヤー

構成要素 {パッケージ}:関数() 役割
1. 凡例・軸のラベル labs*() 凡例と軸のラベルの処理
2. テーマ theme_*() グラフのみかけの設定
3. 座標系(Coordinate System) coord_*() グラフの座標系への処理
4. 統計処理 stat_*() データの統計処理
5. スケール scale_*()_ グラフの色や形を変更
6. ハイライト {gghighlight} データを強調して表示
7. 点の注釈 {ggrepel} ポイントに注釈を付ける
8. ファセット facet_*() データとグラフの分割
9. パッチワーク {patchwork} 複数のグラフを並べる
10.グラフの対話的操作 {plotly} インターアクティブなグラフ作成

データの準備

  • ここでは1996-2021年総選挙データ hr96-21.csv を使う
hr <- read_csv("data/hr96-21.csv", na = ".")
  • hr96_21.csv は1996年に衆院選挙に小選挙区が導入されて以来実施された 9 回の衆議院選挙(1996, 2000, 2003, 2005, 2009, 2012, 2014, 2017, 2021)の結果のデータ
  • hr に含まれる変数名を表示させる
names(hr)
 [1] "year"          "pref"          "ku"            "kun"          
 [5] "wl"            "rank"          "nocand"        "seito"        
 [9] "j_name"        "gender"        "name"          "previous"     
[13] "age"           "exp"           "status"        "vote"         
[17] "voteshare"     "eligible"      "turnout"       "seshu_dummy"  
[21] "jiban_seshu"   "nojiban_seshu"
  • hr には 23 個の変数が入っている
変数名 詳細
year 選挙年 (1996-2017)
pref 都道府県名(例:宮城)
prefecture 都道府県名(例:宮城県)
ku 小選挙区名
kun 小選挙区
rank 当選順位
wl 選挙の当落: 1 = 小選挙区当選、2 = 復活当選、0 = 落選
nocand 立候補者数
seito 候補者の所属政党
j_name 候補者の氏名(日本語)
name 候補者の氏名(ローマ字)
previous これまでの当選回数(当該総選挙結果は含まない)
gender 立候補者の性別: “male”, “female”
age 立候補者の年齢
exp 立候補者が使った選挙費用(総務省届け出)
status 候補者のステータス: 0 = 非現職、1 現職、2 = 元職
vote 得票数
voteshare 得票率 (%)
eligible 小選挙区の有権者数
turnout 小選挙区の投票率 (%)
seshu_dummy 世襲候補者ダミー: 1 = 世襲、0 = 非世襲(地盤世襲 or 非世襲)
jiban_seshu 地盤の受け継ぎ元の政治家の氏名と関係
nojiban_seshu 世襲元の政治家の氏名と関係
ダウンロードした衆院選データを確認する 2 つの方法:
(1) DT::datatable()関数を使って確認する方法
DT::datatable(hr)
(2) reactable:reactable()関数を使って確認する方法
  • reactable:reactable()関数だと複数の条件での検索が可能
reactable::reactable(hr,
  filterable = TRUE,  # 検索可能に設定
  defaultPageSize = 10) # 表示行数の限界を指定  

6.1 凡例・軸のラベル

  • 変数名は「英数字」なので、変数の意味が伝わらない → 変数名にラベルを付ける
  • ラベルを付けるためには labs関数を使う
構成要素 {パッケージ}:関数() 役割
1. ラベル labs*() 凡例・軸のラベルの処理
  • 2005年総選挙における選挙費用と得票率の散布図を描いてみる
ラベル調整なしの散布図
hr %>% 
  filter(year == 2005) %>% 
  mutate(ldp = ifelse(seito == "自民", 1, 0)) %>% 
  ggplot() +
  geom_point(aes(x = exp,
   y = voteshare, 
   color = as.factor(ldp),
   alpha = 0.5)) +
  theme_bw(base_family = "HiraKakuProN-W3") 

ラベル調整した散布図
hr %>% 
  filter(year == 2005) %>% 
  mutate(ldp = ifelse(seito == "自民", 1, 0)) %>% 
  ggplot() +
  geom_point(aes(x = exp,
   y = voteshare, 
   color = as.factor(ldp),
   alpha = 0.5)) +
  ggtitle("2005年総選挙における選挙費用と得票率:自民党 vs 非自民党(ラベルあり)") +
  theme_bw(base_family = "HiraKakuProN-W3") +
  labs(x = "選挙費用(円)", # 審美的属性ごとのラベル変更
  y = "得票率(%)")

6.2 テーマ

構成要素 {パッケージ}:関数() 役割
2. テーマ theme_*() グラフのみかけの設定
  • フォントなどグラフと無関係の要素の見た目を変更する時に使う
  • theme_*() 関数は base_family 引数を備えている
    → グラフ中の各要素のフォントを一括で指定できる
  • 日本語で最も良く使うのは theme_bw(base_family = "HiraKakuProN-W3" という設定
theme関数群
関数 特徴
theme_grey() グラフの背景色をグレーに設定(デフォルト)
theme_bw() グラフの背景色を白色に設定
theme_minimal() 最低限に必要な項目だけのテーマ
theme_classic() クラシックスタイルのテーマ

theme_*()関数の指定なしの場合

plt_3 <- hr %>% 
  filter(year == 2005) %>% 
  mutate(ldp = ifelse(seito == "自民", 1, 0)) %>% 
  ggplot() +
  geom_point(aes(x = exp,
   y = voteshare, 
   color = as.factor(ldp),
   alpha = 0.5)) +
  ggtitle("2005年総選挙における選挙費用と得票率:自民党 vs 非自民党") +
  labs(x = "選挙費用(円)", # 審美的属性ごとのラベル変更
  y = "得票率(%)",
  title = "2005年総選挙における選挙費用と得票率:自民党 vs 非自民党" )
plt_3

  • 日本語の文字化け設定をしていない
    → x 軸と y 軸の変数名とメインタイトルが文字ばけしている

theme_classic() を使う場合のコード

plt_3 + 
theme_classic(base_family = "HiraKakuProN-W3")

  • theme_*()関数の中で base_family = "HiraKakuProN-W3" と設定
    x 軸と y 軸の変数名とメインタイトルが文字ばけが解決

テーマごとの表示一覧

  • 上のテーマの中から、好みのものを選ぶ

6.3 座標系

構成要素 {パッケージ}:関数() 役割
3. 座標系(Coordinate System) coord_*() グラフの座標系への処理

coord_() 関数には次のようなものがある

coord_flip() 横軸と縦軸の交換
coord_cartesian() 座標系の拡大・縮小(最も良く使う)
coord_fixed() 横軸と縦軸比の固定

6.3.1 coord_flip(): 横軸と縦軸の交換

  • coord_flip() は図形の軸を入れ替えるときに使う
  • 箱ひげ図を使って、数学の点数を性別ごとに表示してみる
  • 幾何オブジェクト geom_box() 関数を使う
plt_4 <- df1  %>%
  ggplot() +
  geom_boxplot(aes(x = gender, 
y = math,
fill = gender),# 箱ひげ図を性別カラーにする設定
 show.legend = FALSE) + # 幾何オブジェクトに関する凡例を表示させない設定
  labs(x = "性別", y = "数学") +
  ggtitle("coord_flip()を使わない場合") +
  theme_bw(base_family = "HiraKakuProN-W3") 
plt_4

  • coord_flip() 関数を使って x 軸 と y 軸を入れ替える
plt_5 <- df1  %>%
  ggplot() +
  geom_boxplot(aes(x = gender, 
y = math,
fill = gender),# 箱ひげ図を性別カラーにする設定
 show.legend = FALSE) + # 幾何オブジェクトに関する凡例を表示させない設定
  labs(x = "性別", y = "数学") +
  ggtitle("coord_flip()を使ってx軸 ⇔ y軸") +
  theme_bw(base_family = "HiraKakuProN-W3") +
  coord_flip()  # 横軸と縦軸の交換
plt_5

  • {patchwork}を使って、図を並べて表示させてみる
library(patchwork)
plt_4 + plt_5

6.3.2 coord_cartesian()

  • coord_cartesian() は座標を拡大したり縮小するときに使う、最も良く使う関数の一つ
  • データの準備
  • 1996年〜2021年総選挙データ
hr <- read_csv("data/hr96-21.csv", na = ".")
  • 2005年総選挙データだけを抜き出す
hr2005 <- hr %>% 
  filter(year == 2005)
  • 選挙費用と得票率の関係を散布図と回帰曲線で比較する
plt_6 <- hr2005 %>% 
  ggplot() +
  aes(exp, voteshare) + 
  geom_point() + 
  geom_smooth(se=FALSE) + # 回帰曲線、信頼区間は非表示の設定
  theme_bw()
  • 全領域を表示
plt_6

coord_cartesian()を使って限定区域だけを表示

plt_6 + 
  coord_cartesian(xlim = c(5.0e+6, 2.6e+07))

xlim()を使って限定区域だけを表示

plt_6 + 
  xlim(5.0e+6, 2.6e+07)
Warning: Removed 353 rows containing non-finite values (stat_smooth).
Warning: Removed 353 rows containing missing values (geom_point).

・「353 の欠損値がある」&「回帰曲線を再計算した」との Warning(警告)が表示されている

coord_cartesian()を使うべき理由xlim() を使って表示範囲を限定すると、指定範囲外のデータを「欠損値」(NA)に変換してしまう
→ 表示される回帰曲線が全体の回帰曲線とは異なってしまう
→ グラフを描く目的が「表示範囲を拡大したいだけ」なら、coord_cartesian()を使うべき

6.3.3 coord_fixed()

  • coord_fixed() は座標系比を固定する時に使う
  • 出力される座標系の「横:縦」を調整するレイヤー
  • 架空データで散布図を描いてみる
ggplot() +
  geom_point(aes(x = 1:10,
   y = 1:10))

  • coord_fixed() を使って、横を 1 としたときの縦の割合を 2 と指定してみる
ggplot() +
  geom_point(aes(x = 1:10,
   y = 1:10)) +
  coord_fixed(ratio = 2)

  • xy は全く同じ数字のはずなのに、下の図の方が傾きが急に見える
  • coord_fixed(ratio = 1) と指定してみる
ggplot() +
  geom_point(aes(x = 1:10,
   y = 1:10)) +
  coord_fixed(ratio = 1)

  • 1:1の比率は維持されるまま図が拡大・縮小される

6.4 統計処理

構成要素 {パッケージ}:関数() 役割
4. 統計処理 stat_*() データの統計処理
  • geom_bar()関数を使って、2021年総選挙における立候補者数を政党別に棒グラフにして表示するためには

geom_bar(stat = "count")と指定する

→ aes(x = seito) で指定した seito をカウントして y 軸に表示

  • y は指定する必要がない
    → stat = "count"group に適用され
    → seito のカウントが行われ → y 軸に表示される
hr %>% 
  filter(year == 2021) %>% 
  ggplot(aes(x = seito)) + 
  geom_bar(stat = "count") +
  theme_bw(base_family = "HiraKakuProN-W3", # 背景を Black and White に設定し日本語を表記
   base_size = 12) +
  ggtitle("2021年総選挙における立候補者数(政党別)")

  • 確認のため、group_by()関数を使って、2021年総選挙における政党別立候補者数を政党別に計算してみる
hr %>% 
  filter(year == 2021) %>% 
  group_by(seito) %>% 
  summarize(N = n())
# A tibble: 11 × 2
   seito     N
   <chr> <int>
 1 N党     27
 2 れい     12
 3 公明      9
 4 共産    105
 5 国民     21
 6 無所     80
 7 社民      9
 8 立憲    214
 9 維新     94
10 自民    277
11 諸派      9
  • geom_bar()関数を使って、2021年総選挙における立候補者の「当選回数」の合計を政党別に棒グラフにして表示するためには

geom_bar(stat = "identity")と指定する

→ aes(x = seito, y = previous) で指定した previous の値を seito ごとに足した値が表示される

hr %>% 
  filter(year == 2021) %>% 
  ggplot(aes(x = seito, y = previous)) + 
  geom_bar(stat = "identity") +
  theme_bw(base_family = "HiraKakuProN-W3", # 背景を Black and White に設定し日本語を表記
   base_size = 12) +
  ggtitle("2021年総選挙における立候補者の「当選回数」の合計(政党別)")

  • 確認のため、group_by()関数を使って、2021年総選挙における立候補者の「当選回数」の合計を政党別に計算してみる
hr %>% 
  filter(year == 2021) %>% 
  group_by(seito) %>% 
  summarize(sum(previous))
# A tibble: 11 × 2
   seito `sum(previous)`
   <chr>           <dbl>
 1 N党                0
 2 れい                6
 3 公明               51
 4 共産               28
 5 国民               30
 6 無所               60
 7 社民                0
 8 立憲              481
 9 維新               50
10 自民             1142
11 諸派                5

6.5 スケール

  • scale_*()_ はグラフの色や形を変更する時に使う
  • {ggplot2} には様々な幾何オブジェクトがある
  • それらの幾何オブジェクト次第で、グラフ上におけるデータの示し方が変わる
  • 例えば、散布図だとデータは「点」として表現される
  • 折れ線グラフだと「線」で示される  
  • 棒グラフやヒストグラムだと「面」で表現される
  • これらの点、線、面などが持つ情報がスケール (scale)
  • {ggplot2} パッケージのデフォルトとは異なる色や形が必要な場合に使う
構成要素 {パッケージ}:関数() 役割
5. スケール scale_*()_ グラフの色や形を変更

スケール関数群一覧

scale_x_continuous() 横軸のスケールを調整(連続変数
scale_y_discrete() 縦軸のスケールを調整(離散変数
scale_color_manual() グラフの色や形を変更

軸のスケールを調整する主たる目的

  1. 目盛りの調整
  2. 目盛りラベルの調整

6.5.1 連続変数の目盛り変更

scale_*_continuous()関数

  • 軸に連続変数がマッピングされている場合

  • scale_*_continuous()レイヤーを追加する

  • * の箇所は横軸の場合は x、縦軸の場合は y

  • 1996年から2021年総選挙データを使って、2005年総選挙における選挙費用(x軸)と得票率(y軸)の散布図を描いてみる

hr <- read_csv("data/hr96-21.csv", na = ".")
  • exp を横軸、voteshare を縦軸にした散布図を作成し、plt_money_vs という名のオブジェクトに格納する
plt_7 <- hr %>% 
  select(seito, exp, voteshare, year) %>% 
  filter(year == 2005) %>% 
  ggplot(aes(x = exp, 
y = voteshare, 
col = seito)) +
  geom_point(alpha = 0.5) +
  labs(x = "選挙費用(円)", 
  y = "得票率",
  title = "2005総選挙:選挙費用と得票率") +
  geom_smooth(method = lm, se = FALSE) +
  theme_bw(base_family = "HiraKakuProN-W3")

plt_7

  • plt_7 の横軸は最小値 0、最大値 2.5e+07 (= 25,000,000円 = 2千500万円)
  • 目盛りは 500万円間隔
  • ここではこの横軸を調整してみる
  • プロットにおける最小値と最大値はスケールではなく座標系の問題
    → coord_*()を使う
  • 例えば、目盛りを 500万円間隔にし、そのラベルは 0万円、500万円、1000万円, 1500万円, 2000万円、2500万円と設定
  • exp は連続変数なので、scale_x_continuous()を使う
plt_7 +
  scale_x_continuous(breaks = seq(0, 2.5e+07, by = 0.5e+07),
  labels = c(0, 500, 1000, 1500, 2000, 2500))

  • 目盛りのラベルを文字型にすることも可能
  • 例えば、目盛りを「0」「500万円」「1000万円」・・・としたい場合は以下のようにする
plt_7 +
  scale_x_continuous(breaks = seq(0, 2.5e+07, by = 0.5e+07),
  labels = c("0", "500万円", "1000万円", "1500万円", "2000万円", "2500万円"))

y 軸の範囲を変更したい場合

  • scale_*_continuous() でも limits 引数で指定することも可能
  • 例えば、縦軸の範囲を 0% から 60% にしたい場合
  • scale_y_continuous() の中に limits = c(0, 60) と指定
plt_7 +
  scale_x_continuous(breaks = seq(0, 2.5e+07, by = 0.5e+07),
  labels = c(0, 500, 1000, 1500, 2000, 2500)) +
  scale_y_continuous(limits = c(0, 60))

目盛りと目盛りラベルの位置を変更したい場合

  • position 引数を使う
  • 横軸の目盛りは下(“bottom”)、縦軸は左(“left”)
  • しかし、“top” でも “right” でも指定できる
  • もし、縦軸の目盛りとラベル、軸のラベルを右側にしたい場合
    → scale_y_continuous() の中に position = "right" を指定
  • 同時に、現時点では右側にあるレジェンドは theme(legend.position = "left") と指定すれば左に移動できる
plt_7 +
  scale_x_continuous(breaks = seq(0, 2.5e+07, by = 0.5e+07),
  labels = c(0, 500, 1000, 1500, 2000, 2500)) +
  scale_y_continuous(limits = c(0, 60)) +
  scale_y_continuous(position = "right") +
  theme(legend.position = "left")

6.5.2 離散変数の目盛り変更

scale_*_discrete()関数

  • 軸が名目変数や順序変数のような離散変数でマッピングされている場合
    → scale_*_discrete()を使う
  • 例えば、1996年から2021年までの総選挙に出馬した候補者のを新人・現職・元職別に分類した棒グラフは次のとおり
plt_8 <- hr %>% 
  ggplot() +
  geom_bar(aes(x = status)) +
  labs(x = "新人・現職・元職の分類", y = "立候補者総数") + 
  ggtitle("新人・現職・元職別の立候補者数(1996-2021年総選挙)") +
  theme_bw(base_family = "HiraKakuProN-W3") # 文字化け対策

plt_8

  • 横軸の候補者の立場が数字のままになっている
  • これを日本語にする場合、scale_x_discrete() を使う
  • 使い方は scale_*_continuous() と同じ
plt_8 +
  scale_x_continuous(breaks = c(0, 1, 2),
  labels = c("新人", "現職", "元職"))

6.5.3 散布図の点の色を指定する

scale_color_manual()関数

plt_9 <- hr %>% 
  filter(year == 2012) %>% 
  mutate(ldp = ifelse(seito == "自民", 1, 0)) %>% 
  ggplot() +
  geom_point(mapping = aes(x = exp,    # mapping = は省略可
y = voteshare,
alpha = 0.5,
color = as.factor(ldp))) + 
  labs(x = "選挙費用(円)", y = "得票率 (%)") +
  theme_bw(base_family = "HiraKakuProN-W3", # 背景を Black and White に設定し日本語を表記
   base_size = 12)

plt_9

  • 例えば、上の図の場合、「点」は①横軸上の位置、②縦軸上の位置、③色の 3 つのスケールを持つ
  • 横軸と縦軸は連続変数 (選挙費用と得票率)
  • 色は名目変数 (自民党候補者か否か)
  • ここで、青とトマト色を他の色に変えてみる
plt_9 +
  scale_color_manual(values = c("1" = "deeppink", "0" = "aquamarine"))

6.6 ハイライト

  • 追加パッケージ {gghighlight} が必要
構成要素 {パッケージ}:関数() 役割
6. ハイライト gghighlight() データを強調して表示
  • 1996年から2021年総選挙データを使って、2005年総選挙における選挙費用(x軸)と得票率(y軸)の散布図を描いてみる
plt_10 <- hr %>% 
  select(seito, exp, voteshare, year) %>% 
  filter(year == 2005) %>% 
  ggplot(aes(x = exp, 
y = voteshare, 
col = seito)) +
  geom_point(alpha = 0.5) +
  labs(x = "選挙費用", 
  y = "得票率",
  title = "2005総選挙:選挙費用と得票率") +
  geom_smooth(method = lm, se = FALSE) +
  theme_bw(base_family = "HiraKakuProN-W3")

plt_10

  • {{gghighlight}}パッケージの gghighlight() 関数を使うと、特定の点を強調して表示できる
  • 強調したくないデータを地味な色(グレーなど)で表示する
  • 強調したいデータを派手な色で表示する
library(gghighlight)
  • 自民党と民主党の候補者だけを強調して表示してみる
plt_10 +
  gghighlight(seito == "自民" | seito == "民主")   # 自民党候補をハイライト

6.7 点の注釈

{ggrepel} パッケージ
  • 特定のデータを強調する目的は次の 2 つ
  1. グラフ内で何が重要なのかを示したい
  2. 関連したグラフを比較したい
  • しかし、これらのことは {ggplot2} パッケージだけでは実現できない
    → 追加パッケージ {ggrepel} を利用する
構成要素 {パッケージ}:関数() 役割
7. 点の注釈 {ggrepel} ポイントに注釈を付ける
  • {ggplot2} パッケージは指定した座標に文字列を表示する方法として次の 2 つの関数を実装している
関数 役割
ggrepel_text() 文字列のみ描写
ggrepel_label() 背景が付いた文字列を描写
  • しかし、散布図とラベルが重なって読みにくいことが多い
    → 次の改良版を使うのが良い

改良版: ggrepel_text_repel() & ggrepel_label_repel()

構成要素 {パッケージ}:関数()
ggrepel_text_repel() 表示の重複を調整してくれる
ggrepel_label_repel() 表示の重複を調整してくれる
  • {{ggrepel}}パッケージの geom_text_repel() 関数 を使うと、点に対する注釈を重複せずに表示できる
  • df1 を使って、数学と統計学の試験結果を比較した散布図に、個体名をラベル付けしてみる
  • {ggrepel} パッケージは、ラベルの座標を自動調整した後
    → ラベルがあまりにも原点から離れた場合
    → 原点とラベルを「線」で結ぶ
    → ラベル x 審美的属性とラベル y 審美的属性には、散布図と共通の値を指定する必要あり
library(ggrepel)

全ての観測値のラベルを表示させる場合

# 散布図の作成
plt_11 <- df1 %>% 
  ggplot() +
  aes(math, 
 stat,
 color = gender) +
  geom_point() + 
  theme_bw()

# 散布図上の全ての点に名前をラベリングする  

plt_11 + geom_text_repel(aes(label = name)) 

  • 次に、条件に一致するデータだけを表示させ、さらにラベル表示を行う

数学の点数で上位 5 人だけを表示させる場合

# 散布図上で数学の点数が上位 5 人だけにラベリングする  
plt_11 + 
  geom_text_repel(aes(label = name), # 名前をラベリング
    data = function(data) 
 dplyr::slice_max(data, # 数学の点数が上位 5 人だけを選ぶ
 math,
 n = 5)
    )

統計学の点数で 12 点以上の人だけを表示させる場合

# 散布図上で統計学の点数が 12 点以上の人だけにラベリングする  
plt_11 + 
  geom_text_repel(aes(label = name),  # 名前をラベリング
    data = function(data) 
 dplyr::filter(data,    # 統計学の点数で 12 点以上を指定
 stat >= 12)
    )

自作関数 function() ・例えば \(3x^2 + 5\) という関数を計算したい時、R を使うと次のように計算できる

3^2 * 1 + 5 # x = 1 の時
[1] 14
3^2 * 2 + 5 # x = 2 の時
[1] 23

・しかし、これは極めて効率が悪く、ヒューマンエラーも起こりうる

解決策:

function() を使って自作関数を作る
→ 何度も似た計算を効率よく実行できるようになる

  • 関数 \(3x^2 + 5\)f1 と定義する
f1 <- function(x){
  3^2 * x + 5
}
  • x = 1 の時の計算
f1(x = 1)   # x = 1 の時
[1] 14
  • x = 2 の時の計算
f1(x = 2)   # x = 2 の時
[1] 23
f1() 関数名
function(x)x 引数名
{} で囲まれたコード 関数の処置内容
  • R では関数はオブジェクトの一種
    → 変数を代入することで、関数が実行される
  • 引数 x{} 内で変数として振る舞う
  • 関数実行時に指定した値が代入される
  • {} 内のコードは複数行記述可能
  • コードの最終行の結果は実行結果(=返り値)として利用可能

自作関数 function()の応用例

  • 1996年から2021年総選挙のデータを読み込む
hr <- read_csv("data/hr96-21.csv", na = ".")
  • 2005年総選挙だけを抜き出し hr2005 と名前を付ける
hr2005 <- hr %>% 
  filter(year == 2005)
  • hr2005 の変数名をチェックする
names(hr2005)
 [1] "year"          "pref"          "ku"            "kun"          
 [5] "wl"            "rank"          "nocand"        "seito"        
 [9] "j_name"        "gender"        "name"          "previous"     
[13] "age"           "exp"           "status"        "vote"         
[17] "voteshare"     "eligible"      "turnout"       "seshu_dummy"  
[21] "jiban_seshu"   "nojiban_seshu"
  • hr2005 の任意の列を選んで箱ひげ図を描く関数を作る
bp_hr2005 <- function(x){
  ggplot(hr2005) +
    aes(.data[[x]]) +  # aes({{x}}) と設定することも可能
              # → その際は出力で bp_hr2005(age)と指定
    geom_boxplot() +
    coord_flip()
}

「.data」の意味.data・・・ {tidyverse} が用意している特別な変数
・捜査中のデータフレームの「別名」として機能する
・例:hr2005 データフレームを対象として分析している場合
hr2005[["age"]].data[["age"]] は同じ意味
・「hr2005 データフレームから age 列を選択する」という意味

  • 例えば x に年齢 (age) を指定してみる   
bp_hr2005("age")

グラフを大量に表示したい場合

  • さらに for()関数を使って作業を効率化できる
  • 例えば、年齢 (age) 、得票率 (voteshare)、選挙費用 (exp) の政党ごとの分布を同時に表示したい場合
bp_hr2005_1 <- function(x){
  ggplot(hr2005) +
    aes(x = .data[[x]],  # x 軸に x を指定
y = .data[["seito"]], # y 軸に seito を指定
color = .data[["seito"]]) +  # seito 別に色分け
    geom_boxplot() +
    theme_bw(base_family = "HiraKakuProN-W3") +
    theme(legend.position = "none") # レジェンドを非表示
}

for (x in c("age", "voteshare", "exp")){
  print(
    bp_hr2005_1(x) # 3 つの変数の分析を同時に実行
  )
}

highlight()ggrepel_text_repel() の組み合わせ

  • 特定の政党や人などのラベルをハイライトで表示させる
  • 例えば、2005年総選挙における選挙費用の分布を自民党と民主党をハイライトして箱ひげ図を表示させてみる
  • gghighlight(seito == "自民") と指定
# 散布図の作成
plt_13 <- hr2005 %>% 
  ggplot() +
  aes(x = exp, # x 軸に exp を指定
y = seito,# y 軸に seito を指定
color = seito) +  # seito 別に色分け
  geom_boxplot() +
  theme_bw(base_family = "HiraKakuProN-W3") +
  theme(legend.position = "none") + # レジェンドを非表示
  labs(x = "選挙費用",
  y = "政党",
  title = "2005年総選挙における選挙費用の分布")

# 自民党をハイライトしてラベリング
plt_13 +
  gghighlight(seito == "自民" | seito == "民主",
label_key = seito, # 引数として列名 (seito) を指定)
unhighlighted_params = list(
  color = "grey50") # 自民・民主以外の政党の色も指定できる
) 

6.8 ファセット

構成要素 {パッケージ}:関数() 役割
8. ファセット facet_*() データとグラフの分割
  • facet()関数を使うと、注目したい変数の水準ごとにグラフを分割できる
  • 1996-2021年総選挙データを使って、選挙費用と得票率の関係を政党ごとに比較した散布図を、色合いごとにプロットしてみる

hr96-21.csv を読み込み
・2005年総選挙データだけを抜き出す

hr <- read_csv("data/hr96-21.csv", na = ".")

・「選挙費用」と「得票率」の散布図を描いてみる(政党ごと)

plt_14 <- hr %>% 
  select(seito, exp, voteshare, year) %>% 
  filter(year == 2005) %>% 
  ggplot(aes(x = exp, 
y = voteshare, 
col = seito)) +
  geom_point(alpha = 0.5) +
  labs(x = "選挙費用", y = "得票率") +
  geom_smooth(method = lm) +
  theme_bw(base_family = "HiraKakuProN-W3") +
  ggtitle("2005総選挙:選挙費用と得票率") 

plt_14

  • facet_wrap(~seito) と指定すれば、自動的に分割したグラフを表示できる
plt_14 +
  facet_wrap(~seito) # 政党ごとに散布図を分割する

  • facet()関数内で、色合いごとにファセットする行数や列数を設定できる
plt_14 +
  facet_wrap(
    vars(seito), # 分割する基準になる変数を指定
    nrow = 2,  # 分割する行数を指定(省略できる)
    ncol = 5  # 分割する列数を指定(省略できる)
  ) 

6.9 パッチワーク

構成要素 {パッケージ}:関数() 役割
9. パッチワーク {patchwork} 複数のグラフを並べる
  • 異なる種類のグラフや同種のグラフを 1 枚に並べるパッケージ
  • グラフの並べ方を演算子 \(|\)\(/\) で表現できる
  • 並べたグラフをかっこでまとめて、さらに他のグラフとの比較もできる
演算子 役割
| 横方向に並べる
/ 縦方向に並べる
  • 例えば、散布図を様々な変数で色づけする
    → 変数ごとの交互作用の有無や強弱がわかる

ここでの試み:

  • 2005年総選挙において選挙費用と得票率の関係が、「自民党・非自民党別」「男女別」「新人・現職・元職別」でどのように変わるかを確認する

そのための手順:

  • 関数名を定義する → 例えば scatter_hr()など、好きな関数名を付ける
  • scatter_hr()関数に様々な列名を指定した結果をリストにまとめる
  • patchwork::wrap_plots()関数に与える
library(patchwork)

データの準備

  • 2005年総選挙データを読み取る
hr <- read_csv("data/hr96-21.csv", na = ".")
  • 2005年総選挙データだけを抜き出し、自民党ダミーを作る
hr2005 <- hr %>% 
  filter(year == 2005) %>% 
  mutate(ldp = ifelse(seito == "自民", 1, 0)) # 自民党ダミー (ldp) を作る
  • status, gender, ldp の型を factor に変更
hr2005$status <- as.factor(hr2005$status)
hr2005$gender <- as.factor(hr2005$gender)
hr2005$ldp <- as.factor(hr2005$ldp)
# 散布図を描くための関数
# hr2005 データセットの選挙費用と得票率を比較  

scatter_hr <- function(color = "seito"){ # scatter_hr() 関数を定義
  ggplot(hr2005) +
    aes(
 exp, voteshare,
 color = .data[[color]]
    ) +
    geom_point(size = 1, alpha = 0.5) +
    theme_bw(base_family = "HiraKakuProN-W3") + 
    labs(x = "選挙費用(円)",
 y = "得票率 (%)",
 title = "2005年総選挙") +
    theme(legend.position = "bottom")
}

# hr2005データセットの中から factor 型の列だけを抽出  
# それぞれを散布図の色に割り当てた散布図を作成する  
# patchworkパッケージを使って 1 枚のグラフにまとめる  

hr2005 %>% 
  select(where(is.factor)) %>%# factor 型の列だけを抽出
  names() %>%# scatter_hr()関数に列名を指定した結果をリストにまとめる
  purrr::map(scatter_hr) %>%  # 様々な列を表示色にマッピング
  patchwork::wrap_plots(nrow = 1) # リストを 1 枚のグラフにまとめる  

  • 次の二カ所を変更すれば、一列で表示できる
    theme(legend.position = "right")・・・レジェンドを右側に表示
    patchwork::wrap_plots(ncol = 1)・・・グラフを一列で表示
scatter_hr2005 <- function(color = "seito"){ # scatter_hr() 関数を定義
  ggplot(hr2005) +
    aes(
 exp, voteshare,
 color = .data[[color]]
    ) +
    geom_point(size = 1, alpha = 0.5) +
    theme_bw(base_family = "HiraKakuProN-W3") + 
    labs(x = "選挙費用(円)",
 y = "得票率 (%)",
 title = "2005年総選挙") +
    theme(legend.position = "right")
}

hr2005 %>% 
  select(where(is.factor)) %>%# factor 型の列だけを抽出
  names() %>%# scatter_hr2005()関数に列名を指定した結果をリストにまとめる
  purrr::map(scatter_hr2005) %>%   # 様々な列を表示色にマッピング
  patchwork::wrap_plots(ncol = 1) # リストを 1 枚のグラフにまとめる  

6.10 グラフの対話的操作

構成要素 {パッケージ}:関数() 役割
10.グラフの対話的操作 {plotly} インターアクティブなグラフ作成
  • グラフとの「対話的」(インターアクティブな)操作が可能
  • plotly::ggplotly()関数は {ggplot2}パッケージで作成したグラフを使って
    → 「対話的に」操作可能なグラフに変換してくれる

データの準備

・総選挙データを読み込む

hr <- read_csv("data/hr96-21.csv", na = ".")
  • 2005年総選挙での当選者(小選挙区+復活当選)だけにデータを絞る
hr2005 <- hr %>% 
  filter(year == 2005) %>% 
  filter(wl > 0)
  • 対話的に操作可能なグラフの作成
plt_15 <- ggplot(hr2005) +
  aes(x = exp,
 y = voteshare,
 color = seito) +
  geom_point(aes(alpha = 0.5)) +
  theme_bw(base_family = "HiraKakuProN-W3") 

plotly::ggplotly(plt_15)
  • 作成したグラフの右側にある政党名にカーソルを当ててクリックすると、クリックした政党の表示が消える
  • 「みんな」→「共産」→「国民新党」・・・と政党名を一つずつクリックして非表示にしてみる
  • 「民主」と「自民」だけを残して全て非表示にする  

  • カメラボタンのアイコンをクリックすると、キャプチャ画像を png型式で保存・共有することもできる  

  • 上のグラフで確認した「民主党」と「自民党」だけを表示させたグラフを、{plotly}を使わずに書き直す
    → 再現性を担保しつつ必要なグラフを出力できる
plt_15 +
  gghighlight::gghighlight(seito == "民主" | seito == "自民")

  • coord_cartesian()関数を使えば、x 軸と y 軸の範囲を指定して拡大・縮小が自在にできる

  • さらに x 軸の範囲を 190万円から 1500万円の間、y 軸の範囲を 25%から75%に限定して表示させたい場合

plt_15 +
  gghighlight::gghighlight(seito == "民主" | seito == "自民") +
  coord_cartesian(xlim = c(1900000, 15000000),
    ylim = c(25, 75))

6.11 画像の保存

  • 画像の保存
  • {plotly}を使うと、キャプチャ画像を保存・共有できる
  • より精密にグラフを保存したい場合には ggsave()関数を使う
  • fig フォルダを R プロジェクトフォルダ内に作る
  • 作成した図を fig フォルダに保存する
ggsave("fig/plt_15.png", # 保存したい画像の名前 plt_15.png を指定
  plt_15,   # 作成した画像名(オブジェクト名 plt_1)
  width = 10, # 画像の横サイズ
  height = 10,    # 画像の縦サイズ
  units = "cm")    # 画像サイズの単位を指定  
  # インチなら "in"
  # ミリメートルなら "mm"

7. 省略のバリエーション

  • R では同じ意味を表すコードにバリエーションがある
  • 例えば、下のコードと同じ意味のコードは 10 通り可能
ggplot(data = hr, mapping = aes(x = exp, y = voteshare))
1. ggplot(hr, aes(x = exp, y = voteshare))
2. ggplot(hr, aes(exp, voteshare))
3. ggplot(hr) + aes(x = exp, y = voteshare))
4. ggplot(hr) + aes(exp, voteshare))
パイプ %>% を使ったコマンド
5. hr %>% ggplot(mapping = aes(x = exp, y = voteshare))
6. hr %>% ggplot(aes(x = exp, y = voteshare))
7. hr %>% ggplot(aes(exp, voteshare))
8. hr %>% ggplot() + aes(x = exp, y = voteshare))
9. hr %>% ggplot() + aes(exp, voteshare))

8. 役に立つサイト

from Data to vis
  • R だけでなく、PythonD3.js を使った可視化を紹介
  • グラフの事例が豊富
TidyTuesday
  • 毎週、異なるデータが課題として出され、データの可視化を競う
  • 参加者は Twitter でハッシュタグを付けてグラフを紹介する

10. Exercise

Q10.1: 「6.7 点の注釈: highlight() と ggrepel_text_repel() の組み合わせ」を参考にして、2009年総選挙での選挙費用の分布を政党ごとに箱ひげ図で示しなさい

  • その際、自民党と民主党をハイライトしなさい
  • データは hr96-21.csv を使うこと  

Q10.2: 「6.6 ハイライト」を参考にして、2009年総選挙での「選挙費用」と「得票率」の散布図を描きなさい

  • その際、自民党と民主党をハイライトしなさい
  • データは hr96-21.csv を使うこと  

Q10.3: 「6.8 ファセット」を参考にして、2009年総選挙データだけを抜き出し「選挙費用」と「得票率」の散布図を描きなさい

  • その際、ファセット分割して政党ごとに色分けし、政党ごとの回帰直線も加えなさい

Q10.4: 「6.7 点の注釈:自作関数 function() → グラフを大量に表示したい場合」を参考にして、2009年総選挙における年齢 (age) 、得票率 (voteshare)、選挙費用 (exp) の政党ごとの分布を同時に箱ひげ図を使って表示しなさい

Q10.5: 「6.9 パッチワーク」を参考にして、2009年総選挙において選挙費用と得票率の関係が、「民主党・非民主党別」「男女別」「新人・現職・元職別」でどのように変わるかを patchwork::wrap_plots() 関数を使って散布図で表示しなさい

参考文献

  • 宋財泫 (Jaehyun Song)・矢内勇生 (statuki statanai)「私たちのR: ベストプラクティスの探究」
  • 宋財泫「可視化理論」
  • 土井翔平(北海道大学公共政策大学院)「Rで計量政治学入門」
  • 矢内勇生(高知工科大学)授業一覧
  • 浅野正彦, 矢内勇生.『Rによる計量政治学』オーム社、2018年
  • 浅野正彦, 中村公亮.『初めてのRStudio』オーム社、2018年
  • Winston Chang, R Graphics Coo %>% kbook, O’Reilly Media, 2012.
  • Kieran Healy, DATA VISUALIZATION, Princeton, 2019
  • Kosuke Imai, Quantitative Social Science: An Introduction, Princeton University Press, 2017