tapply(CO2$uptake, CO2[c("Type", "Treatment")], sum)
Treatment
Type nonchilled chilled
Quebec 742 666.8
Mississippi 545 332.1
2023年3月26日
これまで個票データの集計というテーマでtapply
、by
、aggregate
、dplyr::summarise
を紹介してきました。 これらでカテゴリ別の足し上げなどを行うことができますが、小計や合計を一緒に出したいときは少し困ります。
例えばtapply
関数でdatasets::CO2
データについて次のような集計を行ったとします。
Treatment
Type nonchilled chilled
Quebec 742 666.8
Mississippi 545 332.1
Type
別、Treatment
別の集計はできましたが、ここにそれぞれのカテゴリの小計と、全体の合計を加えたい場合はどうしたらよいでしょうか。実はそれらは別途作成しなくてはなりません。
まずType
とTreatment
の計は、片方だけのカテゴリで集計することで得られます。
Treatment
nonchilled chilled
1287.0 998.9
Type
Quebec Mississippi
1408.8 877.1
全体の合計は、単純にsum
を取るだけです。
これらを組み合わせて表を作ります。
cbind(matrix(c(sum(CO2$uptake), tapply(CO2$uptake, CO2["Type"], sum))),
rbind(tapply(CO2$uptake, CO2["Treatment"], sum),
tapply(CO2$uptake, CO2[c("Type", "Treatment")], sum)))
nonchilled chilled
2285.9 1287 998.9
Quebec 1408.8 742 666.8
Mississippi 877.1 545 332.1
手間がかかりますね。なぜこのような手順を踏むかと言うと、集計の関数はどれも基本的にデータ1つ1つをどこかのカテゴリに振り分けていて、1つのデータは1つのカテゴリにしか属することができないからです。上のような小計や合計を算出するには、1つのデータが自身のカテゴリに加えて小計と合計にも振り分けられる必要があります。つまり1つのデータを重複して数える必要があるのですが、それは通常の関数では一度にできないのです。
そこで、小計や合計も一度に算出する関数を自作しました。totalize
と命名しています。これを使うと次のような記述で上の表が作れます。
Treatment
Type all nonchilled chilled
all 2285.9 1287 998.9
Quebec 1408.8 742 666.8
Mississippi 877.1 545 332.1
引数の説明をすると、
となっています。
これは表(matrix
)の形で作った例ですが、aggregate
関数のようにdata frameの形で作ることもできます。それにはasDF=TRUE
を指定します。
Type Treatment uptake
1 all all 2285.9
2 all nonchilled 1287.0
3 all chilled 998.9
4 Quebec all 1408.8
5 Quebec nonchilled 742.0
6 Quebec chilled 666.8
7 Mississippi all 877.1
8 Mississippi nonchilled 545.0
9 Mississippi chilled 332.1
また、変数の値の足し上げではなくtable
関数のようにデータ数をカウントしたい場合は、4つ目の引数を省略します。その場合は5つ目以降の引数は名前付きで指定する必要があります。(なお、5つ目の引数がsum
ならばそれも省略できます)
totalize
関数の引数を見て、何か違和感を感じたかも知れません。実は変数の名前を指定するときにダブルクォーテーション""
で囲まなくてもよいように作っています。subset
関数で使われている”non-standard evaluation”を真似しています。
tidyverseパッケージの各関数は、それをさらに拡張して変数の名前の一部だけでも指定できたりしますね(starts_with()
など)。totalize
はそこまでは実装していません。そこまでやるならtidyselectパッケージを利用するべきですね。このtotalize
はそういった外部パッケージを使わずに、Rにプリインストールされているパッケージだけを使って実装しているのが特徴の1つです。
totalize
はRのパッケージとして作成してあります。私のGithubで公開していますのでご興味があればご覧ください。次のコマンドでパッケージのインストールができます。(devtools
パッケージを使います)