Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I collapse/merge expression objects in R?

Tags:

r

Imagine I generate an R expression object by concatenation:

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

This results in a length-2 expression object:

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

How can I transform/collapse this into a single expression? That is, I'm looking for an operation I can perform on x to get the equivalent of having done this:

expression({
    a + b
    b + c
    a + 1
    b + 1
})
like image 873
cboettig Avatar asked Jul 29 '15 23:07

cboettig


4 Answers

This seems to work, each expression should start with {

as.expression(sapply(x, function(y) as.list(y[-1])))
# expression(a + b, b + c, a + 1, b + 1)
like image 110
Rorschach Avatar answered Nov 12 '22 11:11

Rorschach


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
## })
like image 26
Gabe Becker Avatar answered Nov 12 '22 11:11

Gabe Becker


This doesn't require each expression to be in brackets as in the x + y expression:

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
# })
like image 40
rawr Avatar answered Nov 12 '22 12:11

rawr


This produces the desired results, and could probably be scaled up to take more inputs with reduce or somesuch. That said, I'm not sure how good of a solution this is as I don't often make use of expressions.

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
# })
like image 2
Gregor Thomas Avatar answered Nov 12 '22 11:11

Gregor Thomas