2013-07-03 10 views
12

La mia domanda riguarda la creazione di una variabile che dipende da altre colonne all'interno di un data.table quando nessuno dei nomi delle variabili è noto in anticipo.data.table: modo corretto di creare una variabile condizionale quando i nomi delle colonne non sono noti?

Di seguito è riportato un esempio di giocattolo in cui sono presenti 5 righe e la nuova variabile deve essere 1 quando la condizione è uguale a A e 4 in modo elastico.

library(data.table) 
DT <- data.table(Con = c("A","A","B","A","B"), 
       Eval_A = rep(1,5), 
       Eval_B = rep(4,5)) 
Col1 <- "Con" 
Col2 <- "Eval_A" 
Col3 <- "Eval_B" 
Col4 <- "Ans" 

Il codice seguente funziona ma mi sembra di utilizzare male il pacchetto!

DT[,Col4:=ifelse(DT[[Col1]]=="A", 
       DT[[Col2]], 
       DT[[Col3]]),with=FALSE] 

Update: Grazie, ho fatto qualche rapida tempistica delle risposte qui sotto. Una volta su un data.table con 5 milioni di righe e solo le colonne rilevanti e di nuovo dopo l'aggiunta di 10 colonne non rilevanti, di seguito i risultati:

+-------------------------+---------------------+------------------+ 
|   Method   | Only relevant cols. | With extra cols. | 
+-------------------------+---------------------+------------------+ 
| List method    | 1.8     | 1.91    | 
| Grothendieck - get/if | 26.79    | 30.04   | 
| Grothendieck - get/join | 0.48    | 1.56    | 
| Grothendieck - .SDCols | 0.38    | 0.79    | 
| agstudy - Substitute | 2.03    | 1.9    | 
+-------------------------+---------------------+------------------+ 

Look come .SDCols è la cosa migliore per la velocità e l'utilizzo di sostituto di facile leggi il codice

risposta

11

1. get/se Prova utilizzando get:

DT[, (Col4) := if (get(Col1) == "A") get(Col2) else get(Col3), by = 1:nrow(DT)] 

2. get/unirsi o provare questo approccio:

setkeyv(DT, Col1) 
DT[, (Col4):=get(Col3)]["A", (Col4):=get(Col2)] 

3. .SDCols o questo:

setkeyv(DT, Col1) 
DT[, (Col4):=.SD, .SDcols = Col3]["A", (Col4):=.SD, .SDcols = Col2] 

AGGIORNAMENTO: sono stati aggiunti alcuni approcci aggiuntivi.

+2

Nella prima risposta, che dovrebbe essere 'Col4: =' o 'c (" Col4 "): ='. – Arun

+1

'data.table' in genere non è impostato per prendere una variabile di carattere che si riferisce a una colonna, ma penso che get sia l'approccio migliore che funziona. –

+1

@Arun, 'Col4: =' e 'c (" Col4 "): =' entrambi danno letteralmente 'Col4' come nome della colonna ma il nome della colonna desiderata è' Ans', non 'Col4'. –

5

Utilizzando ifelse e get:

DT[, (Col4) := ifelse (get(Col1) == "A",get(Col2) , get(Col3))] 

o utilizzando substitute per creare l'espressione in questo modo:

expr <- substitute(a4 := ifelse (a1 == "A",a2 , a3), 
        list(a1=as.name(Col1), 
         a2=as.name(Col2), 
         a3=as.name(Col3), 
         a4=as.name(Col4))) 

DT[, eval(expr)] 
Problemi correlati