• このセクションで使っている R packages
library(DT)
library(gapminder)
library(gghighlight)
library(ggrepel)
library(stargazer)
library(tidyverse)

1. 箱ひげ図とは  

  • 箱ひげ図 (boxplot) は連続変数の分布を示す方法の一つ
変数 可視化の方法 特徴
連続変数 箱ひげ図 ①中央値・四分位範囲・最小値・最大値情報が瞬時にわかる
②グループの分布を1つのプロットの中で比較できる
  • ヒストグラムと共に幅広く使われる可視化手法
  • ヒストグラムは「どの辺が最も密度が高いか」を調べる
  • 箱ひげ図は、特定の変数の記述統計量を素早く比較できる
  • 箱ひげ図を使えば、変数の最小値、最大値、第一四分位数、第二四分位数(中央値)、第三四分位数と極端な値である外れ値がわかる
  • 色分けやファセット分割を行わず、変数の分布をグループごとに見ることができる

箱ひげ図の読み方

出典:浅野・矢内『Rによる計量政治学』p.107.

四分位数(しぶんいすう)

  • 変数 x を作る
x <- c(10, 7, 9, 1, 0, 2, 5, 8, 3, 4, 6)
x
 [1] 10  7  9  1  0  2  5  8  3  4  6
  • x を小さい方から順に並べる
sort(x)
 [1]  0  1  2  3  4  5  6  7  8  9 10
  • 左端(第一四分位数:最小値)・・・ 0
  • 真ん中(第二四分位数 = 中央値)・・・5
  • 右端(第三四分位数:最大値)・・・10
  • Base R を使って x の箱ひげ図を描いてみる
boxplot(x)

2. 箱ひげ図の作成

df <- read_csv("data/hr96-21.csv",
               na = ".")  
  • 自民党ダミー (ldp) を作る
df <- df %>% 
  mutate(ldp = if_else(seito == "自民", "自民党", "非自民党")) # 自民党ダミー (ldp) を作る  

2.1 シンプルな箱ひげ図

  • df を使って、得票率 (voteshare) の箱ひげ図を描いてみる
  • 幾何オブジェクト名は geom_boxplot()
  • ヒストグラムのようにマッピングは 1 つのみでよい
  • y にも x にもマッピングできる

パイプ演算子(%>%|> ・2021年5月リリースされた R 4.1以降、R 内蔵演算子としてパイプ演算子(|>)が追加
パイプ演算子は %>% でも |> でも、どちらを使っても結果は同じ

2.2 箱ひげ図の色を変える

  • 棒グラフやヒストグラムは「ある変数の分布」を示す
  • 箱ひげ図は「ある変数のグループごとの分布」を示す時に使われる場合が多い
  • 2021年総選挙における政党別の得票率を箱ひげ図で示してみる
df %>%
  filter(year == 2021) %>% # 2021年総選挙データだけに絞る
  ggplot() +
  geom_boxplot(aes(y = voteshare, x = seito)) + 
  labs(x = "政党", y = "得票率") +
  ggtitle("政党ごとの得票率:2021年総選挙") +
  theme_bw(base_family = "HiraKakuProN-W3")

箱ひげ図の色の変え方

(1) 箱ひげ図の「枠線の色」を変えたい場合: color = ""
  • aes() の「内側に」 color = "skyblue" のように指定できる
df %>%
  filter(year == 2021) %>% # 2021年総選挙データだけに絞る
  ggplot() +
  geom_boxplot(aes(y = voteshare, 
                   x = seito),
               color = "skyblue") + 
   labs(x = "政党", y = "得票率") +
   ggtitle("政党ごとの得票率:2021年総選挙") +
  theme_bw(base_family = "HiraKakuProN-W3")

(2) 「箱の中の色」を変えたい場合: fill = ""
  • aes() の「外側に」 fill = "skyblue" のように指定する
  • color = "skyblue" とマッピングすると、箱内の色でなく、枠線の色が変更される
df %>%
  filter(year == 2021) %>% # 2021年総選挙データだけに絞る
  ggplot() +
  geom_boxplot(aes(y = voteshare, 
                   x = seito),
               fill = "skyblue") + 
   labs(x = "政党", y = "得票率") +
   ggtitle("政党ごとの得票率:2021年総選挙") +
  theme_bw(base_family = "HiraKakuProN-W3")

(3) 政党ごとに色を変えたい場合
  • 政党ごとに色を変えたい場合にはscale_fill_manual() レイヤーを追加する
df %>%
  filter(year == 2021) %>% # 2021年総選挙データだけに絞る
  ggplot() +
  geom_boxplot(aes(y = voteshare, 
                   x = seito,
                   fill = seito)) + 
   labs(x = "政党", y = "得票率") +
   ggtitle("政党ごとの得票率:2021年総選挙") +
  theme_bw(base_family = "HiraKakuProN-W3") +
  theme(legend.position = "none")

(3) 政党ごとに色をカスタマイズしたい場合
  • 政党ごとに色をカスタマイズしたいときは、scale_color_manual() を使う
df %>%
  filter(year == 2021) %>% # 2021年総選挙データだけに絞る
  ggplot() +
  geom_boxplot(aes(y = voteshare, 
                   x = seito,
                   color = seito)) + 
   labs(x = "政党", y = "得票率") +
   ggtitle("政党ごとの得票率:2021年総選挙") +
  theme_bw(base_family = "HiraKakuProN-W3") +
  theme(legend.position = "none") +
  scale_color_manual(values = c("N党" = "grey", 
                               "れい" = "grey",
                               "公明" = "red",
                               "共産" = "grey",
                               "国民" = "grey", 
                               "無所" = "grey",
                               "社民" = "grey",
                               "立憲" = "grey",
                               "維新" = "grey",
                               "自民" = "red",
                               "諸派" = "grey"))

2.3 箱ひげ図に次元を加える

  • 次元を追加するのであれば、色分けで行う
  • 例えば、候補者の性別を新たな次元として立候補者の性別 (gender) を追加してみる
  • aes() の「内側に」 fill = "gender" のように指定する
df %>%
  filter(year == 2021) %>% # 2021年総選挙データだけに絞る
  ggplot() +
  geom_boxplot(aes(y = voteshare, 
                   x = seito,
                   fill = gender)) + 
   labs(x = "政党", y = "得票率") +
   ggtitle("政党別・男女別の得票率:2021年総選挙") +
  theme_bw(base_family = "HiraKakuProN-W3") +
  theme(legend.position = "bottom")

2.4 箱ひげ図の見せ方をカスタマイズする

2.4.1 箱の幅を狭く・広くする

  • 箱の幅を狭くする場合は、aes() の外側に width を指定する
  • 指定しない場合の箱の幅は 0.75
  • ここでは箱の幅を 0.25 に設定してみる
df %>%
  filter(year == 2021) %>% # 2021年総選挙データだけに絞る
  ggplot() +
  geom_boxplot(aes(y = voteshare, 
                   x = seito),
               width = 0.25) +               # 幅を 0.25 に設定
  labs(x = "政党", y = "得票率") +
  ggtitle("政党ごとの得票率:2021年総選挙") +
  theme_bw(base_family = "HiraKakuProN-W3")

2.4.2 縦表示 ⇔ 横表示

  • 箱が多すぎる場合、図は横に長くなる
df %>%
  filter(year == 2021) %>% # 2021年総選挙データだけに絞る
  ggplot() +
  geom_boxplot(aes(y = voteshare, 
                   x = seito)) +              
  labs(x = "政党", y = "得票率") +
  ggtitle("政党ごとの得票率:2021年総選挙") +
  theme_bw(base_family = "HiraKakuProN-W3")

解決策:

  • xy を交換すれば縦長になる
df %>%
  filter(year == 2021) %>% # 2021年総選挙データだけに絞る
  ggplot() +
  geom_boxplot(aes(y = seito, 
                   x = voteshare)) +              
  labs(x = "政党", y = "得票率") +
  ggtitle("政党ごとの得票率:2021年総選挙") +
  theme_bw(base_family = "HiraKakuProN-W3")

2.4.3 政党名の表示順番を反転したい場合

  • scale_y_discrete(limits = rev)
df %>%
  filter(year == 2021) %>% # 2021年総選挙データだけに絞る
  ggplot() +
  geom_boxplot(aes(y = seito, 
                   x = voteshare)) +              
  labs(x = "政党", y = "得票率") +
  theme_bw(base_family = "HiraKakuProN-W3") +
  ggtitle("政党ごとの得票率:2021年総選挙") +
  scale_y_discrete(limits = rev)

2.4.4 政党名の表示順番をカスタマイズしたい場合

  • 得票率の高い順位表示したい時
  • 例えば2021年の総選挙において平均得票率の高い政党ごとに箱ひげ図を描きたいとする

政党ごとの平均得票率を確認してみる

df |> 
  filter(year == 2021) |> 
  group_by(seito) |> 
  summarize(ave_vs_2021 = mean(voteshare)) |> 
  DT::datatable()
  • ggplot() に渡す前に seitofactor 化して、順番を決める

  • seitofactor 化して図を描いてみる

df %>%
  filter(year == 2021) %>% # 2021年総選挙データだけに絞る
  mutate(seito = factor(seito,
                            levels = c("公明", 
                                       "自民", 
                                       "立憲", 
                                       "国民", 
                                       "維新",
                                       "社民", 
                                       "無所", 
                                       "共産", 
                                       "れい", 
                                       "諸派",
                                       "N党"))) %>%  # N党の「N」は全角英字
  ggplot() +
  geom_boxplot(aes(y = seito, 
                   x = voteshare)) +              
  labs(x = "政党", y = "得票率") +
  ggtitle("政党ごとの得票率:2021年総選挙") +
  theme_bw(base_family = "HiraKakuProN-W3") 

平均値 (mean) と中央値 (median) ・箱ひげ図内の太い線は「中央値 (median)」を表している
・ここでは政党の位置は「平均値 (mean)」を基準として並べている
→ 平均値 (mean) と中央値 (median)は必ずしも一致するとは限らない

  • 箱ひげ図は「グループごとに比較」することで、それぞれの変数の分布を素早く確認できる

  • 2021年衆院選で最も平均得票率が高かった政党は公明党

  • 視覚的に、ばらつきの最も大きいのは国民民主党

  • 自民党と比べると、公明党のばらつきは小さい  

  • N党、諸派、れいわ、公明党のばらつきは小さい   

政党ごとのばらつきを確認してみる

df |> 
  filter(year == 2021) |> 
  group_by(seito) |> 
  summarize(ave_sd_2021 = sd(voteshare)) |> 
  DT::datatable()
  • 右に伸びる線の最先端・・・最大値  

  • 左に伸びる線の最先端・・・最小値

  • 最大値より大きい値や、最小値より小さい値がある!!
    → 最先端の左右にあるドット「●」= 外れ値

  • 箱ひげ図の最小値・・・「第1四分位点 - 1.5 × 四分位範囲」より大きい値の中での最小値

  • 箱ひげ図の最大値・・・「第1四分位点 + 1.5 × 四分位範囲」より大きい値の中での最小値

  • これらの「最小値」や「最大値」に収まらないケース → 外れ値 して表示される

  • 自民党には極端に大きな得票率の候補者(外れ値)が数人いる

  • これらの候補者の氏名を表示させてみる

df %>% 
  filter(year == 2021) %>%            # 2021年総選挙データだけに絞る
  filter(voteshare > 75) %>%  # 得票率が 75% 以上の候補者だけに絞る 
  select(pref, kun, seito, age, voteshare, vote, j_name) %>% 
  head(10)
# A tibble: 10 × 7
   pref    kun seito   age voteshare   vote j_name    
   <chr> <dbl> <chr> <dbl>     <dbl>  <dbl> <chr>     
 1 宮崎      3 自民     56      80.7 111845 古川禎久  
 2 宮城      6 自民     61      83.2 119555 小野寺五典
 3 群馬      5 自民     47      76.6 125702 小渕優子  
 4 広島      1 自民     64      80.7 133704 岸田文雄  
 5 香川      3 自民     53      79.8  94437 大野敬太郎
 6 山口      2 自民     62      76.9 109914 岸信夫    
 7 山口      3 自民     60      76.9  96983 林芳正    
 8 秋田      3 自民     57      78.0 134734 御法川信英
 9 石川      2 自民     47      78.4 137032 佐々木紀  
10 鳥取      1 自民     64      84.1 105441 石破茂    

  • マッピング要素として fill = seito を追加すれば、カラーで表示できる
df %>%
  filter(year == 2021) %>% # 2021年総選挙データだけに絞る
  mutate(seito = factor(seito,
                            levels = c("公明", 
                                       "自民", 
                                       "立憲", 
                                       "国民", 
                                       "維新",
                                       "社民", 
                                       "れい", 
                                       "共産", 
                                       "無所", 
                                       "N党", 
                                       "諸派"))) %>% # N党の「N」は全角英字
  ggplot() +
  geom_boxplot(aes(x = voteshare,
                   y = seito,
                   fill = seito)) +              
  labs(x = "政党", y = "得票率") +
  ggtitle("政党ごとの得票率:2021年総選挙") +
  theme_bw(base_family = "HiraKakuProN-W3") +
  theme(legend.position = "none")

3 Exercise

  • Q3.1:「2.2 箱ひげ図の色を変える」の分析手法を使い、2009年総選挙における得票率を政党ごとに箱ひげ図を使って描きなさい
    ・その際、政党ごとに色をカスタマイズし、民主党候補者を blue、自民党候補者を red それ以外の政党を grey にすること

  • Q3.2: 「2.4.4 政党名の表示順番をカスタマイズしたい場合」の分析手法を使い、2009年総選挙における得票率を政党ごとに箱ひげ図を使って描きなさい
    ・その際、箱ひげ図の上から得票率の高い順に白黒で表示しなさい

  • Q3.3: 「2.4.4 政党名の表示順番をカスタマイズしたい場合」の分析手法を使い、2009年総選挙において最も得票率の高かった民主党候補者の氏名・選挙区・年齢・得票率・票数の一覧を表示しなさい

参考文献
  • Tidy Animated Verbs
  • 宋財泫 (Jaehyun Song)・矢内勇生 (statuki statanai)「私たちのR: ベストプラクティスの探究」
  • 宋財泫「ミクロ政治データ分析実習(2022年度)」
  • 土井翔平(北海道大学公共政策大学院)「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