2013-05-15 11 views
44

Si supponga Ho una tabella di dati contenente alcuni giocatori di baseball:sottoinsieme dal gruppo con data.table

library(plyr) 
library(data.table) 

bdt <- as.data.table(baseball) 

Per ogni giocatore (data dalla id), voglio trovare la riga corrispondente all'anno in cui ha giocato la maggior parte dei giochi. Questo è semplice in plyr:

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

Qual è il codice equivalente per data.table?

ho provato:

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 

questo funziona:

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

Ma è è solo il 30% più veloce rispetto plyr, suggerendo probabilmente non è idiomatica.

+2

Wow, questo è lento, ma se si utilizza "anno" al posto di ".SD" ... Sto ottenendo .01, 1.58, 2.39 tempo utente per anno, .SD, plyr, rispettivamente. – Frank

+0

@Frank ma voglio l'intero frame di dati, non solo l'anno. Chiarirò la domanda. – hadley

risposta

51

Ecco il digiuno data.table modo:

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

questo modo si evita la costruzione .SD, che è il collo di bottiglia nelle vostre espressioni.

edit: In realtà, la ragione principale del PO è lento non è solo che ha .SD in essa, ma il fatto che lo utilizza in modo particolare - chiamando [.data.table, che al momento ha un enorme sovraccarico, quindi eseguirlo in un ciclo (quando si fa un by) si accumula una penalità molto grande.

+4

+1 Scommetto che Hadley vuole farlo in modo alquanto programmatico, nel qual caso vorrebbe usare questa sintassi, 'bdt [bdt [, .I [g == max (g)], per = id] [, V1]] 'giusto? – joran

+0

@joran Sto costruendo la chiamata manualmente, quindi non importa davvero – hadley

+4

@hadley Chiaramente, non dovrei scommettere. :) – joran