2013-05-15 9 views
44

Angenommen ich eine Datentabelle enthalten, haben einige Baseball-Spieler:Subset von Gruppe mit data.table

library(plyr) 
library(data.table) 

bdt <- as.data.table(baseball) 

Für jeden Spieler (von id gegeben), möchte ich auf das Jahr um die Zeile finden entspricht, in dem sie spielte die meisten Spiele. Dies ist einfach in plyr:

ddply(baseball, "id", subset, g == max(g)) 

Was ist der entsprechende Code für data.table?

Ich habe versucht:

setkey(bdt, "id") 
bdt[g == max(g)] # only one row 
bdt[g == max(g), by = id] # Error: 'by' or 'keyby' is supplied but not j 
bdt[, .SD[g == max(g)]] # only one row 

Dies funktioniert:

bdt[, .SD[g == max(g)], by = id] 

Aber es ist nur 30% schneller als plyr ist, ist es wahrscheinlich nicht idiomatischen hindeutet.

+2

Wow, das ist langsam, aber wenn Sie "Jahr" anstelle von ".SD" verwenden ... Ich bekomme .01, 1.58, 2.39 Benutzer Zeit für das Jahr, .SD, plyr, jeweils. – Frank

+0

@Frank aber ich will den ganzen Datenrahmen, nicht nur das Jahr. Ich werde die Frage klären. – hadley

Antwort

51

Hier ist der schnelle data.table Weg:

bdt[bdt[, .I[g == max(g)], by = id]$V1] 

Dies vermeidet .SD Konstruktion, die der Engpass in Ihrer Ausdrücken ist.

edit: Eigentlich ist der Hauptgrund, warum die OP langsam sind, ist nicht nur, dass es .SD in ihm hat, aber die Tatsache, dass sie es in einer bestimmten Art und Weise verwendet - von [.data.table Aufruf, die zur Zeit ein riesigen hat Overhead, also läuft es in einer Schleife (wenn man eine by macht) akkumuliert eine sehr große Strafe.

+4

+1 Ich wette, dass Hadley das etwas programmatisch machen möchte, in diesem Fall würde er diese Syntax verwenden wollen, 'bdt [bdt [, .I [g == max (g)], by = id] [, V1]] richtig? – joran

+0

@joran Ich baue den Anruf manuell, also ist es eigentlich egal – hadley

+4

@hadley Natürlich sollte ich nicht wetten. :) – joran