2015-07-29 8 views
9

stelle ich mir ein R expression Objekt durch Verkettung erzeugen:Wie komprimiere/füge ich Expression-Objekte in R zusammen?

x = c(expression({ 
     a + b 
     b + c 
     }), 
     expression({ 
     a + 1 
     b + 1 
     })) 

Dies führt zu einer Länge-2-Expression Objekt:

> x 
expression({ 
    a + b 
    b + c 
}, { 
    a + 1 
    b + 1 
}) 

Wie kann ich umwandeln/collapse diese in einen einzelnen Ausdruck? Das heißt, ich bin für eine Operation der Suche ich auf x ausführen kann die äquivalent bekommen dies getan zu haben:

expression({ 
    a + b 
    b + c 
    a + 1 
    b + 1 
}) 
+0

'deparse', kombinieren Sie die Mitte, re'parse'? Das ist fast da: 'c_exp = function (x1, x2) parse (Text = c (Kopf (deparse (x1), -1), Schwanz (deparse (x2), -1))) ' – Gregor

+0

@nongkrong' as. Ausdruck (Liste (x [[1]] [[2]], x [[2]] [[2]])) sieht vielversprechend aus, aber ich brauche eine allgemeine Lösung, die nicht interessiert, wie viele Zeilen in der einzelne Ausdrücke oder wie viele Ausdrücke beteiligt sind. Obwohl ich wahrscheinlich auf Ihren Ansatz aufbauen kann. – cboettig

+0

@cboettig - Sie wissen, dass Sie in Ihrem Update nur das Ergebnis von 'b + 1' erhalten, wenn Sie den Ausdruck auswerten? –

Antwort

3
x = c(expression({ 
    a + b 
    b + c 
    }), 
    expression({ 
    a + 1 
    b + 1 
    })) 

collapsit = function(x) { 
    if(!all(sapply(x, class) == "{")) 
     stop("I can't collapse non-bracket expressions for you, dawg") 

    stuff = unlist(lapply(x[-1], function(y) as.list(y[-1]))) 
    x[[1]][length(x[[1]])+1:length(stuff)] = stuff 
    x[1] 
} 

res = collapsit(x) 
## expression({ 
##  a + b 
##  b + c 
##  a + 1 
##  b + 1 
## }) 
2

Dies erzeugt die gewünschten Ergebnisse, und wahrscheinlich skaliert werden könnte mehr Eingänge mit reduce zu nehmen oder sowas. Das heißt, ich bin mir nicht sicher, wie gut einer Lösung dies ist, wie ich oft Ausdrücke nicht verwende.

c_exp = function(x1, x2) { 
    parse(text = c("{", 
        tail(head(deparse(x1), -1), -1), 
        head(tail(deparse(x2), -1), -1), 
        "}")) 
} 

x1 = expression({a+b}) 
x2 = expression({a + 1}) 
c_exp(x1, x2) 
# expression({ 
#  a + b 
#  a + 1 
# }) 
4

Dies scheint zu funktionieren soll, jeder Ausdruck mit Start {

as.expression(sapply(x, function(y) as.list(y[-1]))) 
# expression(a + b, b + c, a + 1, b + 1) 
+0

Schön! Ich hatte das gerade mit 'lapply' anstelle von' sapply' versucht und dann aufgegeben. @Hadley erwähnt, dass ich nur auf "Call" mit "y [-1]" in http://adv-r.had.co.nz/Expressions.html gekommen bin, aber ich konnte die resultierenden Listen nicht reduzieren. schöne Arbeit – cboettig

+0

aber dies gibt einen Ausdruck der Länge 4, während die gewünschte Ausgabe in einen Ausdruck kollabieren sollte, richtig? Auch wenn Sie dies mit meinem 'x' Beispiel versuchen, verwirrte es den letzten Ausdruck und teilt das' x + y' in 'x' und' y' auf und ergibt eine Länge von 6 – rawr

+0

@raw ja, wie es heißt, der Unterausdrücke sollten mit '{' beginnen, Sie müssen den letzten Ausdruck korrigieren – jenesaisquoi

3

Dies als im x + y Ausdruck in Klammern sind nicht jeden Ausdruck erfordern:

x = c(expression({ 
    a + b 
    b + c 
    }), 
expression({ 
    a + 1 
    b + 1 
    }), 
expression(x + y)) 

# expression({ 
# a + b 
# b + c 
# }, { 
# a + 1 
# b + 1 
# }, x + y) 

s <- strsplit(paste0(as.character(x), collapse = ''), '[\n{}]')[[1]] 
x <- paste0(Filter(nzchar, gsub('^\\s+|\\s+$','', s)), collapse = '\n') 
parse(text = sprintf('{\n%s\n}', x)) 

# expression({ 
# a + b 
# b + c 
# a + 1 
# b + 1 
# x + y 
# }) 
+0

Das ist doch ein wunsch einer lösung! Es passt mir die Rechnung, obwohl es scheint, dass man in der Lage sein sollte, dies ohne direkte String-Manipulation zu tun (was mich nervös macht); z.B. mit den 'Call'-Objekten http://adv-r.had.co.nz/Expressions.html aber ich kann nicht ganz sehen, wie. – cboettig