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

1. ヒストグラムとは

  • ヒストグラム (histogram) は連続変数の分布を示す方法の一つ

ヒストグラムと棒グラフの違い

  • ヒストグラムは連続変数(=間隔尺度と比率尺度)の分布を確認する普遍的な可視化方法
  • ヒストグラムの見た目は棒グラフと非常に似ている

  • 両者の違い:
    ・棒グラフは「離散変数」、ヒストグラムは「連続変数」を可視化する
    ・棒と棒の間の隙間の有無
変数 可視化の方法 特徴
離散変数 棒グラフ 棒の間の線あり
連続変数 ヒストグラム 棒の間の線なし
横軸が「総選挙年度」の棒グラフの場合
  • 2017年と2021年総選挙の間の総選挙は存在しない
  • 年度(名目尺度)は数字に見えるが「数字」としては扱っていないから
  • 年度は数値であってもその数値の値に意味がない
横軸が「総選挙での得票率」のヒストグラムの場合
  • 1%, 1.1%, …. 〜100%まで、無数の値が存在する
  • 棒を並べるとしたら隙間なく棒を並べる必要がある
    → 値ごとに棒は立てない
    → しかし、それぞれの棒には「棒の横軸上の位置と高さ」という情報が含まれている

2. ggplot2 を使ったヒストグラム

  • ggplot2 では geom_histogram() を使ってヒストグラムを描く
  • ヒストグラムを出力する連続変数を x にマッピングするだけ
  • 棒の高さは自動的に計算される
  • y に対してマッピングを行う必要はなく、x のみで描ける
  • 総選挙(1996-2021)における得票率 (voteshare) のヒストグラムを描いてみる

2.1 シンプルなヒストグラム

df <- read_csv("data/hr96-21.csv",
               na = ".")  
  • 自民党ダミー (ldp) を作る
df <- df %>% 
  mutate(ldp = if_else(seito == "自民", "自民党", "非自民党")) # 自民党ダミー (ldp) を作る  
df %>%
  ggplot() +
  geom_histogram(aes(x = voteshare)) # votehsare のヒストグラム

  • ヒストグラムは連続変数の分布を素早く確認することが目的

2.2 「良いヒストグラム」とは

  • 良いヒストグラムとは次の情報をわかりやすく表示するもの:
  1. 分布においてピークがいくつあるか
  2. ピークがある場合、どの辺が最も度数/密度が高いか
  • 「良いヒストグラム」を表示するため、棒の数を調整する必要がある
  • 以下の 3 つのヒストグラムのうち、どれが「良いヒストグラム」なのか考えてみる
    (本来、「ヒストグラム」には棒の間の線はないが、ここでは見やすくするため、ヒストグラムの棒の間に白い線を入れて表示している)

  • 「幅が狭すぎる」ヒストグラムは、ピークが 2 つあることはわかるが、無駄にギザギザが多い

  • 「幅が広すぎる」ヒストグラムは、ピークがどこにあるかわからない

  • 「幅が適度」ヒストグラムは、ピークが 2 つあることがわかる

  • どれが「良いヒストグラム」なのか?

  • 「幅が狭広すぎる」ヒストグラムはあまりにも多くの情報が失われている

  • 「幅が狭すぎる」ヒストグラムは情報が多すぎる
    → 「幅が適度」のヒストグラムが適切

  • どれが望ましいヒストグラムなのかは作図者が決める

  • 棒の数を調整した複数のヒストグラムを出力して比較する
    → 最も望ましいヒストグラムを選ぶ

棒の数調整方法: bins
  • 棒の「数」geom_histogram() 内、aes() の外に bins 引数を指定することで変更可能
  • 上で作成した「幅が適度」のヒストグラムでは、bins = 5 と指定している
棒の数調整方法: binwidth
  • 棒の「幅」geom_histogram() 内、aes() の外に binwidth 引数を指定することで変更可能
  • 上で作成した「幅が適度」のヒストグラムでは、binwidth = 5 と指定してみる
棒の色の調整方法
  • ヒストグラムをより見やすくするため、棒の枠線を追加している
  • 枠線を入れるかどうかは作図する側が判断する
  • 棒の枠線は geom_histogram() 内、aes() の外に color 引数を指定
  • ここでは枠線は白("white")に指定している

bin とbinwidth 棒の「幅」binwidthと棒の「数」binsはどちらか片方のみ指定可能
・両方指定することはできない

2.3 横軸の目盛り表示変更

  • 前節で作成した得票率のヒストグラムに hist_plot1 と名前を付けて表示してみる
hist_plot1 <- df %>%
  ggplot() +
  geom_histogram(aes(x = voteshare),
                 color = "white",
                 binwidth = 5) 
hist_plot1

このヒストグラムの x 軸の表示を変更したい
  • ヒストグラム hist_plot1 に、目盛り変更のレイヤを追加してみる

  • 目盛りを変更するレイヤー: scale_x_*(), scale_y_*()

  • * の箇所には各軸の尺度を指定

  • ヒストグラムは横軸も縦軸も「連続」した値 → * の箇所には continuous が入る

scale_x_continuous() x 軸の目盛りを変更 位置 ラベル
scale_y_continuous() y 軸の目盛りを変更 位置 ラベル
ここでは x 軸だけ変更してみる
  • 必要な引数:
    ・目盛りの位置を指定する breaks 引数
    ・目盛りのラベルを意味する labels 引数
    ・それぞれ長さ 1 以上のベクトルを指定する
    breakslabels に使用する実引数(=ベクトル)の長さは同じ長さ
    labels には character 型ベクトルを指定することもできる

  • 目盛りは 0 から 100 まで 10 間隔で付け、目盛りラベルもそれぞれ対応する値を指定

  • 公差 10 の等差数列ベクトルなので seq() 関数を使う

  • 目盛り調整済みのヒストグラムは hist_plot2 として格納、出力してみる

hist_plot2 <- hist_plot1 +
  scale_x_continuous(breaks = seq(0, 100, by = 10),
                     labels = seq(0, 100, by = 10))
hist_plot2

  • x 軸の表記が指定通りに変更された!

2.4 次元の追加

  • ヒストグラムにもう一つの次元を追加する場合
    → 棒グラフと同様「面の色分け」または「ファセット分割」が使える
  • ヒストグラムの場合「色分け」よりも「ファセット分割」の方が圧倒的に推奨

facet_wrap(~) を使う場合

  • hist_plot2 のヒストグラムは自民党ダミー(ldp)を使って分ける場合、棒グラフと同様 facet_wrap(~ldp) で分割できる
hist_plot2 + 
  facet_wrap(~ldp) +
  theme_bw(base_family = "HiraKakuProN-W3")

色分けを使う場合

  • 色分けして表示してみる
  • 棒グラフと同様、aes() 内に fill を指定する
注意すべき点:
  • 棒グラフのように position = "identity" を追加する必要がある
  • 立候補者が自民党か否かという基準でヒストグラムの色分けをしてみる
df %>%
  mutate(ldp = if_else(seito == "自民", "自民党", "非自民党")) %>%
   ggplot() +
   geom_histogram(aes(x = voteshare, 
                      fill = ldp), 
                  position = "identity",
                  binwidth = 10, 
                  color = "white") +
   labs(x = "得票率", 
        y = "立候補者数",
        fill = "") +
  theme_bw(base_family = "HiraKakuProN-W3")

  • このヒストグラムには深刻な問題がある
  • 自民党候補者の棒が非自民党候補者の棒の後ろに存在する
    → 自民党候補者の一部の棒が消えている
解決策:
  • alpha 引数を使って、棒の透明度を上げる
  • 全ての棒に対して適用するので aes() の外側に alpha を指定
    alpha = 0・・・透明
    alpha = 1・・・不透明
  • ここでは alpha = 0.5 に指定してみる
df %>%
  mutate(ldp = if_else(seito == "自民", "自民党", "非自民党")) %>%
   ggplot() +
   geom_histogram(aes(x = voteshare, 
                      fill = ldp), 
                  position = "identity",
                  binwidth = 10, 
                  color = "white",
                  alpha = 0.5) +
   labs(x = "得票率", 
        y = "立候補者数",
        fill = "") +
  theme_bw(base_family = "HiraKakuProN-W3")

絶対にやってはいけない可視化
  • 1996年〜2021年の総選挙に立候補した政党ごとに得票率を色分けしてみる
df %>%
   ggplot() +
   geom_histogram(aes(x = voteshare, 
                      fill = seito), 
                  position = "identity",
                  binwidth = 10, 
                  color = "white",
                  alpha = 0.5) +
   labs(x = "得票率", 
        y = "立候補者数",
        fill = "") +
  theme_bw(base_family = "HiraKakuProN-W3")

  • 情報が多い方が良いのはそのとおり
  • しかし「多すぎる」のも問題
3 つ以上のグループの分布を可視化する方法
  • 3 つ以上のグループの分布を可視化、表示させる政党数を絞る
df %>%
  filter(seito == "自民"|seito == "共産"|seito == "民主") %>%
   ggplot() +
   geom_histogram(aes(x = voteshare, 
                      fill = seito), 
                  position = "identity",
                  binwidth = 10, 
                  color = "white",
                  alpha = 0.5) +
   labs(x = "得票率", 
        y = "立候補者数",
        fill = "") +
  theme_bw(base_family = "HiraKakuProN-W3")

  • position = "identity" の指定をしなけば
    → それぞれの棒に占める各政党の候補者数を個別に重ね
    → それぞれの棒で各政党が占める割合を表示できる
df %>%
  filter(seito == "自民"|seito == "共産"|seito == "民主") %>%
   ggplot() +
   geom_histogram(aes(x = voteshare, 
                      fill = seito), 
                  binwidth = 10, 
                  color = "white",
                  alpha = 0.5) +
   labs(x = "得票率", 
        y = "立候補者数",
        fill = "") +
  theme_bw(base_family = "HiraKakuProN-W3")

  • どうしても 3 つ以上のグループの分布を一つのファセットでオーバーラップしたい場合
  • geom_histogram() の代わりに geom_density() を使う
df %>%
  filter(seito == "自民"|seito == "共産"|seito == "民主") %>%
   ggplot() +
   geom_density(aes(x = voteshare, 
                      fill = seito), 
                  color = "white",
                  alpha = 0.5,
                adjust = 0.8) +
   labs(x = "得票率", 
        y = "密度",
        fill = "") +
  theme_bw(base_family = "HiraKakuProN-W3")

  • これは密度曲線を出力する幾何オブジェクト
  • マッピングはヒストグラムと同じ
  • ただし、ヒストグラムではないため binwidthbins 引数は不要
  • その代わりに adjust 引数を使う(デフォルトは 1)
    adjust の値が小さいほど密度曲線がギザギザ
    adjust の値が大きいほど密度曲線が滑らか
  • 縦軸が数(count)でなく、密度(density)になる
    → 解釈の際は注意が必要

3 Exercise

  • Q3.1:
    2.4 次元の追加」の分析手法を使い、2021年総選挙における得票率のヒストグラムを自民党・非自民党候補者で色分けして描きなさい
    ・その際、幾何オブジェクト geom_histogram() を使うこと
    ・自民党候補者の棒と非自民党候補者の棒のオーバーラップにも留意して可視化すること

  • Q3.2:
    2.4 次元の追加」の分析手法を使い、2021年総選挙における得票率のヒストグラムを自民党・立憲民主党・共産党ごとに色分けして描きなさい
    ・その際、幾何オブジェクト geom_density() 密度曲線を出力すること

参考文献
  • 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