2015-05-14 6 views
7

Ich versuche eine effizientere Möglichkeit zu finden, inkrementelle Zählung eindeutiger Datenpunkte in einem Datenrahmen zu erreichen.Effizienter Weg, einzelne Datenpunkte im Datenrahmen inkrementell zu zählen

Zum Beispiel habe ich folgenden Code geschrieben:

df = matrix(c(1,2,3,3,4,5,1,2,4,4)) 

count = matrix(nrow = nrow(df),ncol=1) 

for (i in 1:nrow(df)) { 

    count[i,1] = length(which(df[1:i,1] == df[i,1])) 

} 

Der Zweck des Codes ist, um schrittweise jede Instanz eines spezifischen Wert zu zählen, z.B. die Zählung Spalte wird folgendes Ergebnis haben:

1,1,1,2,1,1,2,2,2,3. 

Der Code, den ich geschrieben habe, so weit hat den Zweck erfüllt, aber die Probe df über nur 10 Werte enthält. Der reale Datenrahmen, an dem ich diese Funktion ausführen möchte, enthält 52,118 values, was sehr viel Zeit in Anspruch nimmt.

Kennt jemand eine effizientere Möglichkeit, den obigen Code auszuführen?

Antwort

9

data.table Lösung

library(data.table) 
set.seed(20) 
dat <-data.frame(values = sample(1:3, 50000, replace=TRUE)) 
setDT(dat)[,runningCount:=1:.N,values] 

     values runningCount 
    1:  3   1 
    2:  3   2 
    3:  1   1 
    4:  2   1 
    5:  3   3 
    ---      
49996:  1  16674 
49997:  2  16516 
49998:  2  16517 
49999:  2  16518 
50000:  2  16519 
+0

Vielen Dank für all das Feedback jeder! Ich versuche die Methoden "data.table" und "dplyr" zu implementieren, da sie für mich am sinnvollsten sind. Trotzdem bekomme ich einen Fehler, der besagt, dass die "setDT" -Funktion bei Verwendung der "data.table" -Methode nicht gefunden wurde. Warum das? –

+0

Welche Version von data.table verwenden Sie? Siehe hier: http://stackoverflow.com/questions/20345022/convert-a-data-frame-to-a-data-table-without-copy. Außerdem sollte das Argument 'x' für 'setDT' eine 'list', 'dat.frame' oder 'data.table' sein. – user227710

+0

Mein Dataset ist ein data.frame, das ist also in Ordnung. Die Version von data.table, die ich habe, ist 1.9.4. Ich habe es gerade heruntergeladen wie vor 20 Minuten. –

6

Hier ist eine schnelle Annäherung mit dem dplyr Paket:

library(dplyr) 

# Fake data 
set.seed(20) 
dat = data.frame(values = sample(1:3, 50000, replace=TRUE)) 

dat %>% group_by(values) %>% 
    mutate(runningCount = 1:n()) 

    values runningCount 
1  2   1 
2  3   1 
3  1   1 
4  3   2 
5  1   2 
6  3   3 
7  3   4 
.. ...   ... 

Timing (in Millisekunden):

 min  lq  mean median  uq  max neval 
2.003755 2.134762 2.198161 2.186214 2.231662 3.665328 100 

Timings für alle bisher Antworten (die Daten unter Verwendung von I erstellt):

   median 
     dplyr: 2.11 
    data.table: 1.24 
lapply/Reduce: 11.61 
      ave: 9.93 

So ist data.table der schnellste.

6

Eine Basis R Ansatz:

Reduce(`+`,lapply(unique(c(df)), function(u){b=c(df)==u;b[b==T]=cumsum(b[b==T]);b})) 
#[1] 1 1 1 2 1 1 2 2 2 3 
Verwandte Themen