2016-03-29 3 views
1

Мне интересно, как я могу обеспечить, чтобы я включал все взаимодействия факторов при использовании агрегата, даже если они не отображаются в данном наборе данных.R - агрегатная функция, обеспечивающая взаимодействие всех уровней факторов

dff <- data.frame(a=as.factor(c(rep(1,3), rep(2,4), rep(3,3))), 
        b=as.factor(c(rep("A", 4), rep("B",6))), 
        c=sample(100,10)) 

levels(dff$b) <- c(levels(dff$b), "C") 
levels(dff$a) <- c(levels(dff$a), 10) 

dff$b 
#[1] A A A A B B B B B B 
#Levels: A B C 
dff$a 
#[1] 1 1 1 2 2 2 2 3 3 3 
#Levels: 1 2 3 10 

aggregate(c~a+b, dff, sum) 
# a b c 
#1 1 A 233 
#2 2 A 78 
#3 2 B 212 
#4 3 B 73 

что я хочу

 a b c 
    1 1 A 233 
    2 1 B 0 
    3 1 C 0 
    4 2 A 78 
    5 2 B 212 
    6 2 C 0 
    7 3 A 0 
    8 3 B 73 
    9 3 C 0 
    10 10 A 0 
    11 10 B 0 
    12 10 C 0 

Н.А. это тоже хорошо.

Причина, по которой я хочу в этом формате, заключается в том, что мне нужно взаимодействовать с dff $ c с результатами других наборов данных, и они могут иметь разную длину, если не все уровни факторов учитываются. Я пытаюсь избежать слияния и вместо этого использовать векторный расчет.

Заранее спасибо.

+1

использовать' complete' из "tidyr" или '' expand.grid' + merge' в базовой R? Вы хотите решить эту проблему или просто спросить в целом? – A5C1D2H2I1M1N2O1R2T1

+1

Я спрашиваю, потому что для этой конкретной проблемы вы можете просто использовать 'as.data.frame (xtabs (...))', как в 'as.data.frame (xtabs (c ~ a + b, dff))' , – A5C1D2H2I1M1N2O1R2T1

+1

При создании примера со случайным процессом добавьте '? Set.seed' для воспроизводимости. –

ответ

2

Если ваша функция агрегации будет только sum, вы можете просто использовать xtabs, что создаст объект, который включает в себя класс table. Таким образом, вы можете использовать data.frame, который будет вызывать соответствующий «метод», который создает «длинный» data.frame.

data.frame(xtabs(c ~ b + a, dff)) 
# b a Freq 
# 1 A 1 121 
# 2 B 1 0 
# 3 C 1 0 
# 4 A 2 89 
# 5 B 2 203 
# 6 C 2 0 
# 7 A 3 0 
# 8 B 3 126 
# 9 C 3 0 
# 10 A 10 0 
# 11 B 10 0 
# 12 C 10 0 

Это похоже на предложение @ Николы использовать as.data.frame.table, который явно вызывает метод для чего-то, что это явно не из «таблицы» класса, но может рассматриваться как единое целое.

Одним из преимуществ такого подхода (и всех остальных) является то, что вы можете использовать разные функции, отличные от sum.

as.data.frame.table(tapply(dff$c, dff[c("a","b")], sum)) 

Если merge ОК, вы можете продолжить aggregate шаг. В этом случае мы используем expand.grid на levels ваших векторов фактора:

merge(expand.grid(lapply(dff[c(1, 2)], levels)), 
     aggregate(c~a+b, dff, sum, drop = FALSE), all = TRUE) 

Аналогичный подход может быть использован в "data.table":

library(data.table) 
as.data.table(dff)[, sum(c), by = .(a, b)][do.call(CJ, lapply(dff[c(1, 2)], levels)), on = c("a", "b")] 

Или с помощью "dplyr" + «tidyr "(который по существу скрывает слияние, но в конечном счете использует left_join, чтобы создать недостающие комбинации):

library(dplyr) 
library(tidyr) 

dff %>% 
    group_by(a, b) %>% 
    summarise(c = sum(c)) %>% 
    complete(a, b, fill = list(c = 0)) 
+0

Спасибо за помощь в комментарии выше и подробное объяснение здесь! – chungkim271

Смежные вопросы