2013-02-21 13 views
12

Potrzebuję użyć grupy według poziomów z ddply lub agregatu, jeśli jest to łatwiejsze. Nie jestem naprawdę pewny, jak to zrobić, ponieważ muszę użyć cumsum jako mojej funkcji agregującej. To co moje dane wygląda następująco:cumsum przy użyciu ddply

level1  level2 hour  product 
A   tea  0   7 
A   tea  1   2 
A   tea  2   9 
A   coffee 17   7 
A   coffee 18   2 
A   coffee 20   4 
B   coffee 0   2 
B   coffee 1   3 
B   coffee 2   4 
B   tea  21   3 
B   tea  22   1 

oczekiwany wynik:

A  tea  0 7 
A  tea  1 9 
A  tea  2 18 
A  coffee 17 7 
A  coffee 18 9 
A  coffee 20 13 
B  coffee 0 2 
B  coffee 1 5 
B  coffee 2 9 
B  tea  21 3 
B  tea  22 4 

Próbowałem za pomocą

ddply(dd,c("level1","level2","hour"),summarise,cumsum(product)) 

ale nie sumują się i myślę, że to dlatego, że kolumny godzinnym jest używany w grupie przez i jest przez to dzielony .. Myślę ... Nie jestem pewien, czy całkowicie rozumiem, jak działa tutaj agregacja. Czy jest jakiś sposób, aby uzyskać wymaganą wydajność za pomocą agregatu lub ddply?

+0

Nie sądzę, chodziło do podsumowania przez równej1 + 2 Poziom + godziny, bo wtedy, Twój agregacji byłby inny niż to, co masz pokazane. – A5C1D2H2I1M1N2O1R2T1

Odpowiedz

16

Oto rozwiązanie w podstawowej R używając ave i within:

within(mydf, { 
    cumsumProduct <- ave(product, level1, level2, FUN = cumsum) 
}) 
# level1 level2 hour product cumsumProduct 
# 1  A tea 0  7    7 
# 2  A tea 1  2    9 
# 3  A tea 2  9   18 
# 4  A coffee 17  7    7 
# 5  A coffee 18  2    9 
# 6  A coffee 20  4   13 
# 7  B coffee 0  2    2 
# 8  B coffee 1  3    5 
# 9  B coffee 2  4    9 
# 10  B tea 21  3    3 
# 11  B tea 22  1    4 

Oczywiście, jeśli chciał spadać istniejącą kolumnę produktu, można zmienić polecenie na następujące, aby zastąpić bieżącą kolumnę "produkt":

within(mydf, { 
    product <- ave(product, level1, level2, FUN = cumsum) 
}) 

Twoje obecne podejście nie działa częściowo, ponieważ uwzględniłeś "godzinę" jako jedną ze zmiennych grupujących. Innymi słowy, to połączenie "A + herbata + 0" różni się od "A + herbata + 1", ale z pożądanej wydajności, po prostu chcesz, aby kombinacja "A + herbata" była Grupa.

aggregate nie będzie działać zgodnie z oczekiwaniami, ponieważ spowoduje skondensowanie wszystkiego w postaci data.frame z taką samą liczbą rzędów, jak liczba unikalnych kombinacji "level1" i "level2", w tym przypadku 4 wiersze. Zagregowana kolumna będzie miała postać list. Wartości byłyby poprawne, ale byłoby mniej użyteczne.

Oto aggregate a jego produkcja:

> aggregate(product ~ level1 + level2, mydf, cumsum) 
    level1 level2 product 
1  A coffee 7, 9, 13 
2  B coffee 2, 5, 9 
3  A tea 7, 9, 18 
4  B tea  3, 4 
+0

dzięki! to działa :) Więc kiedy dajesz produkt, level1 i level2 jako trzy kolumny, mówisz mu, żeby wybrał te 3 i grupę według tego, co jest inne? – Roshini

+1

'ave' po prostu stosuje funkcję do jednej zmiennej (pierwszej) pogrupowanej według wielu innych zmiennych, jeśli to konieczne. Z tego powodu funkcja 'FUN' musi być używana do wywoływania dowolnej funkcji, którą chcesz zastosować do zmiennej * first *. – A5C1D2H2I1M1N2O1R2T1

+0

@AnandaMahto wadą nauczania ludzi jest to, że nie uogólnia się również na nowe sytuacje, a także jest nieefektywne, jeśli połączenie zmiennych grupujących jest rzadkie (niestety jest to prosty błąd, którego R-core nie zostało naprawione). – hadley

7

należy użyć transform zamiast summarise:

# you should probably order your `level2` first 
dd$level2 <- factor(dd$level2, levels=c("tea", "coffee")) 
# and transform using level1 and level2 alone, not hour 
# if you use hour, the groups will be for each row 
ddply(dd, .(level1, level2), transform, product=cumsum(product)) 

# level1 level2 hour product 
# 1  A tea 0  7 
# 2  A tea 1  9 
# 3  A tea 2  18 
# 4  A coffee 17  7 
# 5  A coffee 18  9 
# 6  A coffee 20  13 
# 7  B tea 21  3 
# 8  B tea 22  4 
# 9  B coffee 0  2 
# 10  B coffee 1  5 
# 11  B coffee 2  9 
+0

Dziękuję za odpowiedź ... ale co, jeśli mam więcej niż 2 poziomy na poziomie 2. Nie może być łatwo scenariusz, że mogę mieć około 10 lub więcej poziomów, czy będę musiał umieścić je w wektorze za każdym razem? – Roshini

+1

'dd $ level2 <- factor (dd $ level2, levels = dd $ levels2 [! Duplicated (dd $ levels2)], ordered = T)' – Arun