2016-07-28 7 views
3

Ich habe eine data.table und eine Liste von Formeln,eine Liste der Formeln R data.table Nehmen

DT <- data.table(A = c(1:3), B = c(3:1), C = c(4:6), D = (6:4)) 
l <- list(f1 = "A + B", f2 = "B + C", f3 = "C - D", f4 = "D/A") 

Dies kann durch

DT[, ":="(f1 = A + B, f2 = B + C, f3 = C - D, f4 = D/A)] 

oder

for (i in 1:length(l)) { 
    DT[, eval(names(l)[i]) := eval(parse(text=l[[i]]))] 
} 
erreicht werden

Gibt es eine Möglichkeit, dies unter Verwendung der Informationen in l ohne Verwendung von Schleife zu tun?

# some code 
DT 
# A B C D f1 f2 f3  f4 
# 1: 1 3 4 6 4 7 -2 6.000000 
# 2: 2 2 5 5 4 7 0 2.500000 
# 3: 3 1 6 4 4 7 2 1.333333 
+0

Was ist das Problem mit der Schleife hier? Nicht alle Schleifen sind schlecht. – dayne

+0

Ich möchte nur wissen, ob es eine Möglichkeit gibt, Schleife zu vermeiden ... –

+0

Sie können 'lapply' verwenden, um Schleifen über Spalten zu vermeiden, aber es ist nicht immer eine große Sache, nur eine Schleife zu verwenden, wie Dayne sagte. Erstens sollten Sie diese als Ausdrücke speichern, nicht als Text: 'L = lapply (l, function (x) parse (text = x))'. Dann etwas wie 'DT [, \': = \ '(Namen (L), Lapply (L, Eval, .SD))], das funktioniert, aber ich bin mir nicht sicher, ist koscher. – Frank

Antwort

10

Wenn Sie l von Hand bauen, es stattdessen schreiben wie

L = quote(`:=`(f1 = A + B, f2 = B + C, f3 = C - D, f4 = D/A)) 

Dann können Sie es wie

verwenden
DT[, eval(L)] 

# A B C D f1 f2 f3  f4 
# 1: 1 3 4 6 4 7 -2 6.000000 
# 2: 2 2 5 5 4 7 0 2.500000 
# 3: 3 1 6 4 4 7 2 1.333333 

Dies ist recommended practice from the FAQ, die ...

quote() und eval() sind wie Makros in anderen Sprachen erklärt.

+0

Ich möchte alle diese Formeln nach Gruppe auswerten, aber data.table erlaubt mir das nicht. Wie soll ich das machen? Vielen Dank im Voraus! –

+0

@ Nal-rA Möglicherweise müssen Sie eine neue Frage zur Klärung stellen. Wenn ich es versuche, funktioniert es für mich: 'DT [, id: = c (1,1,2)]' dann 'DT [, eval (L), durch = id] []' – Frank

+1

Danke! Es scheint, dass ich den falschen Weg benutze. Danke nochmal! –

2

Das ist super schlampig, aber Sie können einen Ausdruck mit call, parse und paste erstellen, rufen Sie dann diesen Ausdruck:

library(data.table) 
DT <- data.table(A = c(1:3), B = c(3:1), C = c(4:6), D = (6:4)) 
l <- list(f1 = "A + B", f2 = "B + C", f3 = "C - D", f4 = "D/A") 
ncall <- call(":=", names(l), 
      parse(text = paste0("list(", paste(l, collapse = ","), ")"))) 
DT[ , eval(ncall)] 
DT 
# A B C D f1 f2 f3   f4 
# 1: 1 3 4 6 4 7 -2 6.00000000 
# 2: 2 2 5 5 4 7 0 2.50000000 
# 3: 3 1 6 4 4 7 2 1.33333333 
+0

Kann Ihre Methode alle Formeln nach Gruppen auswerten? Vielen Dank! @dayne –

+0

Sie sollten in der Lage sein, einen "k" -Term und eine Bewertung nach Gruppe hinzuzufügen, z. 'DT [, eval (ncall), by = Liste (D)'. Ich habe das nicht explizit getestet, und dieses Beispiel macht keinen Sinn für die Gruppierung, aber Sie können sicherlich einen Code selbst testen. – dayne