2011-12-22 20 views
10

Funkcja podstawiania w R tworzy obiekt języka w postaci drzewa, które można analizować. Jak mogę utworzyć drzewo od zera używając listy lub by następnie przekazać ją do eval?Tworzenie drzewa wyrażeń w R

# substitute gives a tree representation of the expression 
a=1; b=2; 
e1 = substitute(a+2*b) 
eval(e1)  #gives 5 as expected 
e1   # is type language 
e1[[1]]  # this is `+` 
e1[[2]]  # this is 'a' type symbol 
e1[[3]]  # this is type language 
e1[[3]][[1]] # this is `*` etc.... 

Chciałbym wiedzieć, jak programowo można zrekonstruować obiekt e1. Idealnie utworzyć obiekt listy intricate z poprawnym obiektem w nich i może wywołać niektóre as.language na obiekcie list. Jednak to nie działa. Na przykład:

# how to construct the tree? 
eval(list(as.symbol('+'),1,1))    # does not return 2 
eval(as.expression(list(as.symbol('+'),1,1))) # does not return 2 

Jednym ze sposobów jest po prostu wygenerować ciąg „1 + 1”, a następnie analizować je, ale nie wydaje się elegancki do generowania ciągów analizować je ponownie, gdy masz drzewo na pierwszym miejscu !

eval(parse(text='1+1')) # does return 1, but not elegant if tree is 
         # large and already in memory 

Dzięki za pomoc!

Odpowiedz

6
> plus <- .Primitive("+") 
> plus 
function (e1, e2) .Primitive("+") 
> times=.Primitive("*") 
> eval(call("plus", b, call("times",2, b))) 
[1] 6 
> eval(call("plus", a, call("times",2, b))) 
[1] 5 
+1

jeszcze lepiej, więc mogę po prostu zrobić 'zadzwoń ('+' , e1, e2) 'połączyć 2 wyrażenie z plusem, idealnie! – tlamadon

7

Istnieje kilka sposobów programowania programowo wyrażeń R. Najwygodniejszym, jeśli działa w Twoim przypadku, to bquote:

> a = 1 
> bquote(.(a) + .(a)) 
1 + 1 

gdzie .() jest odwrotny cytat. To powinno działać praktycznie niczego, ale jeśli tak nie jest, istnieją sposoby, aby ręcznie skonstruować podstawowe cegiełki wyrażeń:

> as.symbol('f') 
f 
> as.call(list(quote(f), 1, 2)) 
f(1, 2) 
> as.call(list(as.symbol('{'), 1, 2)) 
{ 
    1 
    2 
} 
> 
+0

wielkie, 'as.call' było rzeczywiście to, co szukałem. Od 2 wyrażeń, jak połączyć je w trzeci i 'as.call (lista (as.symbol ('+'), e1, e2))' działa – tlamadon

Powiązane problemy