備忘ログ

チラシの裏的備忘録&メモ

Rでデータフレームの行の和を列を選んで出す方法のメモ

Rでデータフレームの行の和をどの列かを選んで出す方法のメモ

全部の列の和を各行で計算する方法や、1~10列目と続いている場合にどうやって処理したらいいかはすぐに調べたらでてくるけど、どの列かを選んで計算する方法はいくつかのページの情報をまとめないといけないので、そのつどどこか忘れて調べ直しているので自分用のメモとして

心理測定尺度など、下位尺度がバラバラのところのものの和でしかも逆転項目を含んでいると手が結構かかる……

スマートにやる方法がどこかで紹介されているのかもしれないし、そういう関数がどこかにあるのかもしれないがみつけられず……

例としてScale of Psych(SOP)という(あくまで)架空の29項目、7件法で逆転項目(1,4,5,6,8,9,12,16,19,21,23,25,27)で、下位尺度が3つで第一因子が(1,3,5,10,12,15,17,19,21,24,26)、第二因子が(2,6,9,13,18,20,23,25,27,29)、第三因子が(4,7,8,11,14,16,22,28)の心理測定尺度の例で、各下位尺度得点と合計得点を算出したいとなるとかなり手間。

とりあえず自分なりの泥臭い手をメモしておく。


サンプルデータを作っておく(29項目7件法を100件分を想定)

x <- matrix(nrow = 100,ncol = 29) #100行29列のからの行列を作る
for(i in 1:29){
  x[,i] <- sample(1:7,100,replace = T) #行列に1~7の乱数を入れ込む
}
x <- data.frame(x) #データフレーム化する
#名前はdplyrのmutateで必要になるのでつけておく(つけないとX1~29となる)
sopname <- length(29) #名前のためのベクトルづくり
for(i in 1:29){
  sopname[i] <- paste("sop",i,sep = "") #ベクトルにsop1~29を入れる
}
colnames(x) <- sopname #データフレームの列に名前をつける

逆転項目の得点を逆転させておく

x[,c(1,4,5,6,8,9,12,16,19,21,23,25,27)] <- (1+7) - x[,c(1,4,5,6,8,9,12,16,19,21,23,25,27)] 
#逆転項目は1+何件法でその項目の得点を引く

まず、この逆転項目をちゃんと処理するのを始めにやっておかないと都度合計得点を出すときにやろうとするとめんどくさいし、忘れるし間違える。

何件の項目数+1から得点を引くと逆転項目がでる(5件法なら6-項目点数)。

しかし、このタイミングで間違えると以降全て間違えてしまうので要注意。

自作関数もいいけど、結局選ぶ項目を間違えるリスクを減らせないと元も子もない。

もっといい方法があればいいのだけれど……

もとの生回答データにもどしたければもう一回同じコマンドを叩く。


以下本題

applyを使う

#applyでデータフレームで各因子項目を選んで合計得点を入れていく
x <- transform(x, I_scale = apply(x[,c(1,3,5,10,12,15,17,19,21,24,26)],1,sum))
x <- transform(x, II_scale = apply(x[,c(2,6,9,13,18,20,23,25,27,29)], 1, sum))
x <- transform(x, III_scale = apply(x[,c(4,7,8,11,14,16,22,28)], 1, sum))
x <- transform(x, Total_scale = apply(x[,c(1:29)], 1, sum))

もとのデータフレームを汚してくなければ、y <- xとしていじる用のデータフレームyを作っておいてxをyに置き換えてやるといいと思う。

結局、項目を間違わないように注意しながら入力していく他ない。

入れ間違えたら泣く。

他の方法としては各因子だけのデータフレームを抜き出す方法

#各因子だけのデータフレームを抜き出す
i <- x[,c(1,3,5,10,12,15,17,19,21,24,26)]
ii <- x[,c(2,6,9,13,18,20,23,25,27,29)]
iii <- x[,c(4,7,8,11,14,16,22,28)]
total <- x[,c(1:29)]

#その中身は因子項目のみなのでapplyで合計する
I_scale <- apply(i, 1, sum)
II_scale <- apply(ii, 1, sum)
III_scale <- apply(iii, 1, sum)
total_scale <- apply(total, 1, sum)

#使いやすいようにデータフレーム化しておく
x2 <- data.frame(I_scale,II_scale,III_scale,total_scale)

#各因子ごとのデータフレームを作るメリットのひとつ
library(psych)
alpha(x[,c(1,3,5,10,12,15,17,19,21,24,26)]) #I因子のα係数
alpha(i) #上のと同じ結果がでる、上よりも誤入力リスクが低いと思う

これもデータフレームを抜き出すときに誤入力したら一巻の終わり。

たとえばα係数とかω係数とか出すときに、(x[,c(1,3,5,10,12,15,17,19,21,24,26)]) で各因子を選んでもいいけど、入力ミスのリスクがエグいし、コピペも結局消えたり切れたりのリスクがゼロじゃないので、作ってしまっているフレームを入れるとでるのでそういう点は安心感があるのがメリットの一つ。

デメリットはグローバル変数がどんどん増えていく。

Global Environmentが汚れるのが嫌だったり、あんまり増えていくと名前空間の衝突や他のグローバル変数を入れたときに誤って別の中身に書き換えてしまうリスクがある。

dplyrを使った方法は

#dplyrのmutateをつかってやる方法、列名を""で囲まなくていいから列名で選ぶほうが楽ならこっちのほうが楽
library(dplyr)
library(magrittr)

x <- x %>% 
  mutate(I_scale = sop1+sop3+sop5+sop10+sop12+sop15+sop17+sop19+sop21+sop24+sop26,
         II_scale = sop2+sop6+sop9+sop13+sop18+sop20+sop23+sop25+sop27+sop29,
         III_scale = sop4+sop7+sop8+sop11+sop14+sop16+sop22+sop28,
         total_scale = sop1+sop2+sop3+sop4+sop5+sop6+sop7+sop8+sop9+sop10+sop11+sop12+sop13+sop14+sop15+sop16+sop17+sop18+sop19+sop20+sop21+sop22+sop23+sop24+sop25+sop26+sop27+sop28+sop29)

#上のと同じだがmutateの中身が長いのでどこかで入力ミスしたときに見つけやすいように、3つに分けてパイプし続ける
#結局入れるものは同じなので長い
x <- x %>% 
  mutate(I_scale = sop1+sop3+sop5+sop10+sop12+sop15+sop17+sop19+sop21+sop24+sop26) %>% 
  mutate(II_scale = sop2+sop6+sop9+sop13+sop18+sop20+sop23+sop25+sop27+sop29) %>% 
  mutate(III_scale = sop4+sop7+sop8+sop11+sop14+sop16+sop22+sop28) %>% 
  mutate(total_scale = sop1+sop2+sop3+sop4+sop5+sop6+sop7+sop8+sop9+sop10+sop11+sop12+sop13+sop14+sop15+sop16+sop17+sop18+sop19+sop20+sop21+sop22+sop23+sop24+sop25+sop26+sop27+sop28+sop29)

メリットは列名で指定するときに"”でくくらなくてもいいので、列名で覚えていたり選びやすかったりしたらこっちのほうがいい。

ただ、列名が長いとだるいし、total_scaleなんかはapplyを使わないようにしてやると、項目数が多いと入力だるいし、誤入力リスクが上がる。

いずれにしても、この方法での前処理は誤入力との戦いなので集中力を切らさないようにするのと、あとで必ず見直すのを忘れずに。

excelだと、=A1+B1……と入力していると選んだ項目フォーカスされるし、マウスでも選択できるので最初から因子構造わかっていれば回答結果をexcelに入力している時点でexcel側で処理した方が入力ミスを防げるかもしれない。

Rで因子分析してその結果に基づいて各下位尺度の因子得点を出すときに、excelにもどるのがめんどくさい or Rで完結させたいときにこれをやる。

最初にも書いたがどれも泥臭すぎて入力ミスのリスクも高くて危うい。

しかし心理測定尺度の構造が各因子いろんなところにとんでいるんだから、人間の目でどの項目がどの因子か選んでやらないといけないのでしょうがない。

順番も規則性が基本的にはないのでloop処理とかできない。

しかも心理測定尺度がかわるたびに入れる項目が変わるのでリサイクルできないのがまた泣きポイント。

しかし前処理を怠ると前処理で泣く。