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

1. 棒グラフとは

  • 棒グラフ (bar chart) は離散変数の分布を示す方法の一つ
変数 可視化の方法 特徴
離散変数 棒グラフ 棒の間の線あり

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

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

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

2. データの準備

衆院選データ (hr96-21.csv)の準備
hr96-21.csv をクリックしてデータをパソコンにダウンロード
・選挙データの読み取り

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

読み取った選挙データを確認

  • hr96_17.csv は1996年に衆院選挙に小選挙区が導入されて以来実施された 9 回の衆議院選挙(1996, 2000, 2003, 2005, 2009, 2012, 2014, 2017, 2021)の結果のデータ
  • df に含まれる変数名を表示させる
names(df)
 [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"
  • df には 22 個の変数が入っている
変数名 詳細
1. year 選挙年 (1996-2021)
2. pref 都道府県名
3. ku 小選挙区名
4. kun 小選挙区
5. wl 選挙の当落: 1 = 小選挙区当選、2 = 復活当選、0 = 落選
6. rank 当選順位
7. nocand 立候補者数
8. seito 候補者の所属政党
9. j_name 候補者の氏名(日本語)
10. gender 立候補者の性別: “male”, “female”
11. name 候補者の氏名(ローマ字)
12. previous これまでの当選回数(当該総選挙結果は含まない)
13. age 立候補者の年齢
14. exp 立候補者が使った選挙費用(総務省届け出)
15. status 候補者のステータス: 0 = 非現職、1 現職、2 = 元職
16. vote 得票数
17. voteshare 得票率 (%)
18. eligible 小選挙区の有権者数
19. turnout 小選挙区の投票率 (%)
20. seshu_dummy 世襲候補者ダミー: 1 = 世襲、0 = 非世襲(地盤世襲 or 非世襲)
21. jiban_seshu 地盤の受け継ぎ元の政治家の氏名と関係
22. nojiban_seshu 世襲元の政治家の氏名と関係
  • df に含まれる変数の型 (class) をチェック
str(df)
spec_tbl_df [9,660 × 22] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ year         : num [1:9660] 1996 1996 1996 1996 1996 ...
 $ pref         : chr [1:9660] "愛知" "愛知" "愛知" "愛知" ...
 $ ku           : chr [1:9660] "aichi" "aichi" "aichi" "aichi" ...
 $ kun          : num [1:9660] 1 1 1 1 1 1 1 2 2 2 ...
 $ wl           : num [1:9660] 1 0 0 0 0 0 0 1 0 2 ...
 $ rank         : num [1:9660] 1 2 3 4 5 6 7 1 2 3 ...
 $ nocand       : num [1:9660] 7 7 7 7 7 7 7 8 8 8 ...
 $ seito        : chr [1:9660] "新進" "自民" "民主" "共産" ...
 $ j_name       : chr [1:9660] "河村たかし" "今枝敬雄" "佐藤泰介" "岩中美保子" ...
 $ gender       : chr [1:9660] "male" "male" "male" "female" ...
 $ name         : chr [1:9660] "KAWAMURA, TAKASHI" "IMAEDA, NORIO" "SATO, TAISUKE" "IWANAKA, MIHOKO" ...
 $ previous     : num [1:9660] 2 2 2 0 0 0 0 2 0 0 ...
 $ age          : num [1:9660] 47 72 53 43 51 51 45 51 71 30 ...
 $ exp          : num [1:9660] 9828097 9311555 9231284 2177203 NA ...
 $ status       : num [1:9660] 1 2 1 0 0 0 0 1 2 0 ...
 $ vote         : num [1:9660] 66876 42969 33503 22209 616 ...
 $ voteshare    : num [1:9660] 40 25.7 20.1 13.3 0.4 0.3 0.2 32.9 26.4 25.7 ...
 $ eligible     : num [1:9660] 346774 346774 346774 346774 346774 ...
 $ turnout      : num [1:9660] 49.2 49.2 49.2 49.2 49.2 49.2 49.2 51.8 51.8 51.8 ...
 $ seshu_dummy  : num [1:9660] 0 0 0 0 0 0 0 0 1 0 ...
 $ jiban_seshu  : chr [1:9660] NA NA NA NA ...
 $ nojiban_seshu: chr [1:9660] NA NA NA NA ...
 - attr(*, "spec")=
  .. cols(
  ..   year = col_double(),
  ..   pref = col_character(),
  ..   ku = col_character(),
  ..   kun = col_double(),
  ..   wl = col_double(),
  ..   rank = col_double(),
  ..   nocand = col_double(),
  ..   seito = col_character(),
  ..   j_name = col_character(),
  ..   gender = col_character(),
  ..   name = col_character(),
  ..   previous = col_double(),
  ..   age = col_double(),
  ..   exp = col_double(),
  ..   status = col_double(),
  ..   vote = col_double(),
  ..   voteshare = col_double(),
  ..   eligible = col_double(),
  ..   turnout = col_double(),
  ..   seshu_dummy = col_double(),
  ..   jiban_seshu = col_character(),
  ..   nojiban_seshu = col_character()
  .. )
 - attr(*, "problems")=<externalptr> 
  • 文字列は chr、数値型は num で問題なし

総選挙データの記述統計

  • 総選挙データ (df) の変数の記述統計を表示させる
library(stargazer)
  • チャンクオプションで {r, results = "asis"} と指定する
stargazer(as.data.frame(df), 
          type ="html",
          digits = 2)
Statistic N Mean St. Dev. Min Max
year 9,660 2,007.88 7.68 1,996 2,021
kun 9,660 5.75 5.07 1 25
wl 9,660 0.48 0.67 0 2
rank 9,660 2.65 20.39 1 2,003
nocand 9,660 3.89 1.09 2 9
previous 9,660 1.48 2.46 0 19
age 9,656 51.22 11.13 25 94
exp 6,829 7,551,393.00 5,482,684.00 535 27,462,362
status 9,660 0.49 0.62 0 2
vote 9,660 55,987.87 40,626.34 177 210,515
voteshare 9,660 27.67 19.34 0.10 95.30
eligible 8,785 330,268.30 80,058.87 115,013 495,212
turnout 7,849 62.09 6.53 44.71 83.80
seshu_dummy 8,875 0.12 0.33 0 1

3. 棒グラフの作成

3.1 シンプルな棒グラフ (1)

  • 1996年から2021年までの 9 回の総選挙に出馬した立候補者数を棒グラフで表示してみる
  • ここで使う幾何オブジェクトは ggplot()geom_bar()
幾何オブジェクト 意味
ggplot() 図を描くキャンバスを用意する
geom_bar() 棒(棒グラフ)を描く
  • 必要なデータは次の 2 つ:
  1. 総選挙年 (1996, 2000, 2003,…, 2021)
  2. 総選挙年ごとの立候補者数
  • データは前節で作成した df を使う  
  • まず、table() 関数を使って、出馬した立候補者数を確かめる
table(df$year)

1996 2000 2003 2005 2009 2012 2014 2017 2021 
1261 1199 1026  989 1139 1294  959  936  857 
  • 棒グラフを描くために必要なデータは揃っている
  • 「総選挙年」を横軸、「立候補者数」を縦軸に指定
  • df の中には「総選挙年」を表す変数 year はある
  • しかし「立候補者数」を表す変数がない
  • 幾何オブジェクト geom_bar()aes() 内に指定するマッピングは、棒の横軸上の位置を意味する x だけで良い
  • 棒の高さ(つまり「立候補者数」)である yggplot2 が勝手に計算し表示してくれる
    → geom_bar(aes(x = year)) だけで良い
  • labs() レイヤーを使うと、x 軸と y 軸のラベルを指定できる
df %>% 
  ggplot() +
  geom_bar(aes(x = year)) +
  labs(x = "総選挙年", y = "立候補者総数") + 
  ggtitle("立候補者数(小選挙区:1996-2021年総選挙)") +
  theme_bw(base_family = "HiraKakuProN-W3") # 文字化け対策

  • x 軸の「総選挙年」の間隔が不自然
    その理由:yearclassnumeric だから
  • str() 関数を使って yearclass を確認
str(df$year)
 num [1:9660] 1996 1996 1996 1996 1996 ...
  • yearclassnumeric(数値)
    → Ryear を連続変数だと認識する
    → 総選挙は 4 年以内に実施されるが、必ずしも「4年ごと」に実施されるわけではない
    → x 軸の間隔がバラバラ

解決策:

  • yearclassnumeric(数値)から factor に変更する
df$year <- factor(df$year) 
  • yearclass を確認
str(df$year)
 Factor w/ 9 levels "1996","2000",..: 1 1 1 1 1 1 1 1 1 1 ...
  • yearclassfactor に変更された
df %>% 
  ggplot() +
  geom_bar(aes(x = year)) +
  labs(x = "総選挙年", 
       y = "立候補者総数") +
  ggtitle("平均立候補者数(小選挙区:1996-2021年総選挙)") +
  theme_bw(base_family = "HiraKakuProN-W3") # 文字化け対策

  • 図を作成したら、適切な名前(例えば bar_plot1 など)のオブジェクトとして格納できる
  • 図の保存方法の詳細は「4.9 グラフの保存方法」を参照
bar_plot1 <- df %>% 
  ggplot() +
  geom_bar(aes(x = year)) +
  labs(x = "総選挙年", 
       y = "立候補者総数")+ 
  ggtitle("立候補者数(小選挙区:1996-2021年総選挙)") +
  theme_bw(base_family = "HiraKakuProN-W3") # 文字化け対策
  • 格納された図を出力する場合はオブジェクト名のみ (bar_plot1) 入力すればよい

このグラフからわかること ・総選挙における立候補者総数は、1996年以降(2009年と2012年を除き)減少傾向にある

3.2 シンプルな棒グラフ(2)

  • 1996年から2021年までの総選挙における立候補者の「小選挙区ごとの立候補者数の平均」を棒グラフで表示してみる
  • 必要なデータは次の 2 つ:
  1. 総選挙年 (1996, 2000, 2003,…, 2021)
  2. 総選挙年・小選挙区ごとの立候補者数の平均
  • データは前節で作成した df を使う  
  • 「総選挙年」を横軸、「立候補者数の平均」を縦軸に指定
  • df の中には「総選挙年」を表す変数 year はある
  • しかし「立候補者数の平均」を表す変数がない
    → group_by() 関数を使って「総選挙・小選挙区ごとの立候補者数の平均」を計算し、ave_nocand1 として格納する
df1 <- df %>% 
  group_by(year, ku) %>% 
  summarise(ave_nocand1 = mean(nocand, na.rm = TRUE)) 

df1
# A tibble: 423 × 3
# Groups:   year [9]
   year  ku        ave_nocand1
   <fct> <chr>           <dbl>
 1 1996  aichi            6.33
 2 1996  akita            3.4 
 3 1996  aomori           3.93
 4 1996  chiba            4.75
 5 1996  ehime            3.57
 6 1996  fukui            4.17
 7 1996  fukuoka          3.90
 8 1996  fukushima        3.67
 9 1996  gifu             3.78
10 1996  gunma            3.84
# … with 413 more rows
  • ここで知りたいのは総選挙ごとの各小選挙区における立候補者数なので、ave_nocand1 の総選挙ごとの平均を求め 、ave_nocand2 として格納する   
df1 <- df1 %>% 
  group_by(year) %>% 
  summarise(ave_nocand2 = mean(ave_nocand1, na.rm = TRUE))

df1
# A tibble: 9 × 2
  year  ave_nocand2
  <fct>       <dbl>
1 1996         4.11
2 2000         3.93
3 2003         3.45
4 2005         3.40
5 2009         3.86
6 2012         4.20
7 2014         3.23
8 2017         3.27
9 2021         3.00
  • 幾何オブジェクト geom_bar()aes() 内に指定するマッピング:
    ・棒の横軸(総選挙年)x = year
    ・棒の高さ(立候補者の平均年齢)y = ave_nocand2
    → geom_bar(aes(x = year, y = ave_nocand2)) と指定
  • xy の両方を指定する場合、geom_bar()内側、かつ aes() の外側に stat = "identity" と指定する
  • labs() レイヤーを使うと、x 軸と y 軸のラベルを指定できる
df1 %>% 
  ggplot() +
  geom_bar(aes(x = year, 
               y = ave_nocand2),
           stat = "identity") +
  labs(x = "総選挙年", y = "小選挙区ごとの立候補者数の平均") + 
  ggtitle("平均立候補者数(小選挙区:1996-2021年総選挙)") +
  theme_bw(base_family = "HiraKakuProN-W3") # 文字化け対策

このグラフからわかること ・総選挙における立候補者総数は、減少傾向にある
→ 小選挙区比例代表並立制を導入した1996年の総選挙以降、二大「候補者」制に近づきつつある?

3.3 日本語表記の問題

  • 1996年から2021年までの総選挙における現職、新人、元職(以前、当選したが全回の選挙で落選した人)別の棒グラフを描いてみよう
  • 必要なデータは次の 2 つ:
  1. 現職・新人・元職の分類を表す変数 (status)
  2. 現職・新人・元職それぞれの立候補者数 (N)
  • データは前節で作成した df を使う  
  • status = 0 は新人、status = 1 は現職、 status = 2 は元職
  • まず、table() 関数を使って、出馬した立候補者数を確かめる
table(df$status)

   0    1    2 
5517 3510  633 
  • 棒グラフを描くために必要なデータは揃っている
  • 「現職・新人・元職の分類」(status) を横軸、「立候補者数」(N) を縦軸に指定
  • df の中には「現職・新人・元職の分類」を表す変数 status はある
  • しかし「立候補者数」を表す変数 N がない
  • 幾何オブジェクト geom_bar()aes() 内に指定するマッピングは、棒の横軸上の位置を意味する x だけで良い
  • 棒の高さである y(つまり「立候補者数 N」)は ggplot2 が勝手に計算し表示してくれる
    → geom_bar(aes(x = year)) と指定するだけで良い
  • labs() レイヤーを使うと、x 軸と y 軸のラベルを指定できる
  • ggtitle() レイヤーを使うと、メインタイトルを付けることができる
df %>% 
  ggplot() +
  geom_bar(aes(x = status)) +
  labs(x = "現職・新人・元職の分類", y = "立候補者総数") + 
  ggtitle("現職・新人・元職別の立候補者数(1996-2021年総選挙)") +
  theme_bw(base_family = "HiraKakuProN-W3") # 文字化け対策

  • 棒グラフには「新人・現職・元職の分類」の分類が「0, 1, 2」と表示されている
  • これを「新人・現職・元職」という日本語の表記に修正する必要がある
  • case_when() 関数を使って df の変数 status を日本語にリコーディングする
  • status_J という新たな変数として追加し、データフレーム df2 に格納する
df2 <- df %>%
   mutate(status_J = case_when(status == "0" ~ "新人",
                               status == "1" ~ "現職",
                               TRUE  ~ "元職"))
  • x = status の代わりに x = status_J と指定すれば良い
df2 %>% 
  ggplot() +
  geom_bar(aes(x = status_J)) +
  labs(x = "現職・新人・元職の分類", 
       y = "立候補者総数") + 
  ggtitle("現職・新人・元職別の立候補者数(1996-2021年総選挙)") +
  theme_bw(base_family = "HiraKakuProN-W3") # 文字化け対策

グラフ内の文字化け対策
Windows ユーザーの場合「文字化け対策」として次のコマンドを打つこと
theme_bw(base_family = "HiraKakuProN-W3")

Mac ユーザーの場合「文字化け対策」として次のコマンドを打つこと
theme_bw(base_family = "HiraKakuProN-W3")

3.4 棒グラフの「棒」の順番を変更する

3.4.1 factor() 関数  

  • 前節で作成した棒グラフでは左から「元職・新人・現職」という順番
  • この順番を「現職・新人・元職」に並べ替えたいとする
  • 変数 status_Jfactor 化する
    → 順番を並べ替える
  • df2ggplot() 関数に渡す前に mutate() 関数 を入れ、そこで status_J 変数を factor 化する
    → 順番を指定する:levels = c("現職", "新人", "元職")
df2 %>%
   mutate(status_J = factor(status_J,
                            levels = c("現職", "新人", "元職"))) %>% 
   ggplot() +
   geom_bar(aes(x = status_J)) +
   labs(x = "現職・新人・元職の分類", 
        y = "立候補者総数") + 
  ggtitle("現職・新人・元職別の立候補者数(1996-2021年総選挙)") +
  theme_bw(base_family = "HiraKakuProN-W3") # 文字化け対策

  • 想定通りの順番になっている

3.4.2 fct_inorder() 関数  

  • この関数は forcats パッケージに含まれている  
  • forcats パッケージは tidyverse パッケージに含まれている  
  • tidyverse パッケージを読み込んだら別途読み込む必要はない
  • fct_inorder() 関数は () 内の変数を factor 化し
  • 各要素が登場する順番に表示してくれる関数
  • df2status_J の値(=要素)がどのような順番で登場しているか確認してみる 
head(df2$status_J)
[1] "現職" "元職" "現職" "新人" "新人" "新人"
  • status_J の値(=要素)は「現職・元職・新人」の順番で登場している
  • この順番通りに status_J の値の順番が固定したい時に fct_inorder() 関数を使う   
df2 %>%
   mutate(status_J = fct_inorder(status_J)) %>% 
   ggplot() +
   geom_bar(aes(x = status_J)) +
   labs(x = "現職・新人・元職の分類", y = "立候補者総数") + 
  ggtitle("現職・新人・元職別の立候補者数(1996-2021年総選挙)") +
  theme_bw(base_family = "HiraKakuProN-W3") # 文字化け対策

3.5 次元を追加する

3.5.1 2021年総選挙での政党別立候補者数

  • 通常の棒グラフは x 軸と y 軸のみで構成される 2 次元グラフ
  • 棒グラフ上の棒には「ある総選挙 ( x 軸) の立候補者数 (y 軸)」といった 2 つの情報が含まれる
  • グラフの「次元数」は「情報量」を意味している
  • この情報量は ggplot2 の幾何オブジェクト内の aes() 内で指定する「引数の数」のこと
  • まず、2021年総選挙における政党 seito に属する立候補者数の棒グラフを作ってみる
  • 作図に必要な data.framedf_21 として用意する
df21 <- df %>% 
  filter(year == 2021) 
  • 2021年総選挙に出馬した政党一覧を表示する  
unique(df21$seito)
 [1] "自民" "立憲" "N党" "国民" "維新" "共産" "れい" "無所" "社民" "諸派"
[11] "公明"
  • 11 の政党を表す変数である seitofactor 化する
  • 棒グラフを表示する順番を指定する

棒を表示する順番を指定する方法
・例えば、政党 (seito) を自民、立憲、共産という順番で表示したけければ、変数をファクター化する際に順番を指定する
mutate(seito = factor(seito,
levels = c("自民", "立憲", "共産")))

df21 <- df21 %>%
   drop_na(seito) %>%
   mutate(seito = factor(seito, 
                         levels = c("自民", 
                                    "立憲", 
                                    "共産", 
                                    "維新",
                                    "無所", 
                                    "N党", 
                                    "国民",
                                    "れい",
                                    "公明",  
                                    "諸派", 
                                    "社民")))

3.5.2 立候補者数 N を計算(性別・政党別・当落別)

  • df21 を使って性別と政党別に立候補者数 N を計算
    → 計算結果に res_1 と名前を付ける
 res_1 <- df21 %>%
   group_by(seito, gender, wl) %>%  # 政党別、性別、当落別に立候補者数 N を計算
   summarise(N = n())
DT::datatable(res_1)
  • 棒グラフで可視化してみる
res_1 %>%
   ggplot() +
   geom_bar(aes(x = seito, 
                y = N), 
            stat = "identity") + 
  ggtitle("2021年総選挙での立候補者数(政党別・性別)") +
  theme_bw(base_family = "HiraKakuProN-W3") # 文字化け対策

  • この棒グラフが持つ情報は 2 つ
  • x で指定した所属政党 seito
  • y で指定した立候補者数 N

3.5.2 次元を追加する

fill = gender
  • 上で作成した図に、もう一つの次元として「候補者の性別」gender を加える

  • 次元を追加するときには aes() 内に引数を追加する

  • 「棒」は点・線・面のうち、面に該当

  • 面には次の要素がある:
    ・面の色(fill
    ・枠線の色(color
    ・枠線のタイプ(linetype
    ・透明度(alpha)など

  • もう一つの次元を追加するのであれば、識別する定番の方法は色

  • 棒グラフの場合、「面の色」と「枠線の色」をそれぞれ指定可能

  • ここでは面の色(fill)にマッピングする

  • aes()内に fill = gender を追加する

res_1 %>%
  ggplot() +
  geom_bar(aes(x = seito, 
               y = N, 
               fill = gender), 
           stat = "identity") + 
  ggtitle("2021年総選挙での立候補者数(政党別・性別)") +
  theme_bw(base_family = "HiraKakuProN-W3") # 文字化け対策

3.5.3 棒を左右にずらす

position = "dodge"
  • 上の図は政党ごとに男性と女性がどのような割合で立候補しているか確認できるが、少々見にくい
  • 政党ごとに棒を男女別に並べてずらして (dodge) みる
  • geom_bar() 内に position = "dodge" を指定する
  • aes() の「中」でなく、「外」に指定すること
res_1 %>%
  ggplot() +
  geom_bar(aes(x = seito, 
               y = N, 
               fill = gender), 
           stat = "identity",
           position = "dodge") + # position = "dodge" を aes() の「外」に指定 
  ggtitle("2021年総選挙での立候補者数(政党別・性別)") +
  theme_bw(base_family = "HiraKakuProN-W3") # 文字化け対策

3.5.4 凡例の位置変更

theme(legend.position = "bottom")
  • 凡例の位置を変更してみる
  • グラフ全体の見た目などを細かく調整するレイヤーは theme()
  • この theme() 内に legend.position = "bottom" を指定
    → 凡例が図の下段へ移動する
  • デフォルトは "right""top", "left", "none" が指定可能)
res_1 %>%
  ggplot() +
  geom_bar(aes(x = seito, 
               y = N, 
               fill = gender), 
           stat = "identity",
           position = "dodge") + 
  ggtitle("2021年総選挙での立候補者数(政党別・性別)") +
  theme_bw(base_family = "HiraKakuProN-W3") + # 文字化け対策
  theme(legend.position = "bottom") 

3.6 ファセット分割

  • ファセット(facet)分割は、色分けを抑えたい時に効果的
  • 特に白黒印刷の場合、識別可能な色は白・グレー・黒の 3 つくらい
  • しかし、色の種類は増えると、白黒印刷では識別するのが難しい
  • プロットの面(=ファセット)を分割することで色の増加が抑制できる
  • facet_wrap(~ 分割の基準となる変数名) のレイヤーを加える
  • 所属政党ごとの男女別立候補者数の棒グラフを作成する
  • それぞれの棒グラフは政党ごとに独立したファセットを持つ
res_1 %>%
  ggplot() +
  geom_bar(aes(x = gender, 
               y = N), 
           stat = "identity") +
  ggtitle("2021年総選挙での立候補者数(政党別・性別)") +
  theme_bw(base_family = "HiraKakuProN-W3") + # 文字化け対策
  facet_wrap(~ seito) # 分割の基準は seito と指定

  • 男女別にファセットと作って政党ごとに比較もできる
  • それぞれの棒グラフは性別ごとに独立したファセットを持つ
res_1 %>%
  ggplot() +
  geom_bar(aes(x = seito, 
               y = N), 
           stat = "identity") +
  ggtitle("2021年総選挙での立候補者数(政党別・性別)") +
  theme_bw(base_family = "HiraKakuProN-W3") + # 文字化け対策
  facet_wrap(~ gender) # 分割の基準は seito と指定

3.7 ラベルを見やすく修正

theme(axis.text.x = element_text(angle = XX, vjust = X, hjust = X)
  • 例えば、x 軸のラベルが長くて、左右でオーバーラップすることがよくある(ここでは大丈夫)
  • そのような時、x 軸のラベルを回転させると読みやすくなる
  • 横軸の目盛りラベルを修正するためには theme() レイヤーを追加し、axis.text.x を指定する
  • ラベルの回転が必要な場合は以下のコードから angle だけを修正する
  • ここでは 30 度回転させている
res_1 %>%
  ggplot() +
  geom_bar(aes(x = seito, 
               y = N), 
           stat = "identity") + 
  facet_wrap(~ gender) + # 分割の基準は seito と指定
  labs(x = "政党", y = "立候補者数") + # ラベル修正
  ggtitle("2021年総選挙での立候補者数(政党別・性別)") +
  theme_minimal() + # テーマを変えてみよう
  theme_bw(base_family = "HiraKakuProN-W3") + # 文字化け対策
  theme(axis.text.x        = element_text(angle = 30, vjust = 1, hjust = 1), # 35度回転
        panel.grid.major.x = element_blank()) # 縦線グリッドを削除することもできる

3.8 ファセットに新たなレイヤーを追加

  • aes() の内側に fill = 変数 と指定することで、新たなレイヤーを色別して追加できる
  • elec_result という変数を作ってから、ggplot() に渡す
res_1 %>%
  mutate(elec_result = if_else(wl == "0", "落選", "当選")) %>% 
  ggplot() +
  geom_bar(aes(x = seito, 
               y = N,
               fill = elec_result),                 # 新たなレイヤー elec_result の追加
           stat = "identity") + 
  facet_wrap(~ gender) +                       # 分割の基準は gender と指定
  labs(x = "政党", y = "立候補者数") +            # ラベル修正
  ggtitle("2021年総選挙での立候補者数(政党別・性別)") +
  theme_minimal() +                            # テーマを変えてみよう
  theme_bw(base_family = "HiraKakuProN-W3") +  # 文字化け対策
  theme(axis.text.x = element_text(angle = 40, # 40度回転
                                   vjust = 1,
                                   hjust = 1),
        panel.grid.major.x = element_blank())  + # 縦線グリッドを削除
   theme(legend.position = "bottom")             # レジェンドの位置指定

3.9 x 軸と y 軸を入れ替える

x 軸と y 軸を入れ替える方法

  • x 軸のラベルが長くて左右オーバーラップする場合
    → x 軸と y 軸を入れ替える
res_1 %>%
  ggplot() +
  geom_bar(aes(x = N, 
               y = seito), 
           stat = "identity") + 
  facet_wrap(~ gender) + # 分割の基準は gender と指定
  labs(x = "立候補者数", y = "政党") + # ラベル修正
  ggtitle("2021年総選挙での立候補者数(政党別・性別)") +
  theme_minimal() + # テーマを変えてみよう
  theme_bw(base_family = "HiraKakuProN-W3") 

coord_flip() を加える方法

  • coord_flip() を加えても、同様の結果が得られる
res_1 %>%
  ggplot() +
  geom_bar(aes(x = seito, 
               y = N), 
           stat = "identity") + 
  facet_wrap(~ gender) + # 分割の基準は gender と指定
  labs(x = "立候補者数", y = "政党") + # ラベル修正
  theme_minimal() + # テーマを変えてみよう
  theme_bw(base_family = "HiraKakuProN-W3") +
  coord_flip()

4. 棒に数値を表示させる  

geom_text(aes(label = 表示させたい内容)) を指定する

4.1 シンプルな棒グラフの場合

  • 例えば、次の棒グラフの棒それぞれに数値を表示させたいとする

  • 表示させる数値は全部で 11
  • 2021 年における 11 の政党それぞれの立候補者数
  • データフレーム res_1 の中身を確認する

res_1を作った課程を確認する

df <- read_csv("data/hr96-21.csv", # 総選挙データの読み込み
               na = ".")
df21 <- df %>% 
  filter(year == 2021) %>% # 2021年総選挙データだけに絞り df21 と名前を付ける  
  drop_na(seito) %>%    # seito の欠損値を除外する  
   mutate(seito = factor(seito,             # seito をファクター化し政党名の表示順序を指定  
                         levels = c("自民", 
                                    "立憲", 
                                    "共産", 
                                    "維新",
                                    "無所", 
                                    "N党", 
                                    "国民",
                                    "れい",
                                    "公明",  
                                    "諸派", 
                                    "社民")))
res_1 <- df21 %>%  # 政党別、性別、当落別に立候補者数 N を計算し、res_1と名前と付ける
   group_by(seito, gender, wl) %>%    
   summarise(N = n()) 
  • res_1 の内容を表示させる
DT::datatable(res_1)
  • res_1 を使って 11 の「政党それぞれの立候補者総数」= party_cand を計算
    → 結果を res_2 と名付ける
res_2 <- res_1 %>%
  group_by(seito) %>%
  summarize(party_cand = sum(N)) # 性別と政党ごとに N を合計し total と名前と付け res_2 に格納する  
  • res_2 の内容を表示させる
DT::datatable(res_2)
  • geom_text(aes(label = party_cand) を使って数値を表示させる  
res_2 %>%
  ggplot(aes(x = seito, 
               y = party_cand)) +
  geom_bar(aes(), 
           stat = "identity",
           position = position_dodge(width = 0.9)) +  
  geom_text(aes(label = party_cand), 
            vjust = 1.2, 
            colour = "yellow", 
            position = position_dodge(width = 0.9),
            size = 3) +
  theme_bw(base_family = "HiraKakuProN-W3") +
  ggtitle("2021年総選挙での立候補者数(政党別)") +
  theme(legend.position = "bottom") 

4.2 ずらした棒グラフの場合

  • 例えば、次の棒グラフの棒それぞれに数値を表示させたいとする

  • 表示させる数値は全部で 22

  • それらは 2021 年における 11 の政党それぞれの男女別の立候補者数

  • res_1 の内容を表示させる

DT::datatable(res_1)
  • res_1 を使って 11 の「政党それぞれの男女別の立候補者総数」= total を計算
    → 結果を res_3 と名付ける
res_3 <- res_1 %>%
  group_by(seito, gender) %>%
  summarize(total = sum(N)) # 性別と政党ごとに N を合計し total と名前と付け res_2 に格納する  
  • res_3 の内容を表示させる
DT::datatable(res_3)
  • geom_text(aes(label = party_cand) を使って数値を表示させる  
res_3 %>%
  ggplot(aes(x = seito, 
               y = total, 
               fill = gender)) +
  geom_bar(aes(), 
           stat = "identity",
           position = position_dodge(width = 0.9)) +  
  geom_text(aes(label = total), 
            vjust = 1.2, 
            colour = "white", 
            position = position_dodge(width = 0.9),
            size = 3) +
  theme_bw(base_family = "HiraKakuProN-W3") +
  ggtitle("2021年総選挙での立候補者数(政党別)") +
  theme(legend.position = "bottom") 

  • これだと令和、諸派、社民の数字が見えない
    → 棒の内側に数字を表示する設定 (vjust = 数値) を取り去り
  • 表示させる数字の色を黒に変更する → colour = "black"
res_3 %>%
  ggplot(aes(x = seito, 
               y = total, 
               fill = gender)) +
  geom_bar(aes(), 
           stat = "identity",
           position = position_dodge(width = 0.9)) + 
  geom_text(aes(label = total), 
            colour = "black",   # 表示させる数字の色を黒に変更
            position = position_dodge(width = 0.9),
            size = 3) +
  theme_bw(base_family = "HiraKakuProN-W3") +
  ggtitle("2021年総選挙での立候補者数(政党別・性別)") +
  theme(legend.position = "bottom") 

4.3 重ねた棒グラフの場合

position = "stack" と指定

  • 例えば、次の棒グラフの棒それぞれに数値を表示させたいとする

  • 表示させる数値は全部で 22

  • それらは 2021 年における 11 の政党それぞれの男女別の立候補者数

  • res_1 を使って 11 の「政党それぞれの男女別の立候補者総数」= total を計算
    → 結果を res_4 と名付ける

res_4 <- res_1 %>%
  group_by(seito, gender) %>%
  summarize(total = sum(N))
  • res_4 の内容を表示させる
DT::datatable(res_4)
  • geom_text(aes(label = party_cand) を使って数値を表示させる  
res_4 %>%
  ggplot(aes(x = seito, 
               y = total, 
               fill = gender)) +
  geom_bar(aes(), 
           stat = "identity",
           position = "stack") +  # position = "stack" に変更  
  geom_text(aes(label = total),
            colour = "black", 
            position = "stack",   # position = "stack" に変更  
            size = 3) +
  theme_bw(base_family = "HiraKakuProN-W3") +
  ggtitle("2021年総選挙での立候補者数(政党別・性別)") +
  theme(legend.position = "bottom") 

5. グラフの保存方法

  • 作成した図をファイルとして保存する方法は 2 つある
画像のフォーマット 拡張子 ファイルサイズ 画質
ベクトル画像 .pdf(推奨) .svg 大きい 拡大しても綺麗
ビットマップ画像 .png(推奨) .bmp .jpg .jpeg 小さい そこそこ綺麗
  • ここでは最後に作成した bar_plot_1 を高解像度の .png 形式で保存してみる
  • ggplot2 で作図した図は ggsave() 関数で保存する
Step 1:
  • 作成した図にオブジェクト名を付ける(ここでは bar_plot1 と付けた)
  • RProject フォルダ内に図を保存するためのフォルダ Figs を作る
Step 2:
  • 次のコマンドをチャンクに入力して knit する
library(ragg)
ggsave(filename = "Figs/plot1.png",     # 保存先とファイル名
       plot     = bar_plot1,           # 保存する図のオブジェクト名
       width    = 6,                   # 図の幅 (インチ)
       height   = 3,                   # 図の高さ (インチ)
       dpi      = 400,                 # 解像度
       device   = ragg::agg_png)       # 文字化け防止
  • ここでは、作成した図に bar_plot1 というオブジェクト名を付けた
  • RProject フォルダー内に Figs という名前を付けたフォルダを作成
  • 作成した図 bar_plot1plot1.png という名を付けて を保存している
  • 図のサイズはカスタマイズ可能
  • ここでは幅 5 インチ、高さ 4 インチに指定
  • 解像度(DPI)は 400 に指定(適切な解像度を選ぶこと)
  • ragg パッケージは、図を保存する際に文字化けを防いでくれる

6. Exercise

  • Q6.1:
    「3.1 シンプルな棒グラフ(1)」を参考にして、1996年から2021年総選挙で立候補した男性の候補者数を棒グラフで描きなさい

  • Q6.2:
    「3.1 シンプルな棒グラフ(1)」を参考にして、1996年から2021年総選挙で立候補した女性の候補者数を棒グラフで描きなさい

  • Q6.3:
    「3.5.3 棒を左右にずらす」を参考にして、1996年から2021年総選挙で立候補した男性と女性の候補者数を棒グラフで描きなさい

  • Q6.4(難):
    「3.8 ファセットに新たなレイヤーを追加」を参考にして、2021年総選挙において政党ごとの現職・新人・元職の当選者数を棒グラフで描きなさい
    ・その際、当選者(小選挙区当選者 + 復活当選者)と落選者を色分けして表示しなさい

  • Q6.5(難):
    「4.2 ずらした棒グラフの場合」を参考にして、2021年総選挙における当選者数(小選挙区・比例復活当選)と落選者数を棒グラフで描きなさい
    ・その際、当選者と落選者を色分けして表示し、それぞれの人数を棒グラフの内側(もしくはその付近)に表示させなさい

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