2013-07-03 2 views
12

Meine Frage bezieht sich auf die Erstellung einer Variablen, die von anderen Spalten innerhalb einer data.table abhängt, wenn keiner der Variablennamen im Voraus bekannt ist.data.table: Richtige Methode zum Erstellen einer bedingten Variablen, wenn Spaltennamen nicht bekannt sind?

Unten ist ein Spielzeugbeispiel, wo ich 5 Reihen habe und die neue Variable sollte 1 sein, wenn die Bedingung A und 4 anders ist.

Der Code unten funktioniert, aber fühlt sich an, als ob ich das Paket missbrauche!

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

Update: Danke, ich habe einige schnelle Timing der folgenden Antworten. Einmal auf einer data.table mit 5.000.000 Zeilen und nur die relevanten Spalten und wieder nach 10 nicht relevanten Spalten hinzufügen, unten sind die Ergebnisse:

+-------------------------+---------------------+------------------+ 
|   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    | 
+-------------------------+---------------------+------------------+ 

Looks wie .SDCols ist am besten für die Geschwindigkeit und mit Ersatz für leicht zu Code lesen.

Antwort

11

1. get/wenn Versuchen get mit:

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

2. get/beitreten oder versuchen, diesen Ansatz:

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

3. .SDCols oder das:

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

UPDATE: Einige zusätzliche Ansätze hinzugefügt.

+2

In der ersten Antwort, sollte es 'Col4 sein: =' oder 'c (“ Col4 "): ='. – Arun

+1

'data.table' ist im Allgemeinen nicht eingerichtet, um eine Zeichenvariable zu übernehmen, die auf eine Spalte verweist - aber ich denke,' get' ist der beste Ansatz, der funktioniert. –

+1

@Arun, 'Col4: =' und 'c (" Col4 "): =' geben beide buchstäblich 'Col4' als den Spaltennamen, aber der gewünschte Spaltenname ist' Ans', nicht 'Col4'. –

5

Mit ifelse und get:

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

Oder substitute unter Verwendung des Ausdrucks wie folgt zu erstellen:

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)]