Rでクラスごとの記述統計を効率的に算出するお話

山田(2015)の第1章、第2章を読んでいたらクラスごとの記述統計を効率的に求める関数を見つけたので備忘録としてメモ

例えば、以下のような、クラスごと(5クラス)に集計したデータがあるとする。

##    class sex score
## 1      1   1   310
## 2      1   1   335
## 3      1   1   355
## 4      1   1   350
## 5      1   1   490
## 6      1   1   350
## 7      1   2   365
## 8      1   1   210
## 9      1   2   380
## 10     1   1   425
## 11     2   1   335
## 12     2   2   355
## 13     2   2   545
## 14     2   1   415
## 15     2   1   275
## 16     2   2   425
## 17     2   1   290
## 18     2   2   355
## 19     2   2   520
## 20     2   1   755
## 21     3   1   345
## 22     3   1   565
## 23     3   1   285
## 24     3   1   240
## 25     3   2   395
## 26     3   1   470
## 27     3   1   310
## 28     3   2   405
## 29     3   1   315
## 30     3   1   260
## 31     4   2   360
## 32     4   1   230
## 33     4   2   275
## 34     4   1   410
## 35     4   2   480
## 36     4   2   310
## 37     4   1   340
## 38     4   2   210
## 39     4   1   505
## 40     4   2   375
## 41     5   2   245
## 42     5   1   215
## 43     5   1   345
## 44     5   1   280
## 45     5   2   300
## 46     5   1   300
## 47     5   2   380
## 48     5   1   275
## 49     5   1   340
## 50     5   2   230

このデータから、全体の平均値、標準偏差、最高点、最低点およびクラスごとの平均値、標準偏差、最高点、最低点を導き出したいとする。

Rにおいて上記のデータを導き出したい場合は、

mean() 
sd()
max()
min()

を使うことが考えられるがかなり面倒そう。そこで、以下の2つの解決策を考える。

解決策1:psychパッケージのdescribeBy()を使う。

describeBy()は

describeBy(処理したいデータ,属性)

と入力し、属性ごとの記述統計を算出することができる。例えば、上記データのclassごとにscoreの記述統計量を算出したい場合、以下のように入力する。

library(psych) #psychパッケージの読み込み
describeBy(dat$score,dat$class) #処理したいデータ=datのscore, 属性=datのclass
##  Descriptive statistics by group 
## group: 1
##    vars  n mean   sd median trimmed   mad min max range  skew kurtosis
## X1    1 10  357 72.5  352.5  358.75 33.36 210 490   280 -0.16    -0.08
##       se
## X1 22.93
## -------------------------------------------------------- 
## group: 2
##    vars  n mean     sd median trimmed    mad min max range skew kurtosis
## X1    1 10  427 145.68    385     405 107.49 275 755   480 0.97    -0.15
##       se
## X1 46.07
## -------------------------------------------------------- 
## group: 3
##    vars  n mean     sd median trimmed    mad min max range skew kurtosis
## X1    1 10  359 101.18    330  348.12 100.08 240 565   325 0.67    -0.81
##    se
## X1 32
## -------------------------------------------------------- 
## group: 4
##    vars  n  mean    sd median trimmed    mad min max range skew kurtosis
## X1    1 10 349.5 98.08    350   347.5 100.08 210 505   295 0.14    -1.37
##       se
## X1 31.01
## -------------------------------------------------------- 
## group: 5
##    vars  n mean    sd median trimmed   mad min max range skew kurtosis
## X1    1 10  291 53.11    290  289.38 70.42 215 380   165 0.14    -1.38
##      se
## X1 16.8

これで、各グループ(class 1からclass 5)の記述統計量が一発で算出された。超便利。ちなみに、n=データ数、mean=平均値、sd=標準偏差、median=中央値、min=最小値、max=最大値、skew=歪度、kurtosis=尖度、se=標準誤差

解決策2:tapply()を使う

tapply()は

tapply(処理したいデータ,属性,統計量)

とすることで、グループごとに算出したい統計量を一括で導き出すことができる。例えば、先程のデータでクラスごとの平均値を処理したい場合、以下のように入力する。

tapply(dat$score,dat$class,mean) #処理したいデータ=datのscore, 属性=datのclass,統計量=平均値
##     1     2     3     4     5 
## 357.0 427.0 359.0 349.5 291.0

上記の結果の1,2,3,4,5はそれぞれクラス1,クラス2…を指す。つまり、クラス1の平均値は357点、クラス2の平均値は427点…ということがこの関数一つで算出された。超便利。

tapply()で扱う統計量は平均値以外でも使うことができる。標準偏差や最小値、最大値も以下の通り。

tapply(dat$score,dat$class,sd) #グループごとにSDを算出
##         1         2         3         4         5 
##  72.50287 145.68230 101.18190  98.07735  53.11413
tapply(dat$score,dat$class,min) #グループごとに最小値を算出
##   1   2   3   4   5 
## 210 275 240 210 215
tapply(dat$score,dat$class,max) #グループごとに最大値を算出
##   1   2   3   4   5 
## 490 755 565 505 380

また、先程のpsychパッケージのdescribe()と組み合わせることもできる。

tapply(dat$score, dat$class, describe)
## $`1`
##    vars  n mean   sd median trimmed   mad min max range  skew kurtosis
## X1    1 10  357 72.5  352.5  358.75 33.36 210 490   280 -0.16    -0.08
##       se
## X1 22.93
## 
## $`2`
##    vars  n mean     sd median trimmed    mad min max range skew kurtosis
## X1    1 10  427 145.68    385     405 107.49 275 755   480 0.97    -0.15
##       se
## X1 46.07
## 
## $`3`
##    vars  n mean     sd median trimmed    mad min max range skew kurtosis
## X1    1 10  359 101.18    330  348.12 100.08 240 565   325 0.67    -0.81
##    se
## X1 32
## 
## $`4`
##    vars  n  mean    sd median trimmed    mad min max range skew kurtosis
## X1    1 10 349.5 98.08    350   347.5 100.08 210 505   295 0.14    -1.37
##       se
## X1 31.01
## 
## $`5`
##    vars  n mean    sd median trimmed   mad min max range skew kurtosis
## X1    1 10  291 53.11    290  289.38 70.42 215 380   165 0.14    -1.38
##      se
## X1 16.8

これで解決策1のdescribeBy()と同様、各クラスごとのデータ数、平均値、SD、最小値、最大値が一発で導き出すことができた。

まとめ

上のようなデータを、csvファイルから読み込んで、Rを用いてクラスごとに分析したい場合、解決策1、解決策2ともに以下の3行でOKという話。

解決策1の場合

dat<-read.csv("sample.csv",header=TRUE)  
library(psych) 
tapply(dat$score,dat$class,describe) 

解決策2の場合

dat<-read.csv("sample.csv",header=TRUE) 
library(psych) 
describeBy(dat$score,dat$class)