vapplyとtapplyの使い方について
この記事はRstudioのSwirlの「11: vapplyとtapply」を参照しています。
まずFlagsというデータセットをRに読み込みます(Swirlを使用している場合、自動的に読み込まれます。)。
参考までにflagsのsummaryの結果を示します。
> summary(flags) name landmass zone area Afghanistan : 1 Min. :1.000 Min. :1.000 Min. : 0.0 Albania : 1 1st Qu.:3.000 1st Qu.:1.000 1st Qu.: 9.0 Algeria : 1 Median :4.000 Median :2.000 Median : 111.0 American-Samoa: 1 Mean :3.572 Mean :2.211 Mean : 700.0 Andorra : 1 3rd Qu.:5.000 3rd Qu.:4.000 3rd Qu.: 471.2 Angola : 1 Max. :6.000 Max. :4.000 Max. :22402.0 (Other) :188 population language religion bars Min. : 0.00 Min. : 1.00 Min. :0.000 Min. :0.0000 1st Qu.: 0.00 1st Qu.: 2.00 1st Qu.:1.000 1st Qu.:0.0000 Median : 4.00 Median : 6.00 Median :1.000 Median :0.0000 Mean : 23.27 Mean : 5.34 Mean :2.191 Mean :0.4536 3rd Qu.: 14.00 3rd Qu.: 9.00 3rd Qu.:4.000 3rd Qu.:0.0000 Max. :1008.00 Max. :10.00 Max. :7.000 Max. :5.0000 stripes colours red green Min. : 0.000 Min. :1.000 Min. :0.0000 Min. :0.0000 1st Qu.: 0.000 1st Qu.:3.000 1st Qu.:1.0000 1st Qu.:0.0000 Median : 0.000 Median :3.000 Median :1.0000 Median :0.0000 Mean : 1.552 Mean :3.464 Mean :0.7887 Mean :0.4691 3rd Qu.: 3.000 3rd Qu.:4.000 3rd Qu.:1.0000 3rd Qu.:1.0000 Max. :14.000 Max. :8.000 Max. :1.0000 Max. :1.0000 blue gold white black Min. :0.0000 Min. :0.0000 Min. :0.0000 Min. :0.000 1st Qu.:0.0000 1st Qu.:0.0000 1st Qu.:1.0000 1st Qu.:0.000 Median :1.0000 Median :0.0000 Median :1.0000 Median :0.000 Mean :0.5103 Mean :0.4691 Mean :0.7526 Mean :0.268 3rd Qu.:1.0000 3rd Qu.:1.0000 3rd Qu.:1.0000 3rd Qu.:1.000 Max. :1.0000 Max. :1.0000 Max. :1.0000 Max. :1.000 orange mainhue circles crosses Min. :0.000 red :71 Min. :0.0000 Min. :0.0000 1st Qu.:0.000 blue :40 1st Qu.:0.0000 1st Qu.:0.0000 Median :0.000 green :31 Median :0.0000 Median :0.0000 Mean :0.134 white :22 Mean :0.1701 Mean :0.1495 3rd Qu.:0.000 gold :19 3rd Qu.:0.0000 3rd Qu.:0.0000 Max. :1.000 black : 5 Max. :4.0000 Max. :2.0000 (Other): 6 saltires quarters sunstars crescent Min. :0.00000 Min. :0.0000 Min. : 0.000 Min. :0.0000 1st Qu.:0.00000 1st Qu.:0.0000 1st Qu.: 0.000 1st Qu.:0.0000 Median :0.00000 Median :0.0000 Median : 0.000 Median :0.0000 Mean :0.09278 Mean :0.1495 Mean : 1.387 Mean :0.0567 3rd Qu.:0.00000 3rd Qu.:0.0000 3rd Qu.: 1.000 3rd Qu.:0.0000 Max. :1.00000 Max. :4.0000 Max. :50.000 Max. :1.0000 triangle icon animate text Min. :0.0000 Min. :0.0000 Min. :0.000 Min. :0.00000 1st Qu.:0.0000 1st Qu.:0.0000 1st Qu.:0.000 1st Qu.:0.00000 Median :0.0000 Median :0.0000 Median :0.000 Median :0.00000 Mean :0.1392 Mean :0.2526 Mean :0.201 Mean :0.08247 3rd Qu.:0.0000 3rd Qu.:0.7500 3rd Qu.:0.000 3rd Qu.:0.00000 Max. :1.0000 Max. :1.0000 Max. :1.000 Max. :1.00000 topleft botright black :12 red :69 blue :43 blue :47 gold : 6 green :40 green :32 white :17 orange: 4 black : 9 red :56 gold : 9 white :41 (Other): 3
vapply
前回の記事で以下のコードを実行すると、結果としてリストを返すことが分かりました
(それぞれのリストの要素の長さが異なるため、簡潔化(simplify)できずlapplyと同じ結果となります。)
> sapply(flags, unique)
ここで、もしunique関数の機能を忘れていて、ダブりを除いた結果を数値(numeric)で返すと認識していたらどうなるでしょうか。その場合コードの途中で間違いが起こってしまいます。そのような間違いを防ぐために、vapplyの出番となります。sapplyが結果のフォーマットをRがある程度予測するするのに対し、vapplyでは結果のフォーマットを自分で指定することができます。それにより、予期しない結果を得ることを防ぐことができます。
以下のコードは結果はnumericで長さ1を返すよう指定しています。コードを実行するとどうなるでしょうか。
> vapply(flags, unique, numeric(1))
結果はこのようになり、エラーが発生します。
Error in vapply(flags, unique, numeric(1)) : values must be length 1, but FUN(X[[1]]) result is length 194
例えば前回の記事で行った以下のコードを実行するとsapplyはキャラクターベクターを結果として返します。
> sapply(flags, class)
この結果をもとに、vapplyで以下のコードを実行するとsapplyと同じ結果を返します。これはvapplyにclass関数をflagsのそれぞれの列に実行し、結果はcharacterで長さ1と指定しているからです。
> vapply(flags, class, character(1)) name landmass zone area population language religion "factor" "integer" "integer" "integer" "integer" "integer" "integer" bars stripes colours red green blue gold "integer" "integer" "integer" "integer" "integer" "integer" "integer" white black orange mainhue circles crosses saltires "integer" "integer" "integer" "factor" "integer" "integer" "integer" quarters sunstars crescent triangle icon animate text "integer" "integer" "integer" "integer" "integer" "integer" "integer" topleft botright "factor" "factor"
このようにvapplyを使用することで予期せぬエラーを防ぐことができますが、コードの動作をその都度確認している場合にはsapplyで十分です。
tapply
データを処理する際、データをある変数を基にグループで分け、その分割されたグループに対し、ある計算を行いたいことがあります。tapplyはまさにそのようなことを行います。何を言っているのかわかりずらいと思いますので、例を見ていきましょう。
flagsデータのlandmassは1から6の整数の値を取り、それにより世界の異なる地域を表します。
> table(flags$landmass) 1 2 3 4 5 6 31 17 35 52 39 20
同様にflagsデータのanimateは、もしその国旗が何かキャラクター(鷲、木、人の手など)を含んでいる場合は1を、含んでいない場合は0となります。
> table(flags$animate) 0 1 155 39
この結果より、39の国旗が何かしらのキャラクターを含んでいることが分かります。もしこの平均値を取ると、全体の国旗に対するキャラクターを含んでいる国旗の割合を計算できます。下の結果から20%の国旗で何かしらのキャラクターを含んでいることが分かります。
> 39/194*100 [1] 20.10309
以上を基に、以下のコードを実行してみましょう。
> tapply(flags$animate, flags$landmass, mean) 1 2 3 4 5 6 0.4193548 0.1764706 0.1142857 0.1346154 0.1538462 0.3000000
これはどういう意味かというと、それぞれのlandmassグループ1から6に対し、animateの平均値(mean)を求めています。landmass=1は北アメリカ大陸を表し、42%の国旗がキャラクターを含んでいます。
また以下の例では、国旗に赤色を含んでいる又はいない国の人口(100万)の概要を示しています。
> tapply(flags$population,flags$red, summary) $`0` Min. 1st Qu. Median Mean 3rd Qu. Max. 0.00 0.00 3.00 27.63 9.00 684.00 $`1` Min. 1st Qu. Median Mean 3rd Qu. Max. 0.0 0.0 4.0 22.1 15.0 1008.0
国旗に赤色を含んでいない国の人口の中央値は3.00であることが分かります。