第4回講義資料

記述統計

スライド

新しいタブで開く

セットアップ

 まず、本日の実習で使用するパッケージを読み込む。

library(tidyverse)
library(fastDummies)
library(summarytools)

 当該パッケージがインストールされていない場合、以下のようなメッセージが出力される。

Error in library(パッケージ名) : there is no package called ‘パッケージ名’

 この場合、install.packages("パッケージ名")でパッケージをインストールしてから読み込もう。

 ただし、当該パッケージがインストールされているかが分からない場合もあろう。あるいは、インストールされているにも関わらず、再インストールしてしまう可能性もある。パッケージによってはインストールに数分かかる場合もあるのでこれは非常に非効率的である。ここで便利なものが{pacman}パッケージだ。{pacman}パッケージがインストールされている場合、p_load()関数でパッケージを読み込むことができる。p_load()関数は{pacman}パッケージが提供する関数であるため、予めlibrary(pacman)で{pacman}パッケージを読み込む必要があるが、パッケージ名::関数名()でパッケージを読み込まずに特定パッケージ内の関数を呼び出すこともできる。

# {pacman}パッケージがインストールされていない場合、
# install.packages("pacman") でインストールしておく。
pacman::p_load(tidyverse, fastDummies, summartools)

 一つの関数内に複数のパッケージが同時に読み込めるといったメリットも大きいが、{pacman}最大の特徴は「インストールされていない場合、インストールしてから読み込む」ことだ。一旦、{pacman}をインストールしておけば大変便利になる。

 続いてデータを読み込もう。実習に使用するデータはdescstat_data.csvであり、LMSから入手可能だ。.csv形式データを読み込む関数はread_csv()であり、()内にはパスを含むファイル名を入力する。パス+ファイル名は必ず"で囲むこと。たとえば、プロジェクト・フォルダー内のDataフォルダー内のdescstat_data.csvファイルなら、"Data/descstat_data.csv"と入力する。また、read_csv()だけだとデータが読み込まれて出力されるだけで終わる。つまり、現在の作業環境内に残らない。作業環境にデータを格納するためには<-演算子を使用する。ここではデータを読み込み、raw_dfという名のオブジェクトとして作業環境内に格納しておこう。

 パス(path)とは何かについてよく分からない人は授業後でも良いので必ず本講義のためのファイル管理術」を精読すること。

raw_df <- read_csv("Data/descstat_data.csv")

 データの中身を見るためにはオブジェクト名のみ入力すれば良い。

raw_df
# 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()関数を使用する。

names(raw_df)
  [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()関数でも確認することができる。

dim(raw_df)
[1] 3000  272

 最後に出力される画面の行数についてだが、デフォルトでは10行出力となっている。もし、15行を出力したい場合はprint()関数を使用し、n引数で指定することができる。

print(raw_df, n = 15)
# 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』の第12131415章を参照されたい。ここではまず、記述統計を出したい変数のみを残し、抽出後のデータを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
df <- df %>%
  mutate(Voted = if_else(Voted == 1, 1, 0))

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     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)とはある変数が持つ情報を要約した数値である。例えば、dfAge列は回答者の年齢の変数である。この回答者たちの年齢について語る時、「このデータの回答者の年齢は69、47、37、51、…、18歳ですよ」という人はいないだろう。4-5人分のデータならまだしも、3000人の回答者ならあり得ない。我々は普段、「このデータの回答者の年齢はだいたいXX歳ですよ」とか、「真ん中の年齢はYY歳ですよ」と言うだろう。また、年齢の格差/ばらつきを語るときも標準偏差や範囲(「18歳から75歳までいますよ」など)を言うのが普通であろう。このように元の長い情報を一つの数値として要約したものが記述統計量である。

 Rには記述統計量を計算するいくつかの関数が用意されている。

  • mean(): 平均値
  • median(): 中央値
  • var(): 不偏分散
  • sd(): 不偏標準偏差
  • min()max(): 最小値と最大値

 たとえば、dfAge列(df$Age)の平均値は以下のように計算する。na.rm = TRUEは「もしdf$Ageに欠損値がある場合、それは除外して平均値を計算する」ことを意味する。

mean(df$Age, na.rm = TRUE)
[1] 47.34

 同じやり方で中央値(median())、最小値(min())、最大値(max())などが計算できる。しかし、本講義ではtidyverseパッケージ群を積極的に活用しているため、ここからは{dplyr}パッケージ(tidyverseを構成するパッケージの一つであり、{tidyverse}を読み込むと自動的に読み込まれる)のsummarise()関数を使用する。summarise()関数の詳細については、『私たちのR』の第13章を参照すること。ここではAge変数の平均値、中央値、標準偏差、最小値、最大値、有効ケース数を計算し、それぞれMeanMedianSDMinMaxNという名の列として出力してみよう。

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()関数で簡単に確認することができる。

table(df$Gender)

   1    2 
1492 1508 

 また、{dplyr}を使う場合、count()関数を使用すれば良い。

df %>%
  count(Gender)
# A tibble: 2 × 2
  Gender     n
   <dbl> <int>
1      1  1492
2      2  1508

 しかし、連続変数用の記述統計表と名目変数用の度数分布表を分けることは非効率的である。分析に用いられる名目変数が数が多いと尚更だ。できれば名目変数も連続変数と同じ表で記述統計量を出した方が良いだろう。そのためには名目変数をダミー変数として変換すれば、平均値や標準偏差などが計算できるようになる。

 ダミー変数は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

 あとはGenderVotedParty列は不要なので、こちらを除外する。

df2 <- df2 %>%
  select(-c(Gender, VotedParty))

df2
# 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}パッケージを使えばたった数行のコードでダミー化ができる。手順は以下の通りである。

  1. 名目変数をfactor型変数へ変換する。
  2. {fastDummies}パッケージのdummy_cols()関数でダミー化する。
  3. 生成された列を適宜修正する(変数名や位置など)。

 それではまず、dfGenderVotedParty列をfactor化してみよう。Genderの場合、値が1なら"Male"、2なら"Female"を付ける。VotedPartyは値が1なら"Jimin"、2なら"Minshin"、3なら"Komei"、4なら"Ishin"、5なら"Kyosan"、6なら"Etc"(その他の政党)、7なら"DK"(覚えていない/答えたくない)とする。修正後、dfdf3という名の新しいオブジェクトとして作業環境内に格納する。

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()関数でGenderVotedPartyをダミー変数に変換する。第一引数はダミー変数にしたい変数の名前を"で囲んだものを入れる。2つ以上の変数をダミー化するならc()でまとめる。続いて、ignore_na = TRUEを指定する。これを指定しない場合、「欠損か否か」のダミー変数まで作成される。つづいて、元の変数(GenderVotedParty)を除外する。

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_MaleMaleに、Gender_FemaleFemaleに変更し、ID列の後ろへ移動させるとしよう。この場合、relocate()関数を使用する。列名を変更する場合は新しい変数名 = 既存の変数名と指定し、.after、あるいは.beforeで位置を指定する。

df3 <- df3 %>%
  relocate(Male   = Gender_Male,
           Female = Gender_Female,
           .after = ID)

df3
# 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列の後ろへ動かしてみよう。変数選択の場合、:演算子を使うと「〜から〜まで」の指定ができる。

df3 <- df3 %>%
  relocate(VotedParty_Jimin:VotedParty_DK, .after = Voted)

df3
# 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_で始まる全変数が選択される。

df3 %>%
  relocate(starts_with("VotedParty"), .after = Voted)

{summarytools}の利用

 記述統計量は実証分析の論文において必須であり、多くの場合、最初の表として登場する。人によっては記述統計量の表をTable Oneとも呼ぶのもこれが理由である。記述統計量を示すことが重要だというのは、表作成の需要が高いことを意味し、高い需要はかならず供給を生み出す。Rにおいても簡単に記述統計量をまとめてくれるパッケージが多数あり、ここでは{summarytools}パッケージをを紹介する。

 {summarytools}には記述統計量をまとめてくれる関数が複数あるが、ここではdescr()関数を使用する。使い方は非常に単純で、()内にデータのオブジェクト名を入力するだけだ。むろん、パイプ演算子(%>%または|>)も使える。パイプ演算子は今後毎回登場するので、忘れた人はミクロ政治データ分析実習の第9回講義資料、または『私たちのR』の第12章を参照すること。。

df %>%
  descr()
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引数で指定できる。

df %>%
  descr(stats = c("mean", "sd", "min", "max", "n.valid"))
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"を追加すれば良い。

df %>%
  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
---------------- --------- --------- ------- --------- ---------
              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行の記述統計量を削除してみよう。これは回答者の識別番号であって、その平均値や標準偏差はどうでもいい。そのためにはdfdescr()を渡す前にselect()関数を使ってID列を除外してから渡せば良いだろう。GenderVotedPartyもまた名目変数であるが、ここではとりあえず放置しておく。

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