2015-05-19 17 views
12

Meine Datenrahmen unter Verwendung von wie folgt aussieht, und ich möchte zwei separate kumulative Spalten, eine für Fonds A und die andere für Fonds Bbedingte kumulative Summe dplyr

Name Event SalesAmount Fund Cum-A(desired) Cum-B(desired) 
John Webinar NA   NA  NA    NA 
John Sale  1000   A  1000    NA 
John Sale  2000   B  1000    2000 
John Sale  3000   A  4000    2000 
John Email NA    NA  4000    2000 
Tom  Webinar NA   NA  NA    NA 
Tom  Sale  1000   A  1000    NA 
Tom  Sale  2000   B  1000    2000 
Tom  Sale  3000   A  4000    2000 
Tom  Email NA    NA  4000    2000 

I have tried: 
df<- 
    df %>% 
    group_by(Name)%>% 
    mutate(Cum-A = as.numeric(ifelse(Fund=="A",cumsum(SalesAmount),0)))%>% 
    mutate(Cum-B = as.numeric(ifelse(Fund=="B",cumsum(SalesAmount),0))) 

aber es ist absolut nicht, was ich will, wie es mir zeigt, die Runningtotal von beiden Fonds, wenn auch nur in der Reihe, wenn die Mittel übereinstimmen. Bitte helfen.

Antwort

8

Wie wäre:

library(dplyr) 

d %>% 
    group_by(Name) %>% 
    mutate(cA=cumsum(ifelse(!is.na(Fund) & Fund=="A",SalesAmount,0))) %>% 
    mutate(cB=cumsum(ifelse(!is.na(Fund) & Fund=="B",SalesAmount,0))) 

Der Ausgang:

Source: local data frame [10 x 8] 
Groups: Name 

    Name Event SalesAmount Fund Cum.A.desired. Cum.B.desired. cA cB 
1 John Webinar   NA NA    NA    NA 0 0 
2 John Sale  1000 A   1000    NA 1000 0 
3 John Sale  2000 B   1000   2000 1000 2000 
4 John Sale  3000 A   4000   2000 4000 2000 
5 John Email   NA NA   4000   2000 4000 2000 
6 Tom Webinar   NA NA    NA    NA 0 0 
7 Tom Sale  1000 A   1000    NA 1000 0 
8 Tom Sale  2000 B   1000   2000 1000 2000 
9 Tom Sale  3000 A   4000   2000 4000 2000 
10 Tom Email   NA NA   4000   2000 4000 2000 

Zeroes in den resultierenden Spalten können danach durch NA ersetzt werden, wenn nötig:

result$cA[result$cA==0] <- NA 
result$cB[result$cB==0] <- NA 

Ihre Eingangsdatensatz:

d <- structure(list(Name = structure(c(1L, 1L, 1L, 1L, 1L, 2L, 2L,  2L, 2L, 2L), .Label = c("John", "Tom"), class = "factor"), Event = structure(c(3L,  2L, 2L, 2L, 1L, 3L, 2L, 2L, 2L, 1L), .Label = c("Email", "Sale",  "Webinar"), class = "factor"), SalesAmount = c(NA, 1000L, 2000L,  3000L, NA, NA, 1000L, 2000L, 3000L, NA), Fund = structure(c(NA,  1L, 2L, 1L, NA, NA, 1L, 2L, 1L, NA), .Label = c("A", "B"), class = "factor"),   Cum.A.desired. = c(NA, 1000L, 1000L, 4000L, 4000L, NA, 1000L,   1000L, 4000L, 4000L), Cum.B.desired. = c(NA, NA, 2000L, 2000L,   2000L, NA, NA, 2000L, 2000L, 2000L)), .Names = c("Name",  "Event", "SalesAmount", "Fund", "Cum.A.desired.", "Cum.B.desired." ), class = "data.frame", row.names = c(NA, -10L)) 
+0

"s" nach 'Ereignisse fehlt = "s" tructure' im Datensatz –

+0

dank @ StevenBeaupré –

+0

' Ereignis == "Sale" 'könnte ein schöner Weg sein schriftlich "! is.na (Fund)", wenn die Daten des OP es erlauben. – Frank

2

Sie @ Antwort des Marat verkürzen kann leicht durch sie alle in einem einzigen mutate rollen:

df %>% 
    group_by(Name) %>% 
    mutate(
    cA = cumsum(ifelse(!is.na(Fund) & Fund == "A", SalesAmount, 0)), 
    cB = cumsum(ifelse(!is.na(Fund) & Fund == "B", SalesAmount, 0)), 
    cA = ifelse(cA == 0, NA, cA), 
    cB = ifelse(cB == 0, NA, cB) 
) 
+1

Ja, guter Punkt, es ist nicht notwendig - danke – ivyleavedtoadflax

+3

Dies sollte nur ein Kommentar unter @Marats Antwort sein. –

+1

Stimme zu, aber nicht genug Rep zu kommentieren. – ivyleavedtoadflax

3

Hier ist ein Ansatz, um mehr Mittel zu verallgemeinern, mit zoo und data.table:

# prep 
require(data.table) 
require(zoo) 
setDT(d) 
d[,Fund:=as.character(Fund)]   # because factors are the worst 
uf <- unique(d[Event=="Sale"]$Fund) # collect set of funds 

Erstens Zuweisen kumulativer Verkäufe für die relevante Teilmenge von Beobachtungen:

for (f in uf) d[(Event=="Sale"&Fund==f),paste0('c',f):=cumsum(SalesAmount),by=Name] 

Dann tragen die letzte Beobachtung nach vorn:

d[,paste0('c',uf):=lapply(.SD,na.locf,na.rm=FALSE),.SDcols=paste0('c',uf),by=Name]