第4回講義資料
記述統計
スライド
セットアップ
まず、本日の実習で使用するパッケージを読み込む。
当該パッケージがインストールされていない場合、以下のようなメッセージが出力される。
Error in library(パッケージ名) : there is no package called ‘パッケージ名’
この場合、install.packages("パッケージ名")
でパッケージをインストールしてから読み込もう。
ただし、当該パッケージがインストールされているかが分からない場合もあろう。あるいは、インストールされているにも関わらず、再インストールしてしまう可能性もある。パッケージによってはインストールに数分かかる場合もあるのでこれは非常に非効率的である。ここで便利なものが{pacman}パッケージだ。{pacman}パッケージがインストールされている場合、p_load()
関数でパッケージを読み込むことができる。p_load()
関数は{pacman}パッケージが提供する関数であるため、予めlibrary(pacman)
で{pacman}パッケージを読み込む必要があるが、パッケージ名::関数名()
でパッケージを読み込まずに特定パッケージ内の関数を呼び出すこともできる。
一つの関数内に複数のパッケージが同時に読み込めるといったメリットも大きいが、{pacman}最大の特徴は「インストールされていない場合、インストールしてから読み込む」ことだ。一旦、{pacman}をインストールしておけば大変便利になる。
続いてデータを読み込もう。実習に使用するデータはdescstat_data.csv
であり、LMSから入手可能だ。.csv
形式データを読み込む関数はread_csv()
であり、()
内にはパスを含むファイル名を入力する。パス+ファイル名は必ず"
で囲むこと。たとえば、プロジェクト・フォルダー内のData
フォルダー内のdescstat_data.csv
ファイルなら、"Data/descstat_data.csv"
と入力する。また、read_csv()
だけだとデータが読み込まれて出力されるだけで終わる。つまり、現在の作業環境内に残らない。作業環境にデータを格納するためには<-
演算子を使用する。ここではデータを読み込み、raw_df
という名のオブジェクトとして作業環境内に格納しておこう。
パス(path)とは何かについてよく分からない人は授業後でも良いので必ず「本講義のためのファイル管理術」を精読すること。
データの中身を見るためにはオブジェクト名のみ入力すれば良い。
# A tibble: 3,000 × 272
USER_ID Q1 Q2 Q3 Q4 Q5_1 Q5_2 Q5_3 Q5_4 Q5_5 Q5_6 Q5_7
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 3 3 1 1 80 80 70 50 40 20 50
2 2 2 2 2 8 0 25 30 30 60 30 10
3 3 3 1 1 8 80 10 0 0 0 0 75
4 4 3 3 1 1 100 50 0 0 50 0 100
5 5 3 3 2 3 70 40 40 50 30 20 70
6 6 3 1 1 1 100 0 0 0 0 0 100
7 7 3 3 1 6 100 10 20 10 10 10 50
8 8 3 1 1 6 80 0 60 55 0 0 90
9 9 3 1 1 1 100 50 100 75 50 25 100
10 10 3 3 1 8 25 25 25 25 55 50 50
# … with 2,990 more rows, and 260 more variables: Q5_8 <dbl>, Q5_9 <dbl>,
# Q5_10 <dbl>, Q5_11 <dbl>, Q5_12 <dbl>, Q6_1 <dbl>, Q6_2 <dbl>, Q6_3 <dbl>,
# Q6_4 <dbl>, Q6_5 <dbl>, Q7 <dbl>, Q8 <dbl>, Q9 <dbl>, Q10_1 <dbl>,
# Q10_2 <dbl>, Q10_3 <dbl>, Q10_4 <dbl>, Q10_5 <dbl>, Q10_6 <dbl>,
# Q10_7 <dbl>, Q10_8 <dbl>, Q11 <dbl>, Q12 <dbl>, Q12S1 <dbl>, Q13 <dbl>,
# Q13S1 <dbl>, Q13S2 <dbl>, Q14 <dbl>, Q14S1 <dbl>, Q15 <dbl>, Q15S1 <dbl>,
# Q15S2 <dbl>, Q16 <dbl>, Q16S1 <dbl>, Q16S2 <dbl>, Q17_1 <dbl>, …
出力画面の最上段にはraw_df
の大きさが出力される。3,000 × 272
は「3000行、272列」の表形式データであることを意味する。非常に大きなデータであるため、この内容が一画面に収めることはできないだろう。read_csv()
で読み込まれたデータは画面に表示可能な範囲内でデータを出力してくれる。省略された列は出力画面の下段を見れば分かる。
raw_df
の変数名(列名)を確認するためには、names()
関数を使用する。
[1] "USER_ID" "Q1" "Q2" "Q3" "Q4" "Q5_1" "Q5_2"
[8] "Q5_3" "Q5_4" "Q5_5" "Q5_6" "Q5_7" "Q5_8" "Q5_9"
[15] "Q5_10" "Q5_11" "Q5_12" "Q6_1" "Q6_2" "Q6_3" "Q6_4"
[22] "Q6_5" "Q7" "Q8" "Q9" "Q10_1" "Q10_2" "Q10_3"
[29] "Q10_4" "Q10_5" "Q10_6" "Q10_7" "Q10_8" "Q11" "Q12"
[36] "Q12S1" "Q13" "Q13S1" "Q13S2" "Q14" "Q14S1" "Q15"
[43] "Q15S1" "Q15S2" "Q16" "Q16S1" "Q16S2" "Q17_1" "Q17_2"
[50] "Q17_3" "Q17_4" "Q17_5" "Q17_6" "Q17_7" "Q17_8" "Q18S1"
[57] "Q19S1" "Q20S1" "Q20S2" "Q20S3_1" "Q20S3_2" "Q20S3_3" "Q20S3_4"
[64] "Q20S3_5" "Q20S3_6" "Q21S1" "Q21S2" "Q21S3_1" "Q21S3_2" "Q21S3_3"
[71] "Q21S3_4" "Q21S3_5" "Q21S3_6" "Q22S1" "Q22S2" "Q22S3_1" "Q22S3_2"
[78] "Q22S3_3" "Q22S3_4" "Q22S3_5" "Q22S3_6" "Q23S1" "Q23S2" "Q23S3_1"
[85] "Q23S3_2" "Q23S3_3" "Q23S3_4" "Q23S3_5" "Q23S3_6" "Q24S1" "Q24S2"
[92] "Q24S3_1" "Q24S3_2" "Q24S3_3" "Q24S3_4" "Q24S3_5" "Q24S3_6" "Q25S1"
[99] "Q25S2" "Q25S3_1" "Q25S3_2" "Q25S3_3" "Q25S3_4" "Q25S3_5" "Q25S3_6"
[106] "Q26S1" "Q26S2" "Q26S3_1" "Q26S3_2" "Q26S3_3" "Q26S3_4" "Q26S3_5"
[113] "Q26S3_6" "Q27S1" "Q27S2" "Q27S3_1" "Q27S3_2" "Q27S3_3" "Q27S3_4"
[120] "Q27S3_5" "Q27S3_6" "Q28_1" "Q29" "Q30" "Q31" "Q32"
[127] "Q33" "Q34" "Q35_1" "Q35_2" "Q35_3" "Q35_4" "Q35_5"
[134] "Q35_6" "Q35_7" "Q35_8" "Q35_9" "Q35_10" "Q35_11" "Q35_12"
[141] "Q35_13" "Q35_14" "Q35_15" "Q36S1" "Q36S2" "Q36S3" "Q36S4"
[148] "Q36S5" "Q36S6" "Q36S7" "Q36S8" "Q36S9" "Q37" "Q38"
[155] "Q39" "Q40S1" "Q40S2" "Q40S3" "Q40S4" "Q40S5" "Q41_1"
[162] "Q41_2" "Q41_3" "Q41_4" "Q41_5" "Q41_6" "Q42" "Q43"
[169] "Q44" "Q45" "Q46" "Q47_1" "Q47_2" "Q47_3" "Q47_4"
[176] "Q47_5" "Q47_6" "Q47_7" "Q47_8" "Q47_9" "Q47_10" "Q47_11"
[183] "Q47_12" "Q47_13" "Q47_14" "Q47_15" "Q47_16" "Q47_17" "Q48_1"
[190] "Q48_2" "Q48_3" "Q48_4" "Q48_5" "Q48_6" "Q49_1" "Q49_2"
[197] "Q49_3" "Q50_1" "Q50_2" "Q50_3" "Q50_4" "Q50_5" "Q50_6"
[204] "Q51_1" "Q51_2" "Q51_3" "Q51_4" "Q51_5" "Q51_6" "Q51_7"
[211] "Q51_8" "Q51_9" "Q51_10" "Q51_11" "Q51_12" "Q51_13" "Q51_14"
[218] "Q51_15" "Q52" "Q53" "Q54" "Q55" "Q56_1" "Q56_2"
[225] "Q56_3" "Q56_4" "Q56_5" "Q56_6" "Q56_7" "Q57" "Q58_1"
[232] "Q58_2" "Q58_3" "Q58_4" "Q58_5" "Q58_6" "Q58_7" "Q58_8"
[239] "Q58_9" "Q58_10" "Q58_11" "Q58_12" "Q58_13" "Q58_14" "Q58_15"
[246] "Q58_16" "Q59" "Q59_1" "Q59_2" "Q59_3" "Q59_4" "X2_1"
[253] "X2_2" "X2_3" "Q60" "Q60S1" "Q61" "Q62S1" "Q62S2"
[260] "Q62S4" "Q63" "Q63S1" "Q63S2" "Q63S4" "Q64" "Q65"
[267] "seg" "sex" "age" "chiiki" "QVOTES" "QVOTEP"
また、データの大きさはdim()
関数でも確認することができる。
最後に出力される画面の行数についてだが、デフォルトでは10行出力となっている。もし、15行を出力したい場合はprint()
関数を使用し、n
引数で指定することができる。
# A tibble: 3,000 × 272
USER_ID Q1 Q2 Q3 Q4 Q5_1 Q5_2 Q5_3 Q5_4 Q5_5 Q5_6 Q5_7
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 3 3 1 1 80 80 70 50 40 20 50
2 2 2 2 2 8 0 25 30 30 60 30 10
3 3 3 1 1 8 80 10 0 0 0 0 75
4 4 3 3 1 1 100 50 0 0 50 0 100
5 5 3 3 2 3 70 40 40 50 30 20 70
6 6 3 1 1 1 100 0 0 0 0 0 100
7 7 3 3 1 6 100 10 20 10 10 10 50
8 8 3 1 1 6 80 0 60 55 0 0 90
9 9 3 1 1 1 100 50 100 75 50 25 100
10 10 3 3 1 8 25 25 25 25 55 50 50
11 11 1 2 2 3 60 30 25 10 10 0 60
12 12 2 2 2 6 50 50 50 50 50 50 50
13 13 3 1 1 3 100 5 30 5 0 0 100
14 14 3 3 2 8 60 70 70 50 70 50 50
15 15 2 3 3 7 50 50 50 50 50 50 50
# … with 2,985 more rows, and 260 more variables: Q5_8 <dbl>, Q5_9 <dbl>,
# Q5_10 <dbl>, Q5_11 <dbl>, Q5_12 <dbl>, Q6_1 <dbl>, Q6_2 <dbl>, Q6_3 <dbl>,
# Q6_4 <dbl>, Q6_5 <dbl>, Q7 <dbl>, Q8 <dbl>, Q9 <dbl>, Q10_1 <dbl>,
# Q10_2 <dbl>, Q10_3 <dbl>, Q10_4 <dbl>, Q10_5 <dbl>, Q10_6 <dbl>,
# Q10_7 <dbl>, Q10_8 <dbl>, Q11 <dbl>, Q12 <dbl>, Q12S1 <dbl>, Q13 <dbl>,
# Q13S1 <dbl>, Q13S2 <dbl>, Q14 <dbl>, Q14S1 <dbl>, Q15 <dbl>, Q15S1 <dbl>,
# Q15S2 <dbl>, Q16 <dbl>, Q16S1 <dbl>, Q16S2 <dbl>, Q17_1 <dbl>, …
データハンドリング
通常、データの分析の歳、読み込んだデータをすべて利用することはあまりない(クリーニング済みのデータならすべて使う)。したがって、分析を始める前に、分析に使用するデータのみを残しておいた方が効率的であろう。データハンドリングについては前期の「ミクロ政治データ分析実習」の「データハンドリング」、『私たちのR』の第12、13、14、15章を参照されたい。ここではまず、記述統計を出したい変数のみを残し、抽出後のデータをdf
という名の新しいオブジェクトとして作業環境内に格納する。select()
関数の使い方は『私たちのR』の第12章を参照すること。
df <- raw_df %>%
select(ID = USER_ID, # 回答者ID
Gender = sex, # 性別
Age = age, # 年齢
Education = Q61, # 最終学歴
Voted = Q15, # 投票参加 (2016参院選)
VotedParty = Q15S2, # 投票先 (2016参院選)
T_Jimin = Q5_7, # 自民に対する感情温度
T_Minshin = Q5_11) # 民進に対する感情温度
df
# A tibble: 3,000 × 8
ID Gender Age Education Voted VotedParty T_Jimin T_Minshin
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 2 69 4 1 7 50 30
2 2 2 47 3 2 NA 10 50
3 3 2 37 2 1 1 75 0
4 4 1 51 4 1 1 100 50
5 5 1 38 4 2 NA 70 30
6 6 1 71 2 1 1 100 0
7 7 1 47 3 1 7 50 10
8 8 1 71 2 1 1 90 0
9 9 1 75 4 1 1 100 50
10 10 2 66 3 1 2 50 55
# … with 2,990 more rows
# A tibble: 3,000 × 8
ID Gender Age Education Voted VotedParty T_Jimin T_Minshin
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 2 69 4 1 7 50 30
2 2 2 47 3 0 NA 10 50
3 3 2 37 2 1 1 75 0
4 4 1 51 4 1 1 100 50
5 5 1 38 4 0 NA 70 30
6 6 1 71 2 1 1 100 0
7 7 1 47 3 1 7 50 10
8 8 1 71 2 1 1 90 0
9 9 1 75 4 1 1 100 50
10 10 2 66 3 1 2 50 55
# … with 2,990 more rows
それではこの変数らの記述統計量を計算してみよう。
記述統計
記述統計量(descriptive statistics)とはある変数が持つ情報を要約した数値である。例えば、df
のAge
列は回答者の年齢の変数である。この回答者たちの年齢について語る時、「このデータの回答者の年齢は69、47、37、51、…、18歳ですよ」という人はいないだろう。4-5人分のデータならまだしも、3000人の回答者ならあり得ない。我々は普段、「このデータの回答者の年齢はだいたいXX歳ですよ」とか、「真ん中の年齢はYY歳ですよ」と言うだろう。また、年齢の格差/ばらつきを語るときも標準偏差や範囲(「18歳から75歳までいますよ」など)を言うのが普通であろう。このように元の長い情報を一つの数値として要約したものが記述統計量である。
Rには記述統計量を計算するいくつかの関数が用意されている。
mean()
: 平均値median()
: 中央値var()
: 不偏分散sd()
: 不偏標準偏差min()
、max()
: 最小値と最大値
たとえば、df
のAge
列(df$Age
)の平均値は以下のように計算する。na.rm = TRUE
は「もしdf$Age
に欠損値がある場合、それは除外して平均値を計算する」ことを意味する。
同じやり方で中央値(median()
)、最小値(min()
)、最大値(max()
)などが計算できる。しかし、本講義ではtidyverseパッケージ群を積極的に活用しているため、ここからは{dplyr}パッケージ(tidyverseを構成するパッケージの一つであり、{tidyverse}を読み込むと自動的に読み込まれる)のsummarise()
関数を使用する。summarise()
関数の詳細については、『私たちのR』の第13章を参照すること。ここではAge
変数の平均値、中央値、標準偏差、最小値、最大値、有効ケース数を計算し、それぞれMean
、Median
、SD
、Min
、Max
、N
という名の列として出力してみよう。
df %>%
summarise(Mean = mean(Age, na.rm = TRUE),
Median = median(Age, na.rm = TRUE),
SD = sd(Age, na.rm = TRUE),
Min = min(Age, na.rm = TRUE),
Max = min(Age, na.rm = TRUE),
N = sum(!is.na(Age)))
# A tibble: 1 × 6
Mean Median SD Min Max N
<dbl> <dbl> <dbl> <dbl> <dbl> <int>
1 47.3 47 15.6 18 18 3000
有効ケース数(欠損していないケースの数)を計算する方法がやや面倒である。これはまずis.na()
関数を使って、当該変数が欠損していればTRUE
、そうでなければFALSE
と判定する。そしてis.na()
の前には否定演算子!
が付いている。つまり、is.na()
から得られた結果が逆となり、欠損していればFALSE
、値があればTRUE
になる。RにおいてTRUE
は1、FALSE
は0扱いとなるので、この合計(sum()
)を求めることで欠損していないケースの数が計算できるようになる。
名目変数の場合
これまでの内容は変数が連続変数(continuous variable)に限った話である。名目変数(categorical variable)の場合、平均値などは存在しない。100円と1万円の平均値は計算できるものの、男性と女性の平均値や北海道と鹿児島の平均値などはあり得ないからだ。しかし、名目変数でもデータ分析に使われる場面は多く、分析に使われる以上、記述統計量をしっかりと掲載すべきである。
名目変数の記述する簡単な方法としては度数分布表がある。たとえば、df
の場合、性別(Gender
)は男性(=1)と女性(=2)で構成されている。つまり、2つの要素(levels)で構成される変数だ。度数分布表は各要素がいくつあるかを示したものであり、table()
関数で簡単に確認することができる。
また、{dplyr}を使う場合、count()
関数を使用すれば良い。
しかし、連続変数用の記述統計表と名目変数用の度数分布表を分けることは非効率的である。分析に用いられる名目変数が数が多いと尚更だ。できれば名目変数も連続変数と同じ表で記述統計量を出した方が良いだろう。そのためには名目変数をダミー変数として変換すれば、平均値や標準偏差などが計算できるようになる。
ダミー変数は0と1のみで構成される変数である。たとえば、性別変数(Gender
列)は名目変数であるが、現在、1(男性)と2(女性)の2つの値で構成されている。この変数を男性ダミー変数と女性ダミー変数といった2つの変数に変換することである。男性ダミー変数はGender
の値が1なら、つまり当該回答者が男性(=1)なら1の値を、それ以外の場合は0の値をとる。女性ダミー変数の場合、当該回答者が女性(=2)なら1の値を、それ以外の場合は0の値をとる。if_else()
関数を使って男性ダミー変数(Male
)と女性ダミー変数(Female
)を作ってみよう。このダミー変数はGender
列の後ろにし、df2
という名のオブジェクトとして格納する。
df2 <- df %>%
mutate(Male = if_else(Gender == 1, 1, 0),
Female = if_else(Gender == 2, 1, 0),
.after = Gender)
df2
# A tibble: 3,000 × 10
ID Gender Male Female Age Education Voted VotedParty T_Jimin T_Minshin
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 2 0 1 69 4 1 7 50 30
2 2 2 0 1 47 3 0 NA 10 50
3 3 2 0 1 37 2 1 1 75 0
4 4 1 1 0 51 4 1 1 100 50
5 5 1 1 0 38 4 0 NA 70 30
6 6 1 1 0 71 2 1 1 100 0
7 7 1 1 0 47 3 1 7 50 10
8 8 1 1 0 71 2 1 1 90 0
9 9 1 1 0 75 4 1 1 100 50
10 10 2 0 1 66 3 1 2 50 55
# … with 2,990 more rows
df2
にはもう一つの名目変数がある。それは投票先を意味するVotedParty
変数だ。VotedParty
は1から7までの整数で構成されている。VotedParty
の値が1なら自民党に投票、2なら民進党に投票、…といった変数であり、これは計7個のダミー変数となる。
df2 <- df2 %>%
mutate(VotedParty_Jimin = if_else(VotedParty == 1, 1, 0),
VotedParty_Minshin = if_else(VotedParty == 2, 1, 0),
VotedParty_Komei = if_else(VotedParty == 3, 1, 0),
VotedParty_Ishin = if_else(VotedParty == 4, 1, 0),
VotedParty_Kyosan = if_else(VotedParty == 5, 1, 0),
VotedParty_Etc = if_else(VotedParty == 6, 1, 0),
VotedParty_DK = if_else(VotedParty == 7, 1, 0),
.after = VotedParty)
df2
# A tibble: 3,000 × 17
ID Gender Male Female Age Educa…¹ Voted Voted…² Voted…³ Voted…⁴ Voted…⁵
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 2 0 1 69 4 1 7 0 0 0
2 2 2 0 1 47 3 0 NA NA NA NA
3 3 2 0 1 37 2 1 1 1 0 0
4 4 1 1 0 51 4 1 1 1 0 0
5 5 1 1 0 38 4 0 NA NA NA NA
6 6 1 1 0 71 2 1 1 1 0 0
7 7 1 1 0 47 3 1 7 0 0 0
8 8 1 1 0 71 2 1 1 1 0 0
9 9 1 1 0 75 4 1 1 1 0 0
10 10 2 0 1 66 3 1 2 0 1 0
# … with 2,990 more rows, 6 more variables: VotedParty_Ishin <dbl>,
# VotedParty_Kyosan <dbl>, VotedParty_Etc <dbl>, VotedParty_DK <dbl>,
# T_Jimin <dbl>, T_Minshin <dbl>, and abbreviated variable names ¹Education,
# ²VotedParty, ³VotedParty_Jimin, ⁴VotedParty_Minshin, ⁵VotedParty_Komei
あとはGender
とVotedParty
列は不要なので、こちらを除外する。
# A tibble: 3,000 × 15
ID Male Female Age Education Voted VotedParty…¹ Voted…² Voted…³ Voted…⁴
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 0 1 69 4 1 0 0 0 0
2 2 0 1 47 3 0 NA NA NA NA
3 3 0 1 37 2 1 1 0 0 0
4 4 1 0 51 4 1 1 0 0 0
5 5 1 0 38 4 0 NA NA NA NA
6 6 1 0 71 2 1 1 0 0 0
7 7 1 0 47 3 1 0 0 0 0
8 8 1 0 71 2 1 1 0 0 0
9 9 1 0 75 4 1 1 0 0 0
10 10 0 1 66 3 1 0 1 0 0
# … with 2,990 more rows, 5 more variables: VotedParty_Kyosan <dbl>,
# VotedParty_Etc <dbl>, VotedParty_DK <dbl>, T_Jimin <dbl>, T_Minshin <dbl>,
# and abbreviated variable names ¹VotedParty_Jimin, ²VotedParty_Minshin,
# ³VotedParty_Komei, ⁴VotedParty_Ishin
これで名目変数も連続変数と同じやり方で記述統計量が計算できる。
{fastDummies}の利用
しかし、以上の作業はかなり面倒だろう。7個の変数でも大変だが、たとえば回答者の都道府県があれば、計47行のコードを書く必要がある。このように面倒なダミー変数の作成を{fastuDummies}パッケージを使えばたった数行のコードでダミー化ができる。手順は以下の通りである。
- 名目変数をfactor型変数へ変換する。
- {fastDummies}パッケージの
dummy_cols()
関数でダミー化する。 - 生成された列を適宜修正する(変数名や位置など)。
それではまず、df
のGender
とVotedParty
列をfactor化してみよう。Gender
の場合、値が1なら"Male"
、2なら"Female"
を付ける。VotedParty
は値が1なら"Jimin"
、2なら"Minshin"
、3なら"Komei"
、4なら"Ishin"
、5なら"Kyosan"
、6なら"Etc"
(その他の政党)、7なら"DK"
(覚えていない/答えたくない)とする。修正後、df
はdf3
という名の新しいオブジェクトとして作業環境内に格納する。
df3 <- df %>%
mutate(Gender = factor(Gender, levels = c(1, 2),
labels = c("Male", "Female")),
VotedParty = factor(VotedParty, levels = 1:7,
labels = c("Jimin", "Minshin", "Komei", "Ishin",
"Kyosan", "Etc", "DK")))
df3
# A tibble: 3,000 × 8
ID Gender Age Education Voted VotedParty T_Jimin T_Minshin
<dbl> <fct> <dbl> <dbl> <dbl> <fct> <dbl> <dbl>
1 1 Female 69 4 1 DK 50 30
2 2 Female 47 3 0 <NA> 10 50
3 3 Female 37 2 1 Jimin 75 0
4 4 Male 51 4 1 Jimin 100 50
5 5 Male 38 4 0 <NA> 70 30
6 6 Male 71 2 1 Jimin 100 0
7 7 Male 47 3 1 DK 50 10
8 8 Male 71 2 1 Jimin 90 0
9 9 Male 75 4 1 Jimin 100 50
10 10 Female 66 3 1 Minshin 50 55
# … with 2,990 more rows
続いて、{fastDummies}のdummy_cols()
関数でGender
とVotedParty
をダミー変数に変換する。第一引数はダミー変数にしたい変数の名前を"
で囲んだものを入れる。2つ以上の変数をダミー化するならc()
でまとめる。続いて、ignore_na = TRUE
を指定する。これを指定しない場合、「欠損か否か」のダミー変数まで作成される。つづいて、元の変数(Gender
とVotedParty
)を除外する。
df3 <- df3 %>%
dummy_cols(c("Gender", "VotedParty"), ignore_na = TRUE) %>%
select(-c(Gender, VotedParty))
df3
# A tibble: 3,000 × 15
ID Age Education Voted T_Jimin T_Minshin Gende…¹ Gende…² Voted…³ Voted…⁴
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <int> <int> <int> <int>
1 1 69 4 1 50 30 0 1 0 0
2 2 47 3 0 10 50 0 1 NA NA
3 3 37 2 1 75 0 0 1 1 0
4 4 51 4 1 100 50 1 0 1 0
5 5 38 4 0 70 30 1 0 NA NA
6 6 71 2 1 100 0 1 0 1 0
7 7 47 3 1 50 10 1 0 0 0
8 8 71 2 1 90 0 1 0 1 0
9 9 75 4 1 100 50 1 0 1 0
10 10 66 3 1 50 55 0 1 0 1
# … with 2,990 more rows, 5 more variables: VotedParty_Komei <int>,
# VotedParty_Ishin <int>, VotedParty_Kyosan <int>, VotedParty_Etc <int>,
# VotedParty_DK <int>, and abbreviated variable names ¹Gender_Male,
# ²Gender_Female, ³VotedParty_Jimin, ⁴VotedParty_Minshin
これでダミー化は完了だ。ここで更に変数名を変更し、位置を調整してみよう。たとえば、Gender_Male
はMale
に、Gender_Female
はFemale
に変更し、ID
列の後ろへ移動させるとしよう。この場合、relocate()
関数を使用する。列名を変更する場合は新しい変数名 = 既存の変数名
と指定し、.after
、あるいは.before
で位置を指定する。
# A tibble: 3,000 × 15
ID Male Female Age Education Voted T_Jimin T_Minshin VotedPar…¹ Voted…²
<dbl> <int> <int> <dbl> <dbl> <dbl> <dbl> <dbl> <int> <int>
1 1 0 1 69 4 1 50 30 0 0
2 2 0 1 47 3 0 10 50 NA NA
3 3 0 1 37 2 1 75 0 1 0
4 4 1 0 51 4 1 100 50 1 0
5 5 1 0 38 4 0 70 30 NA NA
6 6 1 0 71 2 1 100 0 1 0
7 7 1 0 47 3 1 50 10 0 0
8 8 1 0 71 2 1 90 0 1 0
9 9 1 0 75 4 1 100 50 1 0
10 10 0 1 66 3 1 50 55 0 1
# … with 2,990 more rows, 5 more variables: VotedParty_Komei <int>,
# VotedParty_Ishin <int>, VotedParty_Kyosan <int>, VotedParty_Etc <int>,
# VotedParty_DK <int>, and abbreviated variable names ¹VotedParty_Jimin,
# ²VotedParty_Minshin
続いて、VotedParty_Jimin
からVotedParty_DK
までの列をVoted
列の後ろへ動かしてみよう。変数選択の場合、:
演算子を使うと「〜から〜まで」の指定ができる。
# A tibble: 3,000 × 15
ID Male Female Age Education Voted VotedParty…¹ Voted…² Voted…³ Voted…⁴
<dbl> <int> <int> <dbl> <dbl> <dbl> <int> <int> <int> <int>
1 1 0 1 69 4 1 0 0 0 0
2 2 0 1 47 3 0 NA NA NA NA
3 3 0 1 37 2 1 1 0 0 0
4 4 1 0 51 4 1 1 0 0 0
5 5 1 0 38 4 0 NA NA NA NA
6 6 1 0 71 2 1 1 0 0 0
7 7 1 0 47 3 1 0 0 0 0
8 8 1 0 71 2 1 1 0 0 0
9 9 1 0 75 4 1 1 0 0 0
10 10 0 1 66 3 1 0 1 0 0
# … with 2,990 more rows, 5 more variables: VotedParty_Kyosan <int>,
# VotedParty_Etc <int>, VotedParty_DK <int>, T_Jimin <dbl>, T_Minshin <dbl>,
# and abbreviated variable names ¹VotedParty_Jimin, ²VotedParty_Minshin,
# ³VotedParty_Komei, ⁴VotedParty_Ishin
むろん、:
ではなく、starts_with()
関数で変数選択もできる。いずれも"VotedParty_"
で始まる変数名なので、starts_with("VotedParty_")
と書けば、VotedParty_
で始まる全変数が選択される。
{summarytools}の利用
記述統計量は実証分析の論文において必須であり、多くの場合、最初の表として登場する。人によっては記述統計量の表をTable Oneとも呼ぶのもこれが理由である。記述統計量を示すことが重要だというのは、表作成の需要が高いことを意味し、高い需要はかならず供給を生み出す。Rにおいても簡単に記述統計量をまとめてくれるパッケージが多数あり、ここでは{summarytools}パッケージをを紹介する。
{summarytools}には記述統計量をまとめてくれる関数が複数あるが、ここではdescr()
関数を使用する。使い方は非常に単純で、()
内にデータのオブジェクト名を入力するだけだ。むろん、パイプ演算子(%>%
または|>
)も使える。パイプ演算子は今後毎回登場するので、忘れた人はミクロ政治データ分析実習の第9回講義資料、または『私たちのR』の第12章を参照すること。。
Descriptive Statistics
df
N: 3000
Age Education Gender ID T_Jimin T_Minshin Voted VotedParty
----------------- --------- ----------- --------- --------- --------- ----------- --------- ------------
Mean 47.34 3.11 1.50 1500.50 41.13 34.25 0.74 2.94
Std.Dev 15.63 0.89 0.50 866.17 28.02 25.95 0.44 2.21
Min 18.00 1.00 1.00 1.00 0.00 0.00 0.00 1.00
Q1 34.00 2.00 1.00 750.50 20.00 10.00 0.00 1.00
Median 47.00 3.00 2.00 1500.50 50.00 40.00 1.00 2.00
Q3 61.00 4.00 2.00 2250.50 60.00 50.00 1.00 5.00
Max 75.00 4.00 2.00 3000.00 100.00 100.00 1.00 7.00
MAD 19.27 1.48 0.00 1111.95 29.65 29.65 0.00 1.48
IQR 27.00 2.00 1.00 1499.50 40.00 40.00 1.00 4.00
CV 0.33 0.29 0.33 0.58 0.68 0.76 0.60 0.75
Skewness -0.03 -0.38 -0.01 0.00 0.02 0.16 -1.07 0.82
SE.Skewness 0.04 0.04 0.04 0.04 0.04 0.04 0.04 0.05
Kurtosis -1.14 -1.28 -2.00 -1.20 -0.83 -0.81 -0.85 -0.82
N.Valid 3000.00 3000.00 3000.00 3000.00 3000.00 3000.00 3000.00 2208.00
Pct.Valid 100.00 100.00 100.00 100.00 100.00 100.00 100.00 73.60
よく使う平均値(Mean)、標準偏差(Std.Dev)など以外にも第一四分位数(Q1)や四分位範囲(IQR)、歪度(Skewness)などまで出力される。実際はこれら全てを掲載するケースはあまりない。ここでは平均値("mean"
)、標準偏差("sd"
)、最小値("min"
)、最大値("max"
)、有効ケース数("n.vailid"
)のみに絞ってみよう。出力する記述統計量はstats
引数で指定できる。
Descriptive Statistics
df
N: 3000
Age Education Gender ID T_Jimin T_Minshin Voted VotedParty
------------- --------- ----------- --------- --------- --------- ----------- --------- ------------
Mean 47.34 3.11 1.50 1500.50 41.13 34.25 0.74 2.94
Std.Dev 15.63 0.89 0.50 866.17 28.02 25.95 0.44 2.21
Min 18.00 1.00 1.00 1.00 0.00 0.00 0.00 1.00
Max 75.00 4.00 2.00 3000.00 100.00 100.00 1.00 7.00
N.Valid 3000.00 3000.00 3000.00 3000.00 3000.00 3000.00 3000.00 2208.00
ただし、まだ気になる点がある。それは行と列が普段見る記述統計量の表と逆だということだ。これはtranspose = TRUE
を追加することで対応できる。また、変数の順番もdf
内の順番でなく、勝手にアルファベット順になっている。これをdf
内の順番にするためにはsort = "p"
を追加すれば良い。
Descriptive Statistics
df
N: 3000
Mean Std.Dev Min Max N.Valid
---------------- --------- --------- ------- --------- ---------
ID 1500.50 866.17 1.00 3000.00 3000.00
Gender 1.50 0.50 1.00 2.00 3000.00
Age 47.34 15.63 18.00 75.00 3000.00
Education 3.11 0.89 1.00 4.00 3000.00
Voted 0.74 0.44 0.00 1.00 3000.00
VotedParty 2.94 2.21 1.00 7.00 2208.00
T_Jimin 41.13 28.02 0.00 100.00 3000.00
T_Minshin 34.25 25.95 0.00 100.00 3000.00
最後にID
行の記述統計量を削除してみよう。これは回答者の識別番号であって、その平均値や標準偏差はどうでもいい。そのためにはdf
をdescr()
を渡す前にselect()
関数を使ってID
列を除外してから渡せば良いだろう。Gender
とVotedParty
もまた名目変数であるが、ここではとりあえず放置しておく。
df %>%
select(-ID) %>%
descr(stats = c("mean", "sd", "min", "max", "n.valid"),
transpose = TRUE, order = "p")
Descriptive Statistics
df
N: 3000
Mean Std.Dev Min Max N.Valid
---------------- ------- --------- ------- -------- ---------
Gender 1.50 0.50 1.00 2.00 3000.00
Age 47.34 15.63 18.00 75.00 3000.00
Education 3.11 0.89 1.00 4.00 3000.00
Voted 0.74 0.44 0.00 1.00 3000.00
VotedParty 2.94 2.21 1.00 7.00 2208.00
T_Jimin 41.13 28.02 0.00 100.00 3000.00
T_Minshin 34.25 25.95 0.00 100.00 3000.00
それでは名目変数を含めた記述統計表を作成してみよう。df
ダミー化を済ませてからdescr()
に渡せば良い。記述統計表はdesc_stat
という名のオブジェクトとして作業環境内に格納する。
desc_stat <- df %>%
mutate(Gender = factor(Gender, levels = c(1, 2),
labels = c("Male", "Female")),
VotedParty = factor(VotedParty, levels = 1:7,
labels = c("Jimin", "Minshin", "Komei", "Ishin",
"Kyosan", "Etc", "DK"))) %>%
dummy_cols(c("Gender", "VotedParty"), ignore_na = TRUE,
# 以下の引数を追加すると元の変数が自動的に削除される
remove_selected_columns = TRUE) %>%
relocate(Male = Gender_Male,
Female = Gender_Female,
.after = ID) %>%
relocate(starts_with("VotedParty"), .after = Voted) %>%
select(-ID) %>%
descr(stats = c("mean", "sd", "min", "max", "n.valid"),
transpose = TRUE, order = "p")
desc_stat
Descriptive Statistics
df
N: 3000
Mean Std.Dev Min Max N.Valid
------------------------ ------- --------- ------- -------- ---------
Male 0.50 0.50 0.00 1.00 3000.00
Female 0.50 0.50 0.00 1.00 3000.00
Age 47.34 15.63 18.00 75.00 3000.00
Education 3.11 0.89 1.00 4.00 3000.00
Voted 0.74 0.44 0.00 1.00 3000.00
VotedParty_Jimin 0.40 0.49 0.00 1.00 2208.00
VotedParty_Minshin 0.20 0.40 0.00 1.00 2208.00
VotedParty_Komei 0.05 0.22 0.00 1.00 2208.00
VotedParty_Ishin 0.10 0.30 0.00 1.00 2208.00
VotedParty_Kyosan 0.08 0.27 0.00 1.00 2208.00
VotedParty_Etc 0.01 0.10 0.00 1.00 2208.00
VotedParty_DK 0.16 0.37 0.00 1.00 2208.00
T_Jimin 41.13 28.02 0.00 100.00 3000.00
T_Minshin 34.25 25.95 0.00 100.00 3000.00
{gt}パッケージを使えば、よりまとまった表として出力できる。興味のある履修者はやってみよう。
library(gt) # or pacman::p_load(gt)
gt(desc_stat,
rownames_to_stub = TRUE) %>% # 行の名前(変数の名前)を1列目に出力
fmt_number(columns = 2:3, decimals = 3) # 2列、3列の値は小数点3桁まで
Mean | Std.Dev | Min | Max | N.Valid | |
---|---|---|---|---|---|
Male | 0.497 | 0.500 | 0 | 1 | 3000 |
Female | 0.503 | 0.500 | 0 | 1 | 3000 |
Age | 47.340 | 15.628 | 18 | 75 | 3000 |
Education | 3.114 | 0.892 | 1 | 4 | 3000 |
Voted | 0.736 | 0.441 | 0 | 1 | 3000 |
VotedParty_Jimin | 0.399 | 0.490 | 0 | 1 | 2208 |
VotedParty_Minshin | 0.199 | 0.399 | 0 | 1 | 2208 |
VotedParty_Komei | 0.051 | 0.220 | 0 | 1 | 2208 |
VotedParty_Ishin | 0.100 | 0.300 | 0 | 1 | 2208 |
VotedParty_Kyosan | 0.078 | 0.269 | 0 | 1 | 2208 |
VotedParty_Etc | 0.011 | 0.104 | 0 | 1 | 2208 |
VotedParty_DK | 0.163 | 0.369 | 0 | 1 | 2208 |
T_Jimin | 41.130 | 28.015 | 0 | 100 | 3000 |
T_Minshin | 34.248 | 25.947 | 0 | 100 | 3000 |