2015-02-04 39 views
9

Mam następujący data.table:oceny ekspresji w R data.table

> dt = data.table(expr = c("a + b", "a - b", "a * b", "a/b"), a = c(1,2,3,4), b = c(5,6,7,8)) 
> dt 
    expr a b 
1: a + b 1 5 
2: a - b 2 6 
3: a * b 3 7 
4: a/b 4 8 

Moim celem jest uzyskanie następujących data.table:

> dt 
    expr a b ans 
1: a + b 1 5 6 
2: a - b 2 6 -4 
3: a * b 3 7 21 
4: a/b 4 8 0.5 

Próbowałem następujące:

> dt[, ans := eval(expr)] 
Error in eval(expr, envir, enclos) : object 'expr' not found 

> dt[, ans := eval(parse(text = expr))] 
Error in parse(text = expr) : object 'expr' not found 

Każdy pomysł, jak obliczyć kolumnę ans na podstawie wyrażenia z expr kolumny?

Odpowiedz

12

Jeśli rzeczywisty wyrażenia opisują wywołań funkcji vectorized i są powtarzane wiele razy, każdy może to być bardziej efektywne, ponieważ tylko analizuje i ocenia każdy odrębny wyraz raz:

f <- function(e, .SD) eval(parse(text=e[1]), envir=.SD) 
dt[, ans:=f(expr,.SD), by=expr, .SDcols=c("a", "b")] 
#  expr a b ans 
# 1: a + b 1 5 6.0 
# 2: a - b 2 6 -4.0 
# 3: a * b 3 7 21.0 
# 4: a/b 4 8 0.5 
6

Naprawdę, istnieje szereg wyzwań związanych z wektoryzacją w takiej konfiguracji. eval nie oczekuje uruchomienia na wektorze wyrażeń, ani nie jest domyślnie skonfigurowany do iteracji po wektorze środowisk. Tu zdefiniować funkcję pomocnika do zawijania wiele iteracji

calc <- function(e, ...) { 
    run<-function(x, ...) { 
     eval(parse(text=x), list(...)) 
    } 
    do.call("mapply", c(list(run, e), list(...))) 
} 

dt[, ans:=calc(expr,a=a,b=b)] 

która zwraca

expr a b ans 
1: a + b 1 5 6.0 
2: a - b 2 6 -4.0 
3: a * b 3 7 21.0 
4: a/b 4 8 0.5 

jako pożądane. Zauważ, że będziesz musiał nazwać parametry w wywołaniu calc(), aby wiedział, która kolumna będzie mapować do której zmiennej.

+0

programowania funkcyjnego FTW, duży + 1 –