社会調査情報処理実習A 2組

2017年度 後期 木04 15:15-16:45 瀬田2-119

Rで表計算

RはExcelより圧倒的に楽に複雑な計算が出来ることが多いのだが、Excelで簡単にできるような計算に思わず苦労することがあったりする。というので、Excelで慣れ親しんだ単純な表計算をRを使ってやってみよう。

二次元の表

科目別成績
氏名国語数学社会理科合計
安倍66545787
飯田64348755
石黒87欠席6564
中澤98649065
福田欠席367572
平均
test.point.matrix <- matrix(c(66,54,57,87,64,34,87,55,87,NA,65,64,98,64,90,65,NA,36,75,72), ncol=4, byrow=T)
colnames(test.point.matrix) <- c("国語","数学","社会","理科")
rownames(test.point.matrix) <- c("安倍","飯田","石黒","中澤","福田")

各要素へのアクセスは一般的なプログラミング言語の二次元配列とは異なり、要素[行番号,列番号]。

#中澤さんの数学
test.point.matrix[4,2]

行列の入れ替え

t関数…行・列の入れ替え

t(X)

表matrixの行列を入れ替える。

  • X=表(matrix)データ
t(test.point.matrix[4,2])

「行列の入れ替え(切り替え)」。グラフ作成するときなどに使う。

> test.point.matrix
     国語 数学 社会 理科
安倍   66   54   57   87
飯田   64   34   87   55
石黒   87   NA   65   64
中澤   98   64   90   65
福田   NA   36   75   72

> t(test.point.matrix)
     安倍 飯田 石黒 中澤 福田
国語   66   64   87   98   NA
数学   54   34   NA   64   36
社会   57   87   65   90   75
理科   87   55   64   65   72

行単位・列単位の計算

上記表で個人ごとの合計と科目ごとの平均を求めたい。

Excelなら相対参照+オートフィル(数式コピー)でちょちょいのちょいだが、Rではどうすれば良いだろうか。

プログラミングになれた人なら、ループを廻して、と思うだろう。

#個人ごとに点数の合計を計算する。
point.sum <- c(rep(0,length(rownames(test.point.matrix))))
for(i in 1:length(point.sum)){
    for(j in test.point.matrix[i,]){
        point.sum[i] <- sum(point.sum[i],j,na.rm=T)
    }
}
point.sum
#科目ごとに点数の平均を計算する。
point.sum <- c(rep(0,length(colnames(test.point.matrix))))
count <- c(rep(0,length(point.sum)))
for(i in 1:length(point.sum)){
    count[i] <- length(na.omit(test.point.matrix[,i]))
    for(j in test.point.matrix[,i]){
        point.sum[i] <- sum(point.sum[i],j,na.rm=T)
    }
}
point.sum/count

もちろんこれでも出来るが、Rはこの手の計算に関しては一般的な言語より遙かに関数が充実している。ループを廻すより、なるべく関数で処理する方が良い。

apply関数…行・列単位集計

apply(X, MARGIN, FUN)

表matrixを行単位または列単位に処理を行う。

  • X=表(matrix)データ
  • MARGIN=行単位1ないし列単位2で集計する
  • FUN=関数名ないし関数定義
#個人ごとに点数の合計を計算する。
apply(test.point.matrix,1,function(x) sum(x,na.rm=T))

#科目ごとに点数の平均値を計算する。
apply(test.point.matrix,2,function(x) mean(x,na.rm=T))
> apply(test.point.matrix,1,function(x) sum(x,na.rm=T))
安倍 飯田 石黒 中澤 福田 
 264  240  216  317  183 
> 
> apply(test.point.matrix,2,function(x) mean(x,na.rm=T))
 国語  数学  社会  理科 
78.75 47.00 74.80 68.60 

セルごとの計算

123456789
1
2
3
4
5
6
7
8
9
num <- 9
row.vec <- c(seq(1:num))
col.vec <- c(seq(1:num))

行×列で九九表を作りたい。Excelなら絶対参照と相対参照の組み合わせで、一般的なプログラミング言語なら二重ループでやるところ。

kuku <- matrix(seq(1:(num*num)),ncol=num)
for(i in row.vec){
    for(j in col.vec){
        kuku[i,j] <- i*j
    }
}
kuku

Rでは行データ一つ一つに列データを掛け合わせる、という作業を一気に行う。

sapply関数…要素ごとの処理

sapply(X, FUN)

要素ごとに処理を行って、表matrixで答えを返す。

  • X=ベクトル(vector)、表(matrix)など複数要素を含むデータ
  • FUN=関数名ないし関数定義
sapply(row.vec,function(x) x*col.vec)
> sapply(row.vec,function(x) x*col.vec)
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
 [1,]    1    2    3    4    5    6    7    8    9
 [2,]    2    4    6    8   10   12   14   16   18
 [3,]    3    6    9   12   15   18   21   24   27
 [4,]    4    8   12   16   20   24   28   32   36
 [5,]    5   10   15   20   25   30   35   40   45
 [6,]    6   12   18   24   30   36   42   48   54
 [7,]    7   14   21   28   35   42   49   56   63
 [8,]    8   16   24   32   40   48   56   64   72
 [9,]    9   18   27   36   45   54   63   72   81

条件付き集計

経費記録データを集計したい。

  • 担当別
  • 費目別
  • 担当・費目別

それぞれに請求件数・合計額を算出する。

経費記録
日付担当費目金額
5月6日藤本交通費5300
5月6日藤本食費2300
5月6日藤本消耗品費1500
5月6日松浦交通費2400
5月6日松浦消耗品費850
5月7日藤本交通費2000
5月7日藤本食費2500

一般的に条件に合うデータの摘出を行うやり方。

data <- read.csv("http://kyoto-edu.sakura.ne.jp/weblesson/statistics/data/expense.csv", fileEncoding = "utf-8")
#全請求件数
length(data$金額)
#請求金額合計
sum(data$金額)

#担当"藤本"である請求金額
sum(data$金額[data$担当=="藤本"])
#担当"藤本"かつ費目"食費"である請求金額合計
sum(data$金額[data$担当=="藤本" & data$費目=="交通費"])
> #全請求件数
> length(data$金額)
[1] 21
> #請求金額合計
> sum(data$金額)
[1] 37970
>
> #担当"藤本"である請求金額
> sum(data$金額[data$担当=="藤本"])
[1] 28810
> #担当"藤本"かつ費目"食費"である請求金額合計
> sum(data$金額[data$担当=="藤本" & data$費目=="交通費"])
[1] 15300

tapply関数…カテゴリー別集計

tapply(X, INDEX, FUN)

要素をグループごとに処理する

  • X=ベクトル(vector)、表(matrix)など複数要素を含むデータ
  • INDEX=カテゴリー変数
  • FUN=関数名ないし関数定義
data <- read.csv("http://kyoto-edu.sakura.ne.jp/weblesson/statistics/data/expense.csv", fileEncoding = "utf-8")
#担当別請求金額
tapply(data$金額,data$担当,sum)
#費目別請求件数
tapply(data$金額,data$費目,length)

#担当別費目別請求金額
tapply(data$金額,list(data$担当,data$費目),sum)
#担当別費目別請求件数
tapply(data$金額,list(data$担当,data$費目),length)
> #担当別請求金額
> tapply(data$金額,data$担当,sum)
 松浦  藤本 
 9160 28810 
> #費目別請求件数
> tapply(data$金額,data$費目,length)
  交通費 消耗品費     食費 
       8        6        7 
> 
> #担当別費目別請求金額
> tapply(data$金額,list(data$担当,data$費目),sum)
     交通費 消耗品費 食費
松浦   5350     1500 2310
藤本  15300     5450 8060
> #担当別費目別請求件数
> tapply(data$金額,list(data$担当,data$費目),length)
     交通費 消耗品費 食費
松浦      4        2    3
藤本      4        4    4

クロス集計

table関数

table(...)

水準ごとの度数を集計する

  • カテゴリー変数
data <- read.csv("http://kyoto-edu.sakura.ne.jp/weblesson/statistics/data/expense.csv", fileEncoding = "utf-8")
#費目別請求件数
table(data$費目)
#担当別費目別請求件数
table(data$担当,data$費目)
> #費目別請求件数
> table(data$費目)

  交通費 消耗品費     食費 
       8        6        7 
> #担当別費目別請求件数
> table(data$担当,data$費目)
      
       交通費 消耗品費 食費
  松浦      4        2    3
  藤本      4        4    4

addmargins関数…表に合計欄を付加

addmargins(X, MARGIN)

表matrixに合計欄を加える。

  • X=表(matrix)データ
  • MARGIN=全体(省略時)、行単位1、列単位2の合計を出力
data <- read.csv("http://kyoto-edu.sakura.ne.jp/weblesson/statistics/data/expense.csv", fileEncoding = "utf-8")
#合計金額欄を付加
addmargins(tapply(data$金額,list(data$担当,data$費目),sum))
#度数クロス集計表に周辺度数を付加
addmargins(table(data$担当,data$費目))
> #合計金額欄を付加
> addmargins(tapply(data$金額,list(data$担当,data$費目),sum))
     交通費 消耗品費  食費   Sum
松浦   5350     1500  2310  9160
藤本  15300     5450  8060 28810
Sum   20650     6950 10370 37970
> #度数クロス集計表に周辺度数を付加
> addmargins(table(data$担当,data$費目))
      
       交通費 消耗品費 食費 Sum
  松浦      4        2    3   9
  藤本      4        4    4  12
  Sum       8        6    7  21

比率

prop.table関数…比率計算

prop.table(X, MARGIN)

表matrix内データの比率計算をする。

  • X=表(matrix)データ
  • MARGIN=全体(省略時)、行単位1、列単位2の比率を出力
data <- read.csv("http://kyoto-edu.sakura.ne.jp/weblesson/statistics/data/expense.csv", fileEncoding = "utf-8")
#総合計金額に占める各項目(担当*費目)の比率
prop.table(tapply(data$金額,list(data$担当,data$費目),sum))
#費目別比率
prop.table(addmargins(tapply(data$金額,list(data$担当,data$費目),sum),margin=1),margin=1)
#担当別比率
prop.table(addmargins(tapply(data$金額,list(data$担当,data$費目),sum),margin=2),margin=2)
> #総合計金額に占める各項目(担当*費目)の比率
> prop.table(tapply(data$金額,list(data$担当,data$費目),sum))
        交通費   消耗品費      食費
松浦 0.1409007 0.03950487 0.0608375
藤本 0.4029497 0.14353437 0.2122728
> #費目別比率
> prop.table(addmargins(tapply(data$金額,list(data$担当,data$費目),sum),margin=1),margin=1)
        交通費  消耗品費      食費
松浦 0.5840611 0.1637555 0.2521834
藤本 0.5310656 0.1891704 0.2797640
Sum  0.5438504 0.1830392 0.2731104
> #担当別比率
> prop.table(addmargins(tapply(data$金額,list(data$担当,data$費目),sum),margin=2),margin=2)
        交通費  消耗品費     食費       Sum
松浦 0.2590799 0.2158273 0.222758 0.2412431
藤本 0.7409201 0.7841727 0.777242 0.7587569