一つのカテゴリカル変数の度数分布表

 調査結果の報告においては,高度な分析をするだけではなく,収集した情報の基本的な集計結果を示す事も重要になる。しかしRでは,度数分布表(単純集計表などとも呼ばれる)や分割表(連関表,クロス表)について,必要最低限の結果を出力するコマンドが基本で,色々な情報を纏めて提示する為には自分で少し手を加える必要がある。
 以下では,学部学生の演習レヴェルであると便利だと思われる作表方法を紹介する。

模擬データの作成

 自分で分析できる調査データを持たない学習者も多いだろうから,あたかも社会調査によって得たかの様な模擬データをRで簡単に作成する方法から紹介しよう。ここでの目的から,二つのカテゴリカル変数を生成する事にする。まずは以下のコマンドで一つのカテゴリカル変数模擬データを生成してみる。

q1 <- sample(c(1, 2, 3, NA), size=100, replace=T, prob=c(.34, .40, .23, .03))

 sample( )関数は,無作為抽出(確率抽出)する為の関数で,抽出元となるヴェクトル,抽出回数size,復元抽出か非復元抽出かreplace,抽出する時の確率probを指定する事が出来る。上の例では,c(1, 2, 3, NA)から100回復元抽出を,それぞれの値が抽出される確率を.34,.40,.23,.03として行え,と云う意味になっている。sizeに与える数字は先に変数として値を与えておく事も出来る。社会調査データらしくする為に,わざわざ欠損値NAも多少発生する様にしている。
 もしデータ入力において欠損値が88や99の値でq1に入力されている場合は,後で欠損値をNAに置き換える必要がある。
   以下は,二つの変数(5件法と4件法,無回答の99混じり)を発生させて,それを(敢えて)データ・フレイムにしている。何故敢えてデータ・フレイムにしているかと言えば,通常社会調査データはcsvファイルでデータを作成し,それをデータ・フレイムとしてRに読み込んで分析するので,それに近い状態を再現する為である。  

n <- 125
q1 <- sample(c(1, 2, 3, 4, 5, 99), size=n, replace=T, prob=c(.25, .15, .20, .20, .15, .05))
q2 <- sample(c(1, 2, 3, 4, 99),    size=n, replace=T, prob=c(.30, .20, .20, .25, .05))
d01 <- data.frame(q1, q2)

それぞれの変数にアクセスする為には,d01$q1,d01$q2とする事になる。

欠損値の処理

 分析に使用する変数については,まず最初に度数分布を確認するのが良い。
 一変数の度数分布表を作成するコマンド(関数)は,table( )である。この関数の引数に変数を渡すと,NAを除いた集計結果を出力する。NAも集計結果に表示させる為には,useNA=“ifany” または useNA=“always” と云うオプションを付ける。
 ここではq1とq2の度数分布を纏めて確認してみる。最初に分布を確認する際には,useNA=“always” とする事を推奨する。
 また,table( ) 関数を使用する時は,with( ) 関数を併用すると便利である。

# with( )関数無し
table(d01$q1, d01$q2, useNA = "always")
      
        1  2  3  4 99 <NA>
  1    10  9  4  6  4    0
  2     9  2  6  2  2    0
  3     8  4  4  3  1    0
  4     7  4  6  4  1    0
  5     9  2  2  7  1    0
  99    5  1  1  1  0    0
  <NA>  0  0  0  0  0    0
# with( )関数有り
with(d01, table(q1, q2, useNA = "always"))
      q2
q1      1  2  3  4 99 <NA>
  1    10  9  4  6  4    0
  2     9  2  6  2  2    0
  3     8  4  4  3  1    0
  4     7  4  6  4  1    0
  5     9  2  2  7  1    0
  99    5  1  1  1  0    0
  <NA>  0  0  0  0  0    0

ここで,99と云う無効回答コードが見つかるので,これをNAにして後の分析から自動的に除外される様にする(欠損値処理)。
変換した結果は必ず新変数として保存する事を推奨する。Rは大文字と小文字を別のものとして扱うのでそれを利用している。
社会調査データでよくある,「得点(値)を反転させる」と云う変換についても例示しておく(q2 → R2)。

d01$Q1 <- c(1:5)[d01$q1]
d01$Q2 <- c(1:4)[d01$q1]
d01$R2 <- c(4:1)[d01$q1]

この変換法は工夫次第でかなり汎用性が高い。

一つのカテゴリカル変数の度数分布表の作成

 集計結果自体をオブジェクトに格納(保存)する事が出来る。オブジェクトに格納しておくと,一度表示して終わりではなく,その後幾らでも再利用出来るので非常に便利である。なるべく集計結果や分析結果をオブジェクト保存する習慣を付けよう。

table(d01$Q1)

 1  2  3  4  5 
33 21 20 22 21 
table(d01$Q1, useNA="ifany")

   1    2    3    4    5 <NA> 
  33   21   20   22   21    8 
t01 <- table(d01$Q1); t01

 1  2  3  4  5 
33 21 20 22 21 

 しかしこれでは度数だけである。度数分布表(単純集計表)は通常,累積度数や相対度数(%)なども纏めて表示される。欠損値の有無別に相対度数を表示する事も多い。それらを付加した表を作成する事を目指す。
 ヴェクトルに対して,累積和を求める関数が cumsum( ) である。また,ヴェクトルに対して割合(比率)を求める関数が prop.table( ) である。基本の度数分布表freqを作成した後,累積度数のヴェクトル,比率のヴェクトルを作成する例を示す。それぞれcumfreq,percentと云う名前を付けてオブジェクトとして格納し,最後にその結果を表示させている。
 

freq <- table(d01$Q1)
cumfreq <- cumsum(freq)
percent <- prop.table(freq)
freq

 1  2  3  4  5 
33 21 20 22 21 
cumfreq
  1   2   3   4   5 
 33  54  74  96 117 
percent

        1         2         3         4         5 
0.2820513 0.1794872 0.1709402 0.1880342 0.1794872 

相対度数のヴェクトルpercentに関数 cumsum( ) を適用すると,累積相対度数のヴェクトルを作成出来る。

cum.pcnt <- cumsum(percent)

 次の様に,列columnを結合bindする関数 cbind( ) を使うと,これらの結果を一纏めに表示出来る。これもオブジェクトに格納したいところだが,後でもう少し手を加えるのでここでは表示だけで済ませる。

cbind(freq, cumfreq, percent, cum.pcnt)
  freq cumfreq   percent  cum.pcnt
1   33      33 0.2820513 0.2820513
2   21      54 0.1794872 0.4615385
3   20      74 0.1709402 0.6324786
4   22      96 0.1880342 0.8205128
5   21     117 0.1794872 1.0000000

 同じ事を,欠損値を含んだ度数分布表についても行う。

freqT <- table(d01$Q1, useNA="always")
cumfreqT <- cumsum(freqT)
percentT <- prop.table(freqT)
cum.pcntT <- cumsum(percentT)

cbind(freqT, cumfreqT, percentT, cum.pcntT)
     freqT cumfreqT percentT cum.pcntT
1       33       33    0.264     0.264
2       21       54    0.168     0.432
3       20       74    0.160     0.592
4       22       96    0.176     0.768
5       21      117    0.168     0.936
<NA>     8      125    0.064     1.000

 最後に,以上の結果から,必要なものだけを纏めてラベルも付けて一つの表にしよう。
NAを含む度数分布表と含まない度数分布表では行の数(ヴェクトルの長さ)が1つ異なるので,最初にそれを調整している。

percent <- c(percent, NA); cum.pcnt <- c(cum.pcnt, NA)

freq.table <- cbind("度数"=freqT, "累積度数"=cumfreqT, "相対度数"=percentT, "累積相対度数"=cum.pcntT, "有効相対度数"=percent, "有効累積相対度数"=cum.pcnt)
freq.table
     度数 累積度数 相対度数 累積相対度数 有効相対度数 有効累積相対度数
1      33       33    0.264        0.264    0.2820513        0.2820513
2      21       54    0.168        0.432    0.1794872        0.4615385
3      20       74    0.160        0.592    0.1709402        0.6324786
4      22       96    0.176        0.768    0.1880342        0.8205128
5      21      117    0.168        0.936    0.1794872        1.0000000
<NA>    8      125    0.064        1.000           NA               NA

 以上から必要な部分だけを抜き出すと以下の通りである。これを,度数分布表を作成したい変数ごとに使いまわせば良い。最初の二行の d01$Q1 の部分だけを書き換えれば良い。

freq <- table(d01$Q1)
freqT <- table(d01$Q1, useNA="always")

percent <- prop.table(freq)
cum.pcnt <- cumsum(percent)
percent <- c(percent, NA); cum.pcnt <- c(cum.pcnt, NA)
cumfreqT <- cumsum(freqT)
percentT <- prop.table(freqT)
cum.pcntT <- cumsum(percentT)

freq.table <- cbind("度数"=freqT, "累積度数"=cumfreqT, "相対度数"=percentT, "累積相対度数"=cum.pcntT, "有効相対度数"=percent, "有効累積相対度数"=cum.pcnt)
freq.table
     度数 累積度数 相対度数 累積相対度数 有効相対度数 有効累積相対度数
1      33       33    0.264        0.264    0.2820513        0.2820513
2      21       54    0.168        0.432    0.1794872        0.4615385
3      20       74    0.160        0.592    0.1709402        0.6324786
4      22       96    0.176        0.768    0.1880342        0.8205128
5      21      117    0.168        0.936    0.1794872        1.0000000
<NA>    8      125    0.064        1.000           NA               NA

 しかしいちいちこれを全て変数ごとにコピー&ペーストして使用するのは手間がかかると云う場合には,「Rでは自分で新しい関数を自由に定義出来る」と云う極めて便利な機能を利用すると良い。自作関数の定義は,初心者が多用すると却って混乱する懸念もあるが,こうした長いスクリプトを繰り返し利用する事が分かっている場合は使ってみても良いだろう。
 以下では,freq.table( ) と云う関数名で定義している。

freq.table <- function (x) {
  freq <- table(x)
  freqT <- table(x, useNA="always")

  percent <- prop.table(freq)
  cum.pcnt <- cumsum(percent)
  percent <- c(percent, NA); cum.pcnt <- c(cum.pcnt, NA)
  cumfreqT <- cumsum(freqT)
  percentT <- prop.table(freqT)
  cum.pcntT <- cumsum(percentT)

  output <- cbind("度数"=freqT, "累積度数"=cumfreqT, "相対度数"=percentT, "累積相対度数"=cum.pcntT, "有効相対度数"=percent, "有効累積相対度数"=cum.pcnt)
  return(output)
}

 こうして新関数として定義した後で,その関数に Q1 や Q2 を引数として与えると以下の様になる。

freq.table(d01$Q1)
     度数 累積度数 相対度数 累積相対度数 有効相対度数 有効累積相対度数
1      33       33    0.264        0.264    0.2820513        0.2820513
2      21       54    0.168        0.432    0.1794872        0.4615385
3      20       74    0.160        0.592    0.1709402        0.6324786
4      22       96    0.176        0.768    0.1880342        0.8205128
5      21      117    0.168        0.936    0.1794872        1.0000000
<NA>    8      125    0.064        1.000           NA               NA
freq.table(d01$Q2)
     度数 累積度数 相対度数 累積相対度数 有効相対度数 有効累積相対度数
1      33       33    0.264        0.264    0.3437500        0.3437500
2      21       54    0.168        0.432    0.2187500        0.5625000
3      20       74    0.160        0.592    0.2083333        0.7708333
4      22       96    0.176        0.768    0.2291667        1.0000000
<NA>   29      125    0.232        1.000           NA               NA

データフレイム中の全変数の度数分布表

実査を行ったら最初に,全ての変数の度数分布表を出力する事が多い。
ここではそれを自動でやってくれるスクリプトを提供しておく。
序に,相対度数を100倍して%表記にし,小数第一位までとする。

# 関数の定義
freq.table <- function (x) {
  freq <- table(x)
  freqT <- table(x, useNA="always")

  percent <- prop.table(freq)
  cum.pcnt <- cumsum(percent)
  percent <- c(percent, NA); cum.pcnt <- c(cum.pcnt, NA)
  cumfreqT <- cumsum(freqT)
  percentT <- prop.table(freqT)
  cum.pcntT <- cumsum(percentT)

  output <- cbind("度数"=freqT, "累積度数"=cumfreqT, "%"=round(percentT*100, 1),
                  "累積%"=round(cum.pcntT*100, 1), "有効%"=round(percent*100, 1),
                  "有効累積%"=round(cum.pcnt*100, 1))
  return(output)
}
# データフレイム中の全変数に対して実行

D00 <- d01 # データフレイムを複写する
names(D00); ncol(D00) # これは単なる確認の為で不要。
[1] "q1" "q2" "Q1" "Q2" "R2"
[1] 5
for (i in c(1:ncol(D00))) {
    print(paste("変数名", names(D00)[i], "の度数分布表"), quote=F)
    print(freq.table(D00[, i]))
    cat("\n")
}
[1] 変数名 q1 の度数分布表
     度数 累積度数   % 累積% 有効% 有効累積%
1      33       33 26.4   26.4   26.4       26.4
2      21       54 16.8   43.2   16.8       43.2
3      20       74 16.0   59.2   16.0       59.2
4      22       96 17.6   76.8   17.6       76.8
5      21      117 16.8   93.6   16.8       93.6
99      8      125  6.4  100.0    6.4      100.0
<NA>    0      125  0.0  100.0     NA         NA

[1] 変数名 q2 の度数分布表
     度数 累積度数   % 累積% 有効% 有効累積%
1      48       48 38.4   38.4   38.4       38.4
2      22       70 17.6   56.0   17.6       56.0
3      23       93 18.4   74.4   18.4       74.4
4      23      116 18.4   92.8   18.4       92.8
99      9      125  7.2  100.0    7.2      100.0
<NA>    0      125  0.0  100.0     NA         NA

[1] 変数名 Q1 の度数分布表
     度数 累積度数   % 累積% 有効% 有効累積%
1      33       33 26.4   26.4   28.2       28.2
2      21       54 16.8   43.2   17.9       46.2
3      20       74 16.0   59.2   17.1       63.2
4      22       96 17.6   76.8   18.8       82.1
5      21      117 16.8   93.6   17.9      100.0
<NA>    8      125  6.4  100.0     NA         NA

[1] 変数名 Q2 の度数分布表
     度数 累積度数   % 累積% 有効% 有効累積%
1      33       33 26.4   26.4   34.4       34.4
2      21       54 16.8   43.2   21.9       56.2
3      20       74 16.0   59.2   20.8       77.1
4      22       96 17.6   76.8   22.9      100.0
<NA>   29      125 23.2  100.0     NA         NA

[1] 変数名 R2 の度数分布表
     度数 累積度数   % 累積% 有効% 有効累積%
1      22       22 17.6   17.6   22.9       22.9
2      20       42 16.0   33.6   20.8       43.8
3      21       63 16.8   50.4   21.9       65.6
4      33       96 26.4   76.8   34.4      100.0
<NA>   29      125 23.2  100.0     NA         NA