2010-07-15 14 views
7

Vorrei utilizzare il pacchetto data.table in R per generare dinamicamente aggregazioni, ma sto correndo in un errore. Sotto, lasciare che my.dt sia di tipo data.table.data.table e "da valutare per elencare" Errore

sex <- c("M","F","M","F") 
age <- c(19, 23, 26, 21) 
dependent.variable <- c(1400, 1500, 1250, 1100) 
my.dt <- data.table(sex, age, dependent.variable) 
grouping.vars <- c("sex", "age") 
for (i in 1:2) { 
    my.dt[,sum(dependent.variable), by=grouping.vars[i]] 
} 

Se corro questo, ottengo errori:

Error in `[.data.table`(my.dt, , sum(dependent.variable), by = grouping.vars[i] : 
    by must evaluate to list 

Eppure le seguenti opere senza errori:

my.dt[,sum(dependent.variable), by=sex] 

vedo il motivo per cui si verifica l'errore, ma non vedo come utilizzare un vettore con il parametro by.

+0

si hanno due "grouping.vars", ma sono l'iterazione tra 1: 5. Mi manca qualcosa lì? – Shane

+1

Inoltre, nel tuo esempio di lavoro, il sesso è un oggetto, mentre nella versione in mancanza è un personaggio. – Shane

+0

Ehi Shane, mi dispiace, l'ho risolto. Dovrebbe essere 2 non 5. Questo è ciò che non mi è chiaro, sembra che il sesso sia un oggetto (??). –

risposta

4

Ho fatto due modifiche al codice originale:

sex <- c("M","F","M","F") 
age <- c(19, 23, 26, 21) 

age<-as.factor(age) 

dependent.variable <- c(1400, 1500, 1250, 1100) 
my.dt <- data.table(sex, age, dependent.variable) 

for (a in 1:2){ 
print(my.dt[,sum(dependent.variable), by=list(sex,age)[a]]) 
} 

numerica vettore age dovrebbero essere costretti in fattori. Per quanto riguarda il parametro by, non utilizzare la virgolette per i nomi delle colonne ma raggrupparle nell'elenco (...). Almeno questo è ciò che l'autore ha suggerito.

+0

Questo è interessante, e il design dietro il "con" sembra un po 'counterintuitiv, ma il vostro codice funziona per lo più. solo un piccolo problema (minore, e facile da risolvere con nomi solo assegnando nel loop), i nomi delle colonne non vengono aggiornati. Per sesso variabile, i nomi sono: il sesso V1 Per l'età variabile, i nomi sono: il sesso V1 –

5

[UPDATE] 2 anni dopo la questione è stato chiesto ...

Sulla esecuzione del codice nella questione, data.table è ora più utile e restituisce questo (utilizzando 1.8.2):

Error in `[.data.table`(my.dt, , sum(dependent.variable), by = grouping.vars[i]) : 
    'by' appears to evaluate to column names but isn't c() or key(). Use by=list(...) 
    if you can. Otherwise, by=eval(grouping.vars[i]) should work. This is for efficiency 
    so data.table can detect which columns are needed. 

e seguendo i consigli nella seconda frase di errore:

my.dt[,sum(dependent.variable), by=eval(grouping.vars[i])] 
    sex V1 
1: M 2650 
2: F 2600 



Vecchio risposta da Lug 2010 (by può ora essere double e character, però):

A rigor di termini le by necessità di valutare a un elenco di vettori ciascuno con modalità di archiviazione intero, però. Pertanto, il vettore numerico age potrebbe essere convertito in intero utilizzando as.integer(). Questo perché data.table utilizza l'ordinamento digitale (molto veloce) ma l'algoritmo radix è specifico per gli interi solo (vedere la voce di wikipedia per 'ordinare radix'). La memorizzazione di interi per colonne chiave e ad hoc by è uno dei motivi per cui data.table è veloce. Un fattore è ovviamente una ricerca di interi per stringhe univoche.

L'idea dietro by è una list() di espressioni è che non si è limitato ai nomi di colonna. È normale scrivere espressioni di nomi di colonne direttamente nello by. Un comune è quello di aggregare per mese; ad esempio:

DT[,sum(col1), by=list(region,month(datecol))] 

o un modo molto veloce per il raggruppamento annoMese è quello di utilizzare un data base non epoca, come yyyymmddL come visto in alcuni degli esempi nel pacchetto, in questo modo:

DT[,sum(col1), by=list(region,month=datecol%/%100L)] 

Nota come puoi nominare le colonne all'interno della lista() in questo modo.

di definire e riutilizzare complesse espressioni di raggruppamento:

e = quote(list(region,month(datecol))) 
DT[,sum(col1),by=eval(e)] 
DT[,sum(col2*col3/col4),by=eval(e)] 

O se non si vuole rivalutare le by espressioni di volta in volta, è possibile salvare il risultato una volta e riutilizzare il risultato per l'efficienza; se le espressioni by stessi impiegano molto tempo per calcolare/allocare, o avete bisogno di riutilizzare molte volte:

byval = DT[,list(region,month(datecol))] 
DT[,sum(col1),by=byval] 
DT[,sum(col2*col3/col4),by=byval] 

Si prega di consultare http://datatable.r-forge.r-project.org/ per le informazioni più recenti e lo stato. Presto ci sarà una nuova presentazione e speriamo di rilasciare presto anche la versione 1.5 di CRAN. Questo contiene diverse correzioni di bug e nuove funzionalità dettagliate nel file NEWS. La lista di aiuto datatable ha circa 30-40 post al mese che potrebbero essere di interesse.

Problemi correlati