R のデータフレームやベクトルに対してドカンとリスト処理を適用したいことが度々あるのですが、都度やり方を調べていて進歩が無いので、整理のためにまとめておきます。
操作 | ベクトル | データフレーム |
---|---|---|
map 関数 | ベクトル演算 / sapply 関数 | 列ベクトル同士をベクトル演算 |
fold 関数 | sum や mean 等の集約関数に突っ込む | なし |
filter 関数 | which 関数の結果を添字とする | subset 関数 |
色々と罠が多いし、簡単に実現できないこともあるので、難しくなってきたら awk なり Excel なりで前処理する方が良さそうです。
データ
以下の例では徳川時代の諸侯のデータを使います。
# shoko.txt kamei ryogoku kokudaka type 徳川宗家 天領 400 将軍家 前田家 加賀 103 外様 島津家 薩摩 77 外様 伊達家 陸奥 63 外様 尾張徳川家 尾張 62 御三家 紀州徳川家 紀伊 58 御三家 細川家 肥後 54 外様
このデータを、 read.table 関数で読み込みます。
shoko <- read.table('shoko.txt', header = TRUE) shoko # kamei ryogoku kokudaka type # 1 徳川宗家 天領 400 将軍家 # 2 前田家 加賀 103 外様 # 3 島津家 薩摩 77 外様 # 4 伊達家 陸奥 63 外様 # 5 尾張徳川家 尾張 62 御三家 # 6 紀州徳川家 紀伊 58 御三家 # 7 細川家 肥後 54 外様
ベクトルに対する map 関数の適用
スカラ値を引数に取る関数や演算子を使う時に、スカラ値の代わりにベクトルを指定すると、個々の要素に演算を適用した結果のベクトルが戻ります。
shoko$kokudaka * 10000 # [1] 4000000 1030000 770000 630000 620000 580000 540000 (function(x) { return(x * 10000) })(shoko$kokudaka) # [1] 4000000 1030000 770000 630000 620000 580000 540000
sapply 関数を使っても同じことができます。
sapply(shoko$kokudaka, function(x) { return(x * 10000) }) # [1] 4000000 1030000 770000 630000 620000 580000 540000
ベクトルに対する fold 関数の適用
それっぽいものはなさそうです。数値ベクトルを取って集約する関数が豊富なので、大体何とかなる気がします。
sum(shoko$kokudaka) # 合計 # [1] 817 mean(shoko$kokudaka) # 平均値 # [1] 116.7143 sd(shoko$kokudaka) # 不偏標準偏差 # [1] 126.0128
ベクトルに対する filter 関数の適用
which 関数で、条件を満たす要素の添字ベクトルが取れます。この添字ベクトルで要素を絞ります。
which(shoko$kokudaka >= 100) # 100万石以上の諸侯の添字 # [1] 1 2 shoko$kokudaka[which(shoko$kokudaka >= 100)] # 100万石以上の諸侯の石高 # [1] 400 103 shoko$kamei[which(shoko$kokudaka >= 100)] # 100万石以上の諸侯の家名 # [1] 徳川宗家 前田家
データフレームに対する map 関数の適用
結果としてスカラ値のベクトルが欲しいなら、列ベクトル同士をベクトル演算します。
paste(shoko$kamei, shoko$kokudaka * 10000, '石') # [1] "徳川宗家 4e+06 石" "前田家 1030000 石" "島津家 770000 石" # [4] "伊達家 630000 石" "尾張徳川家 620000 石" "紀州徳川家 580000 石" # [7] "細川家 540000 石"
結果としてデータフレームが欲しいなら、列ベクトルを data.frame 関数に突っ込みます。
> data.frame(kamei = shoko$kamei, kokudaka = shoko$kokudaka * 10000) # kamei kokudaka # 1 徳川宗家 4000000 # 2 前田家 1030000 # 3 島津家 770000 # 4 伊達家 630000 # 5 尾張徳川家 620000 # 6 紀州徳川家 580000 # 7 細川家 540000
データフレームに対する fold 関数の適用
直接該当するものはなさそうです。ベクトルの集約を組み合わせて何とかすれば大体間に合う気がします。
データフレームに対する filter 関数の適用
subset 関数で絞り込みます。この時、論理 OR は | で、論理 AND は & で書く必要があります (id:miyakawa_taku:20121101:1351784444) 。
subset(shoko, type == '将軍家' | type == '御三家') # kamei ryogoku kokudaka type # 1 徳川宗家 天領 400 将軍家 # 5 尾張徳川家 尾張 62 御三家 # 6 紀州徳川家 紀伊 58 御三家