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))
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.
In case you don't mind when x is created in .GlobalEnv, and potentially overwriting it, you can use <- inside data.frame.
quotes<-alist(x, x+1, x+2)
data.frame(x=x <- c(5, 10, 15), lapply(quotes, eval))
# 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
rm(x)
You can call it inside local but then x is not created in the .GlobalEnv and eval needs to be told to look in current environment.
local(data.frame(x=x <- c(5, 10, 15), lapply(quotes, eval, environment())))
# 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
It is also possible to assign the values to a different name but here eval needs a list with the name x. Note that in this case TMP would be first created or overwritten and if needed, afterwards removed with rm from the .GlobalEnv.
data.frame(x=TMP <- c(5, 10, 15), lapply(quotes, eval, list(x=TMP)))
# 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
rm(TMP)
Other (but not asked/wanted) possibilities might be using transform:
transform(data.frame(x=c(5, 10, 15)), y=lapply(quotes, eval, environment()))
# x y.c.5..10..15. y.c.6..11..16. y.c.7..12..17.
#1 5 5 6 7
#2 10 10 11 12
#3 15 15 16 17
within:
within(data.frame(x=c(5, 10, 15)), y <- lapply(quotes, eval, environment()))
# x y
#1 5 5, 10, 15
#2 10 6, 11, 16
#3 15 7, 12, 17
or tibble:
tibble::tibble(x=c(5, 10, 15), y=sapply(quotes, eval, environment()))
## A tibble: 3 x 2
# x y[,1] [,2] [,3]
# <dbl> <dbl> <dbl> <dbl>
#1 5 5 6 7
#2 10 10 11 12
#3 15 15 16 17
And finally (for reference) the intended output from the question:
x <- c(5, 10, 15)
data.frame(x, lapply(quotes, eval))
# 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
rm(x)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With