In R, Evaluate Expressions Within Vector of Strings

In R, evaluate expressions within vector of strings

Just apply the whole function.

sapply(foo, function(x) eval(parse(text=x)))

Evaluate expression given as a string

The eval() function evaluates an expression, but "5+5" is a string, not an expression. Use parse() with text=<string> to change the string into an expression:

> eval(parse(text="5+5"))
[1] 10
> class("5+5")
[1] "character"
> class(parse(text="5+5"))
[1] "expression"

Calling eval() invokes many behaviours, some are not immediately obvious:

> class(eval(parse(text="5+5")))
[1] "numeric"
> class(eval(parse(text="gray")))
[1] "function"
> class(eval(parse(text="blue")))
Error in eval(expr, envir, enclos) : object 'blue' not found

See also tryCatch.

R: How to go from a vector of strings to a vector of quotes / names?

List apply as.symbol() to your input vector.

lapply(X = input, as.symbol)

How to correctly evaluate a literal character vector

You have to use get to get an object with the given name.

eval(parse(text = get(paste0(question_stem, "_my_vector"))))
#[1] "Element 1" "Element 2" "Element 3" "Element 4

eval(parse(text=x)) inside a function, how to evaluate in global environment?

eval has an argument, envir, that allows you to specify the environment in which you want to evaluate your expression. So,

eval(parse(text=command[i]), envir=.GlobalEnv)

should hopefully work.

Evaluate an expression given as a string inside substitute()

parse() returns an expression, which is essentially a list of language objects marked as a different type. You want to put a language object into the title, so I think this is what you want:

plot(0~1, xlab = substitute("My"~ind, list(ind = parse(text = mystrng)[[1]])))

That gives this as the x label:

Sample Image

This won't work if mystrng isn't legal R syntax, so "My index[1]" will need some preprocessing to convert it to something legal like "My~index[1]"

R sometimes fails to evaluate expressions parsed from strings

The issue is that glm stores the name of the variable used to reference the data, and stepAIC then attempts to retrieve this name and evaluate it to access the data, but gets confused about which environment the variable was defined in. To demonstrate, I'm going to simplify your code to

mdl <- str2lang(modelfiller("y", 2, "x", "lag"))      # This is your y~x+lag01+lag02
dfn <- df %>% tidyr::nest( data = c(-group) ) # First step of your %>% chain
glms <- purrr::map( dfn$data, ~glm(data = .x, mdl) ) # Construct the models

# Examine glms to observe that
# Call: glm(formula = mdl, data = .x) <--- glm() remembers that the data is in .x

# but stepAIC is not properly aware of where .x
# is defined and behaves effectively as
MASS::stepAIC( glms[[1]] ) # Error: object '.x' not found

Option 1

One workaround is to manually construct the expression that contains the data and then evaluate it:

glm2 <- function(.df, ...) {
eval(rlang::expr(glm(!!rlang::enexpr(.df),!!!list(...)))) }

glms2 <- purrr::map( dfn$data, ~glm2(data = .x, mdl) ) # Same as above, but with glm2
MASS::stepAIC( glms2[[1]] ) # Now works

Changing glm to glm2 in your problematic spot makes your code work too. The down side is that the Call: then remembers the entire data frame, which can be problematic if they are very large.

Option 2

Another alternative is to replace the purrr call with a for loop, which helps maintain the calling frames assumed by stepAIC, thus guiding it to where the data is defined

# This fails with Error: object '.x' not found
purrr::map( dfn$data, ~MASS::stepAIC(glm(data=.x, mdl), direction="both") )

# This works
for( mydata in dfn$data )
MASS::stepAIC(glm(data=mydata, mdl), direction="both")

The advantage here is not needing to store the entire data frame inside the call. The disadvantage is that you effectively lose access to what purrr does to streamline the code.

Evaluating mathematical expression in R

You can evaluate the string within your data.table 's environment. As a quick example:

#parse the text first
express <- parse(text = 'A+(B*C)/D')

#dummy data
library(data.table)
dt <- data.table(A = runif(5),
B = runif(5),
C = runif(5),
D = runif(5))

#using eval
eval(express, envir = dt)
#[1] 0.2654480 0.6818451 0.7611150 5.5714248 2.8076066


Related Topics



Leave a reply



Submit