SQLのgroup byのようにRのデータフレームをグルーピングして、sumやmaxを取るのに意外に手間取ってしまったので、メモ。
by関数の第一引数は関数を適用したいデータフレーム、第二引数はグルーピングしたいキーのリスト、第三引数はグルーピン後のサブデータフレームに適用したい関数となる。
具体的には適用する関数を無名関数で作ってあげればいい。
これで、グループ毎のmaxが取れるし、無名関数の中でデータのカラムを選別するので、by関数の第一引数をサブデータフレームにする必要もない。
同じ考え方で、colSumsを使わずにsumを取ると、以下のようになる。
まず、データ
このようにA,B,Cとラベリングされたデータに対して、ラベルの値ごとにsumやmaxを取りたい。label <- c("A", "B", "C", "A", "B", "C") v1 <- c(1, 2, 3, 4, 5, 6) v2 <- c(100, 200, 300, 400, 500, 600) df <- data.frame(label, v1, v2) df label v1 v2 1 A 1 100 2 B 2 200 3 C 3 300 4 A 4 400 5 B 5 500 6 C 6 600
by関数とcolSums関数
単純にsumを取りたい場合は、colSums関数をby関数に渡せばいい。by関数の第一引数は関数を適用したいデータフレーム、第二引数はグルーピングしたいキーのリスト、第三引数はグルーピン後のサブデータフレームに適用したい関数となる。
by(df[,2:3], df$label, colSums) df$label: A v1 v2 5 500 ------------------------------ df$label: B v1 v2 7 700 ------------------------------ df$label: C v1 v2 9 900
maxはどうする。
by関数とcolSums関数でグループ毎のsumは取れるけど、maxは適用する関数をもう少し一般形にする必要がある。具体的には適用する関数を無名関数で作ってあげればいい。
by(df, df$label, function(m) c(v1 = max(m$v1), v2 = max(m$v2))) df$label: A v1 v2 4 400 ------------------------------- df$label: B v1 v2 5 500 ------------------------------- df$label: C v1 v2 6 600
これで、グループ毎のmaxが取れるし、無名関数の中でデータのカラムを選別するので、by関数の第一引数をサブデータフレームにする必要もない。
同じ考え方で、colSumsを使わずにsumを取ると、以下のようになる。
by(df, df$label, function(m) c(v1 = sum(m$v1), v2 = sum(m$v2))) df$label: A v1 v2 5 500 ------------------------------- df$label: B v1 v2 7 700 ------------------------------- df$label: C v1 v2 9 900
0 件のコメント:
コメントを投稿