Search code examples
rdataframeeval

Can eval be called within a data frame with variables defined in that data frame?


Consider:

quotes<-alist(x, x+1, x+2)
data.frame(x=c(5, 10, 15), lapply(quotes, eval))

This does not work because eval cannot find x. Is there any way to get eval to recognize the variables that were defined in the data frame? I know that I could assign the data frame to some variables and then build it up with functions like transform, but I'm looking to do all of this within my call to data.frame.

For a possible version of the intended outputs, we can use this:

quotes<-alist(x, x+1, x+2)
x=c(5, 10, 15)
data.frame(x, lapply(quotes, eval))

Solution

  • Have you noticed that the simpler call data.frame(x, y = x) wouldn't work either ?

    data.frame() uses standard evaluation so in your case they'll be evaluated in the global environment.

    If you name your quotes elements you'll be able to do tibble(x, !!!quotes) though, because tibble works differently.

    Technically the following might be acceptable to you, we cheat by creating a temp value in the global environment, which we then remove on exit.

    (I use evalq only to be able to use on.exit)

    quotes<-alist(x, x+1, x+2)
    
    df <- data.frame(
      x = c(5, 10, 15) ->> .t.e.m.p., 
      evalq({
        on.exit(rm(.t.e.m.p., envir = .GlobalEnv))
        lapply(quotes, eval, list(x= .t.e.m.p.))
      }))
    
    df
    #>    x c.5..10..15. c.6..11..16. c.7..12..17.
    #> 1  5            5            6            7
    #> 2 10           10           11           12
    #> 3 15           15           16           17
    
    ls(all.names = TRUE)
    #> [1] "df"     "quotes"
    

    Created on 2021-05-11 by the reprex package (v0.3.0)

    This looks of course horrible, and using transform, within or tibble is probably a wiser choice.