2012-12-09 15 views
5

Ich habe eine Zeitreihe von Sales by Account ID. Um das durchschnittliche Wachstum zu berechnen, muss ich den ersten Monat mit Nicht-Null-Verkäufen für jede ID extrahieren. Da das Konto zu unterschiedlichen Zeiten eingerichtet werden konnte, muss ich beim ersten Mal dynamisch identifizieren, wenn der Umsatz> 0 ist.Finden Sie das erste Nicht-Null-Vorkommen im Datenrahmen

Der Index zu der Zeile würde ausreichen, um zu einer Funktion zu gelangen, die Wachstum berechnet. Also erwarte ich die folgenden Ergebnisse nach Konto ID:

54 - [1] 
87 - [4] 
95 - [2] 

I tried `apply(df$Sales,2,match,x>0)` but this doesn't work. 

Irgendwelche Zeiger? Oder gibt es eine einfachere Möglichkeit, CAGR mit diesem Datensatz zu berechnen?

Vielen Dank im Voraus!

CalendarMonth ID Sales 
8/1/2008 54 6692.60274 
9/1/2008 54 6476.712329 
10/1/2008 54 6692.60274 
11/1/2008 54 6476.712329 
12/1/2008 54 11098.60822 
7/1/2008 87 0 
8/1/2008 87 0 
9/1/2008 87 0 
10/1/2008 87 18617.94155 
11/1/2008 87 18017.36279 
12/1/2008 87 18617.94155 
1/1/2009 87 18617.94155 
2/1/2009 87 16816.20527 
7/1/2008 95 0 
8/1/2008 95 8015.956284 
9/1/2008 95 0 
10/1/2008 95 8015.956284 
11/1/2008 95 6309.447514 
12/1/2008 95 6519.762431 
1/1/2009 95 6519.762431 
+1

Wollen Sie sagen, dass Sie den Index für diese Zeile in einer Untergruppe von Einträgen für eine ID wünschen, bei der der Umsatz nicht null ist? Weil 4 für 87 nur dann ist, wenn Sie diese Tabelle unterteilen, sonst wäre es 9 (von oben gezählt). –

+0

Ja, das ist richtig. Ich habe noch nicht komplett herausgefunden, aber mit plyr und ggplot habe ich Visionen, an ID-Untergruppen zu arbeiten, um durchschnittliche Wachstumsraten effizient zu berechnen und zu zeigen. – user1100825

Antwort

6

Würden diese Hilfe:

tapply(df$Sales, df$ID, function(a)head(which(a>0),1)) 

wo df Datenrahmen oben ist?

Wenn Sie die gesamte Zeile & nicht nur den Index wollen, könnte dies helfen:

lapply(unique(df$ID),function(a) head(subset(df,ID==a & Sales>0),1)) 
+0

Ich habe Ihre hartcodierten Indizes (2, 3) mit den Spaltennamen (ID, Sales) bearbeitet und ersetzt. Die Verwendung von Indizes ist weniger robust. (Stellen Sie sich vor, die Daten stammen aus einer Datei und jemand entscheidet sich, eine Spalte einzufügen). – flodel

+0

Jetzt ist das ziemlich nah an @ digEmAll's Antwort. Der einzige Unterschied besteht darin, dass Sie mit 'Kopf' eine Liste erhalten, wenn eine ID keinen Verkaufswert ungleich null hat, während er immer noch einen Vektor erhält, aber mit 'NA'. – flodel

+0

Danke eine Tonne @flodel. Ich denke, wir haben fast gleichzeitig geantwortet ... :-) Vielen Dank für die Änderungen. Ich sollte vorsichtiger sein, wenn ich von meinen Versuchen an der R-Konsole kopiere. –

3

Hier ist eine mögliche Lösung:

res1 <- tapply(df$Sales,INDEX=df$ID,FUN=function(x) which(x > 0)[1]) 

> res1 
54 87 95 
1 4 2 

Wo res einen numerischen Vektor mit ist:

> names(res) 
[1] "54" "87" "95" 

Wenn Sie die Indizes der Zeile in der ursprünglichen data.frame erhalten möchten und nicht In den Teilmengen können Sie Folgendes tun:

res2 <- tapply(1:nrow(df), 
       INDEX=df$ID,FUN=function(idxs) idxs[df[idxs,'Sales'] > 0][1]) 

> res2 
54 87 95 
1 9 15 

Dann nutzen Sie einfach die Indizes in res2, die data.frame der Teilmenge:

df2 <- df[res2,] 

> df2 
CalendarMonth ID  Sales 
    8/1/2008  54  6692.603 
10/1/2008  87 18617.942 
    8/1/2008  95  8015.956 
+0

Danke. Das sieht vielversprechend aus! Ich werde es drehen. – user1100825

1

Aufbauend auf digEmAll Antwort, eine Lösung mit functional Programmierung (vielleicht etwas sauberer):

> res3 <- tapply(
    1:nrow(df) 
    , df$ID 
    , function(Idx) Idx[Position(function(x) df[x, "Sales"] > 0, Idx)] 
) 
> identical(res3, res2) 
[1] TRUE 
Verwandte Themen