準備

まず、いつも通り、今回使うパッケージを読み込む。インストール済みでないものはまずインストールする。

library('ggmap')
library('readr')
library('dplyr')
library('tidyr')
library('xtable')
library('stargazer')
library('ggplot2')

分析結果を図表にする。

例として、 淺野・矢内 (2013) で使われているデータを利用する。衆議院総選挙の小選挙区データセット hr96-09.csv をダウンロードし、プロジェクト内の data フォルダ(他の場所がよければ自分で指定せよ)に保存しよう。

dir.create('data', showWarnings = FALSE)
download.file('http://www2.kobe-u.ac.jp/~yyanai/jp/quant-methods-stata/data/hr96-09.csv',
              destfile = 'data/hr96-09.csv')

このデータセットはCSV (カンマ区切り) 形式である。Rは、readr::read_csv() (またはパッケージなしで使えるread.csv())でCSVファイルを読み込むことができる。 Rは欠測値 (missing values) を NA (引用符等はなし)で表す。CSVファイル(あるいは他の外部ファイル)でNA 以外のコードで欠測値を表しているときは、 ファイルを読み込む際に欠測値コードをnaという引数で指定する。例えば、データファイルで “わからない (don’t know)” を\(9\)で、未回答を \(-1\) で表していて、これらを欠測値として扱いたいとき(それが「正しい」方法かどうかは於いておく)は、 na = c(9, -1) とする。

淺野・矢内 (2013) のCSVファイルは欠測を “.” で表しているので、次のようにしてデータを読み込む。

HR <- read_csv('data/hr96-09.csv', na = '.')  # dataset is in "data" folder
# Alternatively, you can use read.csv(), although we prefer readr::read_csv()
# HR <- read.csv('data/hr96-09.csv', na = '.')
head(HR)  # display the first 6 rows 
## Source: local data frame [6 x 16]
## 
##    year    ku   kun party              name   age status nocand    wl
##   <int> <chr> <int> <int>             <chr> <int>  <int>  <int> <int>
## 1  1996 aichi     1  1000 KAWAMURA, TAKASHI    47      2      7     1
## 2  1996 aichi     1   800     IMAEDA, NORIO    72      3      7     0
## 3  1996 aichi     1  1001     SATO, TAISUKE    53      2      7     0
## 4  1996 aichi     1   305   IWANAKA, MIHOKO    43      1      7     0
## 5  1996 aichi     1  1014       ITO, MASAKO    51      1      7     0
## 6  1996 aichi     1  1038  YAMADA, HIROSHIB    51      1      7     0
## Variables not shown: rank <int>, previous <int>, vote <int>, voteshare
##   <dbl>, eligible <int>, turnout <dbl>, exp <int>.
tail(HR)  # display the last 6 rows
## Source: local data frame [6 x 16]
## 
##    year        ku   kun party                name   age status nocand
##   <int>     <chr> <int> <int>               <chr> <int>  <int>  <int>
## 1  2009 yamanashi     2     1    NAGASAKI, KOTARO    41      2      4
## 2  2009 yamanashi     2   800    HORIUCHI, MITSUO    79      2      4
## 3  2009 yamanashi     2  1115 MIYAMATSU, HIROYUKI    69      1      4
## 4  2009 yamanashi     3  1001       GOTO, HITOSHI    52      2      3
## 5  2009 yamanashi     3   800           ONO, JIRO    56      2      3
## 6  2009 yamanashi     3  1115   SAKURADA, DAISUKE    47      1      3
## Variables not shown: wl <int>, rank <int>, previous <int>, vote <int>,
##   voteshare <dbl>, eligible <int>, turnout <dbl>, exp <int>.
glimpse(HR) # another way to check the data by dplyr
## Observations: 5,614
## Variables: 16
## $ year      (int) 1996, 1996, 1996, 1996, 1996, 1996, 1996, 1996, 1996...
## $ ku        (chr) "aichi", "aichi", "aichi", "aichi", "aichi", "aichi"...
## $ kun       (int) 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3...
## $ party     (int) 1000, 800, 1001, 305, 1014, 1038, 1, 1000, 800, 1001...
## $ name      (chr) "KAWAMURA, TAKASHI", "IMAEDA, NORIO", "SATO, TAISUKE...
## $ age       (int) 47, 72, 53, 43, 51, 51, 45, 51, 71, 30, 31, 44, 61, ...
## $ status    (int) 2, 3, 2, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, 2, 1...
## $ nocand    (int) 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7...
## $ wl        (int) 1, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 1, 0, 2...
## $ rank      (int) 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3...
## $ previous  (int) 2, 3, 2, 0, 0, 0, 0, 2, 1, 1, 0, 0, 0, 0, 0, 1, 3, 1...
## $ vote      (int) 66876, 42969, 33503, 22209, 616, 566, 312, 56101, 44...
## $ voteshare (dbl) 40.0, 25.7, 20.1, 13.3, 0.4, 0.3, 0.2, 32.9, 26.4, 2...
## $ eligible  (int) 346774, 346774, 346774, 346774, 346774, 346774, 3467...
## $ turnout   (dbl) 49.22, 49.22, 49.22, 49.22, 49.22, 49.22, 49.22, 51....
## $ exp       (int) 9828097, 9311555, 9231284, 2177203, NA, NA, NA, 1294...

これで、データセットがRに読み込まれた。HRという名前がこのデータフレームオブジェクトを参照している。

このデータセットは、複数の選挙結果を含んでいる。 どの年の選挙が含まれているか確認してみよう。 table() 関数で簡単な表ができる。 データフレームの中にあるそれぞれの変数にアクセスするために、with() 関数を一緒に使う。

with(HR, table(year))
## year
## 1996 2000 2003 2005 2009 
## 1261 1199 1026  989 1139
# Alternatively, you can do
# table(HR$year)

5つの選挙に関するデータがあることがわかる。 簡単のため、2009年のデータだけ取り出して練習に使おう。 特定の条件を満たす観測値だけを取り出すには、 dplyr::filter() が使える。

HR09 <- HR %>%
    filter(year == 2009)  # extract observations with year==2009
with(HR09, table(year))
## year
## 2009 
## 1139

ここでパイプ %>% はパイプの左側で評価された結果をパイプの右側に送り、右側の関数は受け取ったものを第1引数として利用する。したがって、HR09 %>% filter (year == 2009) の実行結果はfilter(HR09, year == 2009) と全く同じである。 つまり、この例ではパイプを使う必要はまったくない。 しかし、将来的にはパイプを多用することになるので、簡単な例を使ってしっかり使い方を身につけよう。パイプを複数回使えば、複雑な変換を簡単に行うことが可能になる。パイプは、magrittr パッケージに含まれているが、dplyr を読み込むと自動的にmagrittrも読み込まれるので、いつもdplyr読み込んでおけばよい。

以下では、2009年の衆院選の結果だけが含まれた HR09 を使って図表の作り方を学ぶ。

Rで表を作る

2009年の衆院選データを使い、候補者の立場(status, 現職か元職か新人か)と選挙の勝敗 (wl) のクロス表を作る。

(tbl_st_wl <- with(HR09, table(status, wl)))
##       wl
## status   0   1   2
##      1 559  81  43
##      2 168 174  52
##      3  15  45   2

このままではどの数字がどのカテゴリを表しているかわかりにくいので、変数にラベルをつけよう。 ラベルをつけるために、変数の種類を整数 (integer) から ファクタ (factor) に変える。 3つの変数、wl, status, party にラベルをつけよう。 後で使うかもしれないので、全体のデータ(2009年以外を含む)にラベルをつけ、2009年の分を改めて取り出そう。

# names of parties in the order of coded values
party_names <- c('independent', 'JCP', 'LDP', 'CGP', 'oki',
                 'tai', 'saki', 'NFP', 'DPJ', 'SDP',
                 'LF', 'NJSP', 'DRF', 'kobe', 'nii',
                 'sei', 'JNFP', 'bunka', 'green', 'LP',
                 'RC', 'muk', 'CP', 'NCP', 'ND',
                 'son', 'sek', 'NP', 'NNP', 'NPJ',
                 'NPD', 'minna', 'R', 'H', 'others')
HR <- HR %>%
    mutate(wl = factor(wl, levels = 0:2, labels = c('lost', 'won', 'zombie')),
           status = factor(status, levels = 1:3, 
                           labels = c('challenger', 'incumbent', 'ex-member')),
           party = factor(party, labels = party_names))
HR09 <- HR %>%
    filter(year == 2009)

先ほどと同じクロス表をもう一度作る。

(tbl_st_wl <- with(HR09, table(status, wl)))
##             wl
## status       lost won zombie
##   challenger  559  81     43
##   incumbent   168 174     52
##   ex-member    15  45      2

データの内容を理解するためには、この表で十分かもしれない。 しかし、この表をそのまま論文(または課題)にコピペして使ってはいけない。 論文等で使うには、表の見た目を整える必要がある。

そこですぐに思いつくのは、MS Excel やLibreOffice Calc などに数字を入力して表を作る方法だろう。 しかし、表計算ソフトに数字を手動で入力して表を作るのはやめたほうが良い。理由は2つある。第1に、入力ミスをする可能性がある。第2に、これがより重要だが、手入力は面倒(時間の無駄)である。 幸い、Rには見栄えのよい表を作るための関数があるので、それを利用する。

xtablestargazer を使ってLaTeX 用の表を作る

xtable

xtable::xtable() を使えば、RでLaTeX用の表を簡単に作ることができる。 LaTeX の使い方はこの授業では解説しないが、研究者を目指すなら使うべきである。 理由は、論文を書くのが楽になるからである。 LaTeXを使うことによって論文執筆が楽になる場面はたくさんあるが、表をRで作れるというのは楽できる場面の1つである。 計量分析を用いた論文では図表をたくさん使うので、 賢明な皆さん(特に研究で計量分析を使う皆さん)は、MS Word とお別れしましょう。

LaTeX がどんなものか知りたいなら、まず『LaTeX 2\(\epsilon\) 美文書作成入門』を読むことをすすめる。

LaTeX の表を作るには、表オブジェクトを xtable()に渡せばよい。 (行列または回帰分析の結果もそのまま渡せる。 詳しくは、methods(xtable) を実行されたい。)

xtbl_st_wl <- xtable(tbl_st_wl, align = 'lccc',
                     caption = "Candidate's Status and Election Result",
                     label = 'tbl:status-result')
print(xtbl_st_wl)
## % latex table generated in R 3.3.0 by xtable 1.8-2 package
## % Wed Jun 22 16:17:55 2016
## \begin{table}[ht]
## \centering
## \begin{tabular}{lccc}
##   \hline
##  & lost & won & zombie \\ 
##   \hline
## challenger & 559 &  81 &  43 \\ 
##   incumbent & 168 & 174 &  52 \\ 
##   ex-member &  15 &  45 &   2 \\ 
##    \hline
## \end{tabular}
## \caption{Candidate's Status and Election Result} 
## \label{tbl:status-result}
## \end{table}

この結果をコピペしてもよいが、次のようにtex ファイルに保存することもできる。

print(xtbl_st_wl, file = 'tbl-st-wl.tex')

表を微調整したいときは、保存したファイルを編集すればよい。

表は、LaTeX の代わりにHTML ように出力することもでできる。そのためには、type = ‘html’ とする。

print(xtbl_st_wl, type = 'html')
Candidate’s Status and Election Result
lost won zombie
challenger 559 81 43
incumbent 168 174 52
ex-member 15 45 2


R Markdown でHTML 出力するときは、この方法で表を作り、チャンクオプションでresults='asis'と指定する。

より詳しい使い方は、 The xtable gallery (by Jonathan Swinton) を参照されたい。


stargazer

回帰分析の結果を表にまとめるときは、stargazer::stargazer() が便利である(感じの悪い名前だが、便利なので我慢して使う。あるいは皮肉なのか?)。 例のために、実際には何の役にも立たない回帰直線を推定し、表を作ってみよう。

fit_1 <- lm(voteshare ~ I(exp / 1000000), data = HR09)
fit_2 <- lm(voteshare ~ previous, data = HR09)
fit_3 <- lm(voteshare ~ I(exp / 1000000) + previous, data = HR09)
label_explanatory <- c('expenditure (million yen)', 'previous wins', 'constant')
stargazer(fit_1, fit_2, fit_3,
          digits = 2, digits.extra = 0, align = TRUE,
          star.cutoffs = NA, omit.table.layout = 'n', # this line is IMPORTANT!
          keep.stat = c('n', 'adj.rsq', 'f'), df = FALSE,
          covariate.labels = label_explanatory,
          dep.var.caption = 'Outcome variable',
          dep.var.labels = 'Vote share (%)',
          title = 'Results of Linear Regressions',
          label = 'tbl:reg-res',
          out = 'stargazer-reg-res.tex')
## 
## % Table created by stargazer v.5.2 by Marek Hlavac, Harvard University. E-mail: hlavac at fas.harvard.edu
## % Date and time: Wed, Jun 22, 2016 - 16:17:55
## % Requires LaTeX packages: dcolumn 
## \begin{table}[!htbp] \centering 
##   \caption{Results of Linear Regressions} 
##   \label{tbl:reg-res} 
## \begin{tabular}{@{\extracolsep{5pt}}lD{.}{.}{-2} D{.}{.}{-2} D{.}{.}{-2} } 
## \\[-1.8ex]\hline 
## \hline \\[-1.8ex] 
##  & \multicolumn{3}{c}{Outcome variable} \\ 
## \cline{2-4} 
## \\[-1.8ex] & \multicolumn{3}{c}{Vote share (%)} \\ 
## \\[-1.8ex] & \multicolumn{1}{c}{(1)} & \multicolumn{1}{c}{(2)} & \multicolumn{1}{c}{(3)}\\ 
## \hline \\[-1.8ex] 
##  expenditure (million yen) & 3.07 &  & 2.14 \\ 
##   & (0.10) &  & (0.11) \\ 
##   & & & \\ 
##  previous wins &  & 5.41 & 2.85 \\ 
##   &  & (0.20) & (0.22) \\ 
##   & & & \\ 
##  constant & 7.74 & 16.89 & 8.42 \\ 
##   & (0.76) & (0.61) & (0.71) \\ 
##   & & & \\ 
## \hline \\[-1.8ex] 
## Observations & \multicolumn{1}{c}{1,124} & \multicolumn{1}{c}{1,139} & \multicolumn{1}{c}{1,124} \\ 
## Adjusted R$^{2}$ & \multicolumn{1}{c}{0.48} & \multicolumn{1}{c}{0.40} & \multicolumn{1}{c}{0.55} \\ 
## F Statistic & \multicolumn{1}{c}{1,028.24} & \multicolumn{1}{c}{770.86} & \multicolumn{1}{c}{676.97} \\ 
## \hline 
## \hline \\[-1.8ex] 
## \end{tabular} 
## \end{table}

LaTeX の表がコンソールに表示されるとともに、“stargazer-reg-res.tex” と言う名前のファイルに保存された。 ファイルが保存されたのは、out 引数でファイル名を指定したからである。

stargazer()を使うときは、star.cutoffs = NAomit.table.layout = “n” の指定を忘れずに。これを忘れると、ものすごく迷惑な星印が表についてしまう。私たちは政治学者(社会科学者)であって、天文学者ではないことをお忘れなく!

HTML 用の表は、type = “html” で得られる(type のデフォルトは ‘latex’ である)。 (R Markdown でHTML 出力するときは、チャンクオプションでresults=‘asis’ に。)

stargazer(fit_1, fit_2, fit_3,
          digits = 2, digits.extra = 0, align = TRUE,
          star.cutoffs = NA, omit.table.layout = 'n', # IMPORTANT!!!
          keep.stat = c('n', 'adj.rsq', 'f'), df = FALSE,
          covariate.labels = label_explanatory,
          dep.var.caption = 'Outcome variable',
          dep.var.labels = 'Vote share (%)',
          title = 'Results of Linear Regressions',
          type = 'html')
Results of Linear Regressions
Outcome variable
Vote share (%)
(1) (2) (3)
expenditure (million yen) 3.07 2.14
(0.10) (0.11)
previous wins 5.41 2.85
(0.20) (0.22)
constant 7.74 16.89 8.42
(0.76) (0.61) (0.71)
Observations 1,124 1,139 1,124
Adjusted R2 0.48 0.40 0.55
F Statistic 1,028.24 770.86 676.97


より詳しい使い方は、 A Stargazer Cheatsheet を参照されたい。


表を CSV ファイルに保存する

LaTeX をどうしても使いたくない場合、(まず、5,000回考え直し、それでもなお使いたくないなら)表をCSVファイルに保存し、それをExcel やCalc などで開いて編集することもできる。 表をCSV ファイルに保存するには、write.csv() を使う。

write.csv(tbl_st_wl, file = 'tbl-st-wl.csv')

現在の作業ディレクトリに、“tbl-st-wl.csv” という名前のファイルが保存されているはずである。 これをExcel 等で開いて表を整形すれば、数値を手入力する手間は省ける。


ggplot2 で図を作る

論文やプレゼンテーションで使う図は、ggplot2 を使って作る。 ggplot2 を使えば、Rで美しい図を作ることができる。 言うまでもなく、研究は見た目よりも中身(図が伝えるメッセージ)の方が大切である。 しかし、保持する情報が同じなら、美しい図の方が汚い図よりも望ましい。 汚い図を解読するより、美しい図を愉しむ方が多くの読者にとって楽である。 したがって、美しい図の方が、読者に情報を正しく伝達する可能性が高いと考えられる。 美しい図は、ggplot2 を使わなくてもできる。しかし、ggplot2 を使わずに美しい図を作るには、熟練Rユーザになる必要がる。ggplot2 を使えば、ある程度美しい(少なくとも読むに耐える)図がデフォルトでできる。 つまり、ggplot2 は美しい図を作るための必要条件ではないが、(ほぼ)十分条件である(ただし、統計の使い方を正しく理解していることを前提とする)。

ggplot2は(も) Hadley Wickham (日本の一部のRユーザは、「羽鳥先生」と呼んで崇拝している)によって開発された。

ggimage(hadley)

使い方は、ココ に載っている。 より詳しい使い方は、Hadley Wickham. (forhcoming). ggplot2: Elegant Graphics for Data Analysis, 2nd ed. (Springer) (ココ で入手できる)を参照されたい。

ggplot2 入門

ggplot2 で図を作るときはいつも ggplot2:ggplot() 関数を使う (ggplot2:qplot() でも簡単な図は作れるが、この関数の使い方は説明しない)。

ggplot() の第1引数には、データフレームを渡す。 したがって、ggplot2で図を作るためには、必要な変数を1つのデータフレームに保存する必要がある。

第2引数では、aesaestheticsの略)を指定する(より正確には、mapping = aes(…)である)。 視覚化したい変数をaesで指定する。 例えば、2次元の図(散布図など)を作るときには、 横軸 \(x\) と縦軸 \(y\) の変数を指定する。 さらに、色 (color)、大きさ (size) などを指定して、図で表現する次元を増やすことができる。

次に、ggplot()で作られたオブジェクトに、グラフィックの層 (layer) を加える。 異なる種類の図は、異なる種類の層 (layer) で作る。 例えば、散布図を作りたいときは、geom_point() 層を加える。 ヒストグラムには geom_histogram()を使う。 これらの例が示すように、グラフィック層は geomgeometry の略)から始まる。 1つの図に複数のグラフィック層を重ねることもできる。

最後に、図に必要な他の要素、例えば、軸ラベルや凡例を加える(ただし、凡例は通常は自動的にできる)。

例として、選挙費用 (exp) と過去の当選回数 (previous) の散布図を作ってみよう。 まず、ggplot()関数でggplotオブジェクトを作る。 次に、geom_point()で散布図用の層 (layer) を加える。 最後に、labs() で軸ラベルとタイトルをつける(論文で使う図を作るときは、タイトルを空欄にして、図のに番号つきのキャプションをつける。)

# 1. Create a ggplot object
scatter1 <- ggplot(HR09, aes(x = previous, y = exp))
# 2. Add the layer of the scatter plot 
scatter1 <- scatter1 + geom_point()
# 3. Add axis labels and the title
scatter1 <- scatter1 + labs(x = 'previous wins', y = 'money spent (yen)', 
                            title = 'Scatter Plot')
# 4. Print the figure on screeen
print(scatter1)

これで散布図ができた。表示以外のステップは、1度に実行することもできる。

scatter1 <- ggplot(HR09, aes(x = previous, y = exp)) +
    geom_point() +
    labs(x = 'previous wins',
         y = 'money spent (yen)',
         title = 'Scatter Plot')
print(scatter1)

図を表示するときには、print()を使うが、これを使わずに単に scatter1 としても通常は図が表示される。 しかし、安全のため、常にprint()を使ったほうが良い(R Markdownを使う場合は特に)。

次に、選挙費用のヒストグラムを作ってみよう。 通常のヒストグラムは1つの変数を図にするので、aes では x のみ指定すればよい。

histogram1 <- ggplot(HR09, aes(x = exp)) +
    geom_histogram() + 
    xlab('Money Spent (yen)') +
    ggtitle('Histogram - Frequnecy')
print(histogram1)

このヒストグラムの縦軸は、「数(count; frequency, 頻度)」である。 縦軸を確率密度にしたいときは、次のようにする。

histogram2 <- ggplot(HR09, aes(x = exp)) + 
    geom_histogram(aes(y = ..density..)) +
    xlab('Money Spent (yen)') +
    ggtitle('Histogram - Density')
print(histogram2)

このように、aesy = ..density..をしてすればよい。 “density” の前後についているドットは、この “density” がデータフレームにもともとあった変数ではなく、ggplot() によって計算され、ggplot 内に保存されているものであることを示している。

次に、選挙費用の箱ひげ図を、過去の当選回数別に作って並べてみよう。

box1 <- ggplot(HR09, aes(x = as.factor(previous), y = exp)) + geom_boxplot()
box1 <- box1 + labs(x = 'Previous Wins', y = 'Money Spent (yen)', title = 'Box Plot')
print(box1)

ここでは、 previous 変数を aes で指定するとき、as.factor() を使っている。 こうすることで、ggplotに previous がカテゴリー変数(したがって、箱ひげ図をグループ化できる)ことを伝えている。

続いて、得票率と選挙費用の散布図を作り、その上に回帰直線を重ね書きしてみよう。 回帰直線は、geom_smooth(method = 'lm') で描ける。

scatter2 <- ggplot(HR09, aes(x = exp, y = voteshare))  + geom_point()
scatter2 <- scatter2 + labs(x = 'Money Spent (yen)', y = 'Vote Share')
scatter3 <- scatter2 + geom_smooth(method = 'lm')
print(scatter3)

geom_smooth() はデフォルトで95%信頼区間を直線の周りに示す。 他の信頼度を使いたいときは、level を指定する。 例えば、50%信頼区間に変えるには次のようにする。

scatter4 <- scatter2 + geom_smooth(method = 'lm', level = .5)
print(scatter4)

信頼区間を示したくないときは、se = FALSE とする。

scatter5 <- scatter2 + geom_smooth(method = 'lm', se = FALSE)
print(scatter5)

ggplotで日本語を使う

通常の図で日本語を表示できるようにしただけでは、(Mac の)ggplot2で日本語を使うことはできない。 試しに、簡単な図を作ってみると、

plot(exp ~ previous, data = HR09,
     main = "日本語表示のテスト: ggplot を使わない場合",
     ylab = "選挙費用(円)", xlab = "当選回数")

test_jpn <- ggplot(HR09, aes(x = previous, y = exp)) + geom_point()
test_jpn <- test_jpn + 
    labs(x = "当選回数", y = "選挙費用(円)", title = "日本語表示のテスト: ggplot")
print(test_jpn)

のように、ggplotで作った図では日本語が表示されない。

ggplot2で日本語を使う場合、ggplotのテーマで日本語を表示できるフォンとを選ぶ必要がある。 Macでヒラギノ角ゴシックを使うには、以下のようにテーマを設定する(もちろん、他に好みのフォントがあれば、違うフォントを選んでも良い)。**Windowsの場合は特に何もしなくてよい(はず)。

フォントに、12ポイントのヒラギノ角ゴシックを指定する。

theme_set(theme_gray(base_size = 12, base_family = 'HiraKakuProN-W3'))
# または
# theme_set(theme_gray(base_size = 12, base_family = 'Hiragino Sans'))

先ほどの図を表示してみよう。

print(test_jpn)

これでうまくいかないときは以下を試す。

quartzFonts(HiraKaku = quartzFont(rep('Hiragino Kaku Gothic Pro W3', 4)))
theme_set(theme_gray(base_size = 12, base_family = 'HiraKaku'))

これで日本語が表示できるようになった。



ggplot で作った図を保存する

図を画像ファイル (PNG file) に保存する

ggplotで作った図は、 ggplot2::ggsave() で保存できる。 例えば、

dir.create('figs'. showWarnings = FALSE)
ggsave(file = 'figs/scatter-eg1.png', plot = scatter1, width = 6, height = 4.5)

で、scatter1 がfigs フォルダの中に ‘scatter-eg1.pn’ として保存される。 plot を指定しないと、最後に作った図が保存される。

図を保存するときは、実際に図として使う図の幅と高さを指定する。 幅 (width) が 6で 高さ (height) が 4.5 の図は、A4用紙を縦に置いた場合にはおおよそ半ページを占める。

図をPDFファイルとして保存する。

LaTeX ように図を保存するときは、PDF で保存したほうがよい。 Macでは、quartz()type = “pdf” を指定すればPDFができる。

quartz(file = 'scatter-eg1.pdf', family = 'sans', type = 'pdf',
       width = 6, height = 4.5)
  print(scatter1)
dev.off()

quartz() で新しいグラフィックデバイスを開き、そこにprint()で図を載せ、最後に dev.off()でデバイスを閉じている。 デバイスを閉じるのを忘れると、後で作った図もすべてこのデバイスに載ってしまうので、デバイスを閉じ忘れないように注意が必要である。

Windowsでは、(おそらく) ggsave() でPDFができる。

ggsave(file = 'scatter-eg1a.pdf', plot = scatter1)

これでうまくいかないときは、pdf() を次のように使う。

pdf(file = 'scatter-eg1b.pdf', widhth = 6, height = 4.5)
  print(scatter1)
dev.off()

ほんの少しだけ高度な使い方

グループごとにプロットの色やサイズ、形を変える

グループごとに色分け(サイズ分け、形分け)した図を作るには、aes でcolor (size, shape) にグループを表すカテゴリ変数を渡せばよい。 凡例は自動的にできる。

例として、議員が民主党 (DPJ) に所属していたかどうかで色分けしてみよう。 まず、民主党所属を表すダミー変数を作る。

HR09 <- HR09 %>%
    mutate(dpj = as.numeric(party == "DPJ"),
           dpj = factor(dpj, labels = c("その他", "民主党")))

このダミー変数を使い、得票率と選挙費用の散布図を、民主党議員かどうかによって色分けして作ってみよう。

sp_vs_ex <- ggplot(HR09, aes(x = exp, y = voteshare)) + 
    labs(x = "選挙費用(円)", y = "得票率 (%)")
sp_vs_ex1 <- sp_vs_ex + geom_point(aes(color = dpj))
print(sp_vs_ex1)

カテゴリ変数で色分けされた凡例を調整したいときは、scale_color_discrete(). さらに、guides() で凡例の表示順を変えることができる。

dpj_legend <- scale_color_discrete(name = "政党", labels = c("その他", "民主党"))
sp_vs_ex2 <- sp_vs_ex1 + 
    dpj_legend + 
    guides(color = guide_legend(reverse = TRUE))
print(sp_vs_ex2)

同じように、点の大きさを過去の当選回数によって変えてみよう。変数 previous を連続変数として扱うと、凡例は scale_size_continuous() で調整できる。

sp_vs_ex3 <- sp_vs_ex +
    geom_point(aes(color = dpj, size = previous)) +
    scale_size_continuous(name = "過去の当選回数") +    
    dpj_legend + 
    guides(color = guide_legend(reverse = TRUE))
print(sp_vs_ex3)

グループごとに作った図を並べる:Facetting

グループごとに分けて作った図を並べるときは、facetting (面刻み) という方法を使う ggplot2 には、2種類のfacetting が用意されている。 行グループと列グループによって並べる(グループ変数が2種類ある、または特定の方向に向かって並べたい)ときは、facet_grid()を使い、1つのグループ変数しか使わな(かつ、並べる方向は気にしない)ときはfacet_wrap()を使う。

まず、facet_grid()の使い方を説明する。 例として、民主党に所属するかどうかでグループ分けをした選挙費用のヒストグラムを作る。 Facetting は facet_grid(row_factor ~ column_factor) で行う。 ここでは、列要素のみを指定する(つまり、図を横に並べる)。

hist_lab <- labs(x = "選挙費用(円)", y = "度数")
hist_exp_dpj <- ggplot(HR09, aes(x = exp)) + geom_histogram()
hist_exp_dpj_1 <- hist_exp_dpj +
    facet_grid(. ~ dpj) +
    hist_lab
print(hist_exp_dpj_1)

縦に並べたいなら、次のようにする。

hist_exp_dpj_2 <- hist_exp_dpj +
    facet_grid(dpj ~ .) +
    hist_lab
print(hist_exp_dpj_2)

2つのグループ変数を使って図をグリッド常に並べることもできる。 例えば、

# change the labels of two variables
HR09 <- HR09 %>%
    mutate(dpj = factor(dpj, labels = c('Not Dem.', 'Dem.')),
           status = factor(status, labels = c('new', 'incumbent', 'ex')))
# call ggplot() again because we modified the data frame to use
hist_exp_dpj_st <- ggplot(HR09, aes(x = exp)) +
    geom_histogram() +
    facet_grid(dpj ~ status) +
    hist_lab
print(hist_exp_dpj_st)

のように並べられる。

グループごとに図を作る範囲を変えるには、scale = “free” とする(横軸のみ可変にするには scale = “free_x”、縦軸のみ可変にするにはn scale = “free_y” とする)。

hist_free_scale <- ggplot(HR09, aes(x = exp)) +
    geom_histogram() +
    facet_grid(dpj ~ status, scale = 'free') +
    hist_lab
print(hist_free_scale)

次に、 facet_wrap()の使い方を説明する。 この関数はグループ片数が1つだが、グループの数が多いために1行(あるいは1列)だけでは図を並べきれないときに便利である。 例として、選挙費用のヒストグラムを過去の当選回数別に作って並べてみよう。

hist_wins <- ggplot(HR09, aes(x = exp)) +
    geom_histogram() +
    facet_wrap( ~ previous, scale = 'free') +
    hist_lab
print(hist_wins)


表から図へ

クロス表をモザイク図にする

候補者の立場(現職、元職、新人)と選挙結果をもう1度クロス表にしてみよう。

(tbl_st_wl2 <- with(HR09, table(wl, status)))
##         status
## wl       new incumbent  ex
##   lost   559       168  15
##   won     81       174  45
##   zombie  43        52   2

この情報をより直感的(あるいは視覚的)に伝えるために、表の情報をモザイク図にする。 まず、ggplot2 を使えるようにするため、データフレームを作る。 その際、望んた形のデータフームを作るために、tidyr::gather() を使う。

# total num. of candidates by status
tbl_st <- with(HR09, table(status))
# turn the table into a matrix
tbl_st_wl2 <- as.matrix(tbl_st_wl2[1:3, 1:3])
tbl_st <- as.matrix(tbl_st[1:3])
# Create a data frame
# make variables of the share of each status and
# of the share of each result for each status
df <- data.frame(status = levels(HR09$status),
                 status_pct = 100 * as.vector(tbl_st / sum(tbl_st)),
                 win = 100 * as.vector(tbl_st_wl2[2,] / tbl_st),
                 zombie = 100 * as.vector(tbl_st_wl2[3,] / tbl_st),
                 lose = 100 * as.vector(tbl_st_wl2[1,] / tbl_st))
# Calculate the boundaries of categories on the horizontal axis
df <- df %>%
    mutate(xmax = cumsum(status_pct),
           xmin = xmax - status_pct)
## Remove the variable status_pct because we won't use it
df$status_pct <- NULL
# Reshape the data frame
df_long <- df %>% gather(key = result, value = voteshare, win:lose)
##################################################
## COMPARE df_long with df
## to understand what gather() has accomplished
## df
## df_long
###################################################
# Calculate the boundaries of categories on the vertical axis
df_long_1 <- df_long %>%
    group_by(status) %>%
    mutate(ymax = cumsum(voteshare),
           ymin = ymax - voteshare)
# Detemine the locations to put texts
df_long_1 <- df_long_1 %>%
    mutate(xtext = xmin + (xmax - xmin) / 2,
           ytext = ymin + (ymax - ymin) / 2)
# Make a mosaic plot
mosaic <- ggplot(df_long_1, aes(ymin = ymin, ymax = ymax,
                                xmin = xmin, xmax = xmax,
                                fill = result))
mosaic <- mosaic +
    geom_rect(color = I('grey')) +
    geom_text(aes(x = xtext, y = ytext, label = paste0(round(voteshare), '%'))) +
    geom_text(aes(x = xtext, y = 103, label = status)) +
    labs(x = '', y = '')
print(mosaic)

モザイク図ができた。 モザイク図を作るのは少し大変だが、表の内容を直感的・視覚的に捉えることができる。 読者の立場にたって考えれば、多少の手間は惜しまずにモザイク図を作った方が良い。 この図の欠点は、場所を取るということである。


回帰分析の結果をキャタピラ図で示す

例として、単純な重回帰を考える。

fit_1 <- lm(voteshare ~ I(exp / (10^6)) + previous, data = HR09)
tbl_fit_1 <- xtable(fit_1)
print(tbl_fit_1, type = 'html')
Estimate Std. Error t value Pr(>|t|)
(Intercept) 8.4151 0.7071 11.90 0.0000
I(exp/(10^6)) 2.1408 0.1143 18.74 0.0000
previous 2.8486 0.2182 13.06 0.0000

この結果をキャタピラ図にしてみよう。

# Create a data frame:
# The plot will have the names of explanatory variables,
# the estimated coefficients, and 95% CI
fit_1_df <- data.frame(variable = c('選挙費用(百万円)', '過去の当選回数'),
                       mean = coef(fit_1)[-1],
                       lower = confint(fit_1)[-1, 1],
                       upper = confint(fit_1)[-1, 2])
row.names(fit_1_df) <- NULL

## making a caterpillar plot
ctplr <- ggplot(fit_1_df, aes(x = reorder(variable, lower),
                              y = mean,
                              ymin = lower,
                              ymax = upper)) +
    geom_pointrange(size = 1.4) +
    geom_hline(yintercept = 0, linetype = 'dotted') +
    labs(x = '説明変数', y = '係数の推定値') +
    ggtitle('結果変数:得票率 (%)') +
    coord_flip()
print(ctplr)

キャタピラプロットができた。 この図については、回帰分析(2)以降でもう少し詳しく学ぶ。