Сводная статистика по двум или более факторам?
Это лучше всего иллюстрируется примером
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 на каждую передачу. Но скажу, что мне нужна таблица 3x3 с шестеркой сверху и цилиндром вниз, и 9 ячеек с двузначными суммами, как бы я получил это "умно".
Я мог бы пойти.
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)
Приветствия
Ответы
Ответ 1
Как насчет этого, все еще используя 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-мерном массиве:
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
Ответ 2
Я думаю, что ответы уже на этот вопрос являются фантастическими вариантами, но я хотел поделиться дополнительным вариантом, основанным на пакете dplyr
(это пришло мне в голову, потому что я преподаю класс прямо сейчас, где мы используем dplyr
для манипуляций с данными, поэтому я хотел не вводить учащихся в специализированные базовые функции R, такие как tapply
или aggregate
).
Вы можете группировать столько переменных, сколько хотите, используя функцию 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
С двумя переменными вы можете суммировать с одной переменной в строках, а другую в столбцах, добавив вызов функции spread
из пакета tidyr
:
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
Ответ 3
Мне нравится Josh для этого, но 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
Ответ содержит тот же результат, используя функцию tapply и aggregate.
Я хотел бы добавить некоторую информацию в ответ Джоша О'Брайена. Пользователь может либо использовать функцию агрегата, либо использовать в зависимости от вывода. Чтобы использовать более одной фактор-переменной в tapply, можно использовать метод, показанный Джошем.
Загрузка набора данных
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
Теперь, если пользователь хочет получить тот же результат, что и функция aggregate, но используя 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 может храниться или удаляться в соответствии с требованиями бизнеса.