2013-01-23 12 views
8

Korzystając z pakietu data.table, można podsumować zachowując kombinacje zmiennych, które nie pojawiają się na wejściu?Jak zachować kombinacje zmiennych, które nie pojawiają się w danych wejściowych podczas grupowania za pomocą data.table?

Z plyr pakietu wiem, jak to zrobić z argumentem .drop, na przykład:

require(plyr) 
df <- data.frame(categories = c(rep("A",3), rep("B",3), rep("C",3)), groups = c(rep(c("X", "Y"),4), "Z"), values = rep(1, 9)) 

df1 <- ddply(df, c("categories","groups"), .drop = F, summarise, sum = sum(values)) 

wyjściowa:

categories groups sum 
1   A  X 2 
2   A  Y 1 
3   A  Z 0 
4   B  X 1 
5   B  Y 2 
6   B  Z 0 
7   C  X 1 
8   C  Y 1 
9   C  Z 1 

W tym przypadku zachować wszystkie grupy/kategorie kombinacje, nawet jeśli jego suma wynosi 0.

Odpowiedz

8

Świetne pytanie. Oto dwa sposoby. Oboje korzystają z "by-without-by".

DT = as.data.table(df) 
setkey(DT,categories,groups) 
DT[CJ(unique(categories),unique(groups)), sum(values,na.rm=TRUE)] 

    categories groups V1 
1:   A  X 2 
2:   A  Y 1 
3:   A  Z 0 
4:   B  X 1 
5:   B  Y 2 
6:   B  Z 0 
7:   C  X 1 
8:   C  Y 1 
9:   C  Z 1 

gdzie CJ oznacza Krzyża Dołącz patrz ?CJ. "by-without-by" oznacza po prostu, że j zostaje wykonane w każdej grupie, do której dołącza każdy wiersz i.

Na pierwszy rzut oka wygląda na trudny. Chodzi o to, że jeśli masz znany podzbiór grup, ta składnia jest szybsza niż grupowanie wszystkiego, a następnie wybieranie tylko tych wyników, których potrzebujesz. Ale w tym przypadku i tak chcesz wszystko, więc nie ma zbyt wiele korzyści, poza możliwością wyszukiwania grup, które nie istnieją w danych (których nie można wykonać z by).

Innym sposobem jest by najpierw jako normalne, a następnie przystąpić do CJ() wynik to:

DT[,sum(values),keyby='categories,groups'][CJ(unique(categories),unique(groups))] 
    categories groups V1 
1:   A  X 2 
2:   A  Y 1 
3:   A  Z NA 
4:   B  X 1 
5:   B  Y 2 
6:   B  Z NA 
7:   C  X 1 
8:   C  Y 1 
9:   C  Z 1 

ale potem można dostać NA zamiast pożądanego 0. te mogą być zastąpione przy użyciu set() jeśli zajdzie taka potrzeba. Drugi sposób może być szybszy, ponieważ dwa wywołania unique mają znacznie mniejsze wejście.

Obie metody można zawinąć w małe funkcje pomocnicze, jeśli robisz to bardzo często.

Powiązane problemy