2

I'm trying to use the lazyeval package to create non-standard evaluation in R, but was confused about what's the difference between substitute and lazy.

df <- data.frame(col1 = runif(10), col2 = runif(10))
> df
         col1      col2
1  0.54959138 0.8926778
2  0.99857207 0.9649592
3  0.26451336 0.9243096
4  0.98755113 0.7155882
5  0.84257525 0.5918387
6  0.20692997 0.5875944
7  0.44383744 0.5839235
8  0.44014903 0.1006080
9  0.49835993 0.7637619
10 0.07162048 0.3155483

I first created a function to take a data frame and two column names and return a column that is the sum of the two columns. substitute and eval seem to work just fine.

SubSum <- function(data, x, y) {
  exp <- substitute(x+y)
  r <- eval(exp, data)

  return(cbind(data, data.frame(sum=r)))
}

> SubSum(df, col1, col2)
         col1      col2       sum
1  0.54959138 0.8926778 1.4422692
2  0.99857207 0.9649592 1.9635312
3  0.26451336 0.9243096 1.1888229
4  0.98755113 0.7155882 1.7031394
5  0.84257525 0.5918387 1.4344140
6  0.20692997 0.5875944 0.7945244
7  0.44383744 0.5839235 1.0277610
8  0.44014903 0.1006080 0.5407570
9  0.49835993 0.7637619 1.2621218
10 0.07162048 0.3155483 0.3871688

I then tried to create a function with lazy and lazy_eval, but it didn't work.

require(lazyeval)
LazySum <- function(data, x, y) {
  exp <- lazy(x+y)
  r <- lazy_eval(exp, data)

  return(cbind(data, data.frame(sum=r)))
}

> LazySum(df, col1, col2)
Error in eval(expr, envir, enclos) : object 'col1' not found

My current answer

After some trial and error, this snippet seems to work.

LazySum <- function(data, x, y) {
  exp <- interp(~x + y, x=lazy(x), y=lazy(y))
  r <- lazy_eval(exp, data)

  return(cbind(data, data.frame(sum=r)))
}

Basically I had to build the lazy expression myself using interp.

Jarod Meng
  • 281
  • 1
  • 3
  • 4

1 Answers1

1

You were pretty close. read ?lazy especially the examples to understand the changes I made to your code

require(lazyeval)
set.seed(357)
df <- data.frame(col1 = runif(10), col2 = runif(10))
LazySum <- function(data, sum=x+y) {
   exp <- lazy(sum) #giving lazy a named arguement
   r <- lazy_eval(exp, data)

   return(cbind(data, data.frame(sum=r)))
 }

LazySum(df, col1+col2)
infominer
  • 1,981
  • 13
  • 17
  • 1
    Also, `lazyeval`'s vignette explains the differences between `lazy` and `substitute`: http://cran.r-project.org/web/packages/lazyeval/vignettes/lazyeval.html – sebpardo May 01 '15 at 05:02
  • thanks for adding the link, was just about to link to it – infominer May 01 '15 at 05:03
  • Thanks, but unfortunately this isn't what I was aiming for. I think user supplying `col1 + col2` is redundant and unsafe. The function is already named "LazySum". User shouldn't need to specify the action again. Also, if they supply something other than "+", it would still evaluate and create confusion. So I was looking for a function which takes two columns as separate arguments and returns the sum using `lazy` and `lazy_eval`. – Jarod Meng May 01 '15 at 05:14