web-dev-qa-db-ja.com

2つ以上の因子変数による要約統計量?

これは例で最もよく説明されています

str(mtcars)
mtcars$gear <- factor(mtcars$gear, labels=c("three","four","five"))
mtcars$cyl <- factor(mtcars$cyl, labels=c("four","six","eight"))
mtcars$am <- factor(mtcars$am, labels=c("manual","auto")
str(mtcars)
tapply(mtcars$mpg, mtcars$gear, sum)

これにより、ギアごとの合計mpgが得られます。しかし、上部にギアがあり、側面にシリンダーがあり、2変量の合計が9つのセルになっている3x3テーブルが必要だったとしたら、どうすれば「スマート」にできますか。

行くことができました。

tapply(mtcars$mpg[mtcars$cyl=="four"], mtcars$gear[mtcars$cyl=="four"], sum)
tapply(mtcars$mpg[mtcars$cyl=="six"], mtcars$gear[mtcars$cyl=="six"], sum)
tapply(mtcars$mpg[mtcars$cyl=="eight"], mtcars$gear[mtcars$cyl=="eight"], sum)

これは扱いにくいようです。

それでは、どのようにして3番目の変数をミックスに組み込むのでしょうか。

これは、私が考えているスペースに多少あります。 ddplyを使用した要約統計

updateこれは私をそこに連れて行きますが、きれいではありません。

aggregate(mpg ~ am+cyl+gear, mtcars,sum)

乾杯

13
nzcoops

まだtapply()を使っていますか?それはあなたが知っているよりも用途が広いです!

with(mtcars, tapply(mpg, list(cyl, gear), sum))
#       three  four five
# four   21.5 215.4 56.4
# six    39.5  79.0 19.7
# eight 180.6    NA 30.8

または、印刷出力をもう少しわかりやすくしたい場合は、次のようにします。

with(mtcars, tapply(mpg, list("Cylinder#"=cyl, "Gear#"=gear), sum))

3つ以上の相互分類変数を使用する場合も、考え方はまったく同じです。結果は3次元以上の配列で返されます。

A <- with(mtcars, tapply(mpg, list(cyl, gear, carb), sum))

dim(A)
# [1] 3 3 6
lapply(1:6, function(i) A[,,i]) # To convert results to a list of matrices

# But eventually, the curse of dimensionality will begin to kick in...
table(is.na(A))
# FALSE  TRUE 
#    12    42 
35
Josh O'Brien

この質問の回答は素晴らしいオプションだと思いますが、dplyrパッケージに基づいて追加のオプションを共有したいと思いました(これは、私がdplyrはデータ操作に使用するため、tapplyaggregateなどの特殊なベースR関数を生徒に紹介しないようにしました。

group_by関数を使用して、必要な数の変数をグループ化し、これらのグループからの情報をsummarizeで要約できます。このコードは、Rの初心者にとって、数式ベースのaggregateのインターフェイスよりも読みやすく、同じ結果が得られると思います。

library(dplyr)
mtcars %>%
  group_by(am, cyl, gear) %>%
  summarize(mpg=sum(mpg))
#       am   cyl  gear   mpg
#    (dbl) (dbl) (dbl) (dbl)
# 1      0     4     3  21.5
# 2      0     4     4  47.2
# 3      0     6     3  39.5
# 4      0     6     4  37.0
# 5      0     8     3 180.6
# 6      1     4     4 168.2
# 7      1     4     5  56.4
# 8      1     6     4  42.0
# 9      1     6     5  19.7
# 10     1     8     5  30.8

2つの変数を使用すると、spreadパッケージからtidyr関数への呼び出しを追加することにより、行の1つの変数と列のもう1つの変数で要約できます。

library(dplyr)
library(tidyr)
mtcars %>%
  group_by(cyl, gear) %>%
  summarize(mpg=sum(mpg)) %>%
  spread(gear, mpg)
#     cyl     3     4     5
#   (dbl) (dbl) (dbl) (dbl)
# 1     4  21.5 215.4  56.4
# 2     6  39.5  79.0  19.7
# 3     8 180.6    NA  30.8
9
josliber

私はこれに対するジョシュの答えが好きですが、reshape2は、これらのタイプの問題に適切なフレームワークを提供することもできます。

library(reshape2)

#use subset to only grab the variables of interest...
mtcars.m <- melt(subset(mtcars, select = c("mpg", "gear", "cyl")), measure.vars="mpg")
#cast into appropriate format
dcast(mtcars.m, cyl ~ gear, fun.aggregate=sum, value.var="value")

   cyl three  four five
1  four  21.5 215.4 56.4
2   six  39.5  79.0 19.7
3 eight 180.6   0.0 30.8
4
Chase

答えには、tapplyおよびaggregate関数を使用した同じ出力が含​​まれています。

Josh O'Brienの回答にいくつかの情報を追加したいと思います。ユーザーは、出力に応じて集約関数またはタッププライのいずれかを使用できます。 Tapplyで複数の因子変数を使用するには、Joshが示した方法を使用できます。

データセットを読み込んでいます

data("mtcars")

Tapplyの使用

with(mtcars, tapply(mpg, list("Cylinder#"=cyl, "Gear#"=gear), sum))

上記のコードの出力は

        Gear#
Cylinder#     3     4    5
    4     21.5 215.4 56.4
    6     39.5  79.0 19.7
    8    180.6    NA 30.8

集計関数の使用

with(mtcars, aggregate(mpg, list(Cylinder = cyl, Gear =  gear), sum))

集計関数の出力

    Cylinder Gear  x
1        4    3  21.5
2        6    3  39.5
3        8    3 180.6
4        4    4 215.4
5        6    4  79.0
6        4    5  56.4
7        6    5  19.7
8        8    5  30.8

ここで、ユーザーが集約関数と同じ出力を望んでいるが、tapplyを使用している場合。

as.data.frame(as.table(with(mtcars, tapply(mpg, list("Cylinder#"=cyl, "Gear#"=gear),
sum))))

Tapply関数の出力

   Cylinder. Gear.  Freq
1         4     3  21.5
2         6     3  39.5
3         8     3 180.6
4         4     4 215.4
5         6     4  79.0
6         8     4    NA
7         4     5  56.4
8         6     5  19.7
9         8     5  30.8

NAは、ビジネス要件に従って保持または削除できます。

3