Saren Tasciyan
Saren Tasciyan

Reputation: 483

Generating expression within a function and return it in R

I was trying to generate an expression in a separate function. To prevent repetitive code. The expression is then passed onto ggplot.

This works fine (a simple expression)

ggplot(mpg, aes(x = model, y = displ)) + geom_boxplot()

This works fine too (an expression with formula and string)

x = "displ"
xVar = expr(!!ensym(x) * 2)
ggplot(mpg, aes(x = model, y = !!xVar)) + geom_boxplot()

This doesn't work (an expression generated in a formula)

makeExpression = function(varName){
    return(expr(!!ensym(varName) * 2))
}
xVar = makeExpression(x)
ggplot(mpg, aes(x = model, y = !!xVar)) + geom_boxplot()

This works (an expression generated in a formula with a dirty hack)

makeExpression = function(varName){
    a = varName
    return(expr(!!ensym(varName) * 2))
}
xVar = makeExpression(x)
ggplot(mpg, aes(x = model, y = !!xVar)) + geom_boxplot()

The third example gives the following error: *Error in x * 2 : non-numeric argument to binary operator*

This means that "x", which was supplied to the function is not evaluated. x holds a string of a column name. The expression should have been: displ * 2

Funnily 4th example also works after accessing varName once within the function. Note that a is never used.

I don't understand why this is the case. It looks like a dirty hack to me but it probably has something to do with the scoping. Is there any cleaner way of doing this?

Upvotes: 0

Views: 67

Answers (1)

MrFlick
MrFlick

Reputation: 206167

If you want to pass a variable that contains a name as a character value, then you want to use sym rather than ensym. sym will evaluate the parameter to pass to it to get the value. ensym is meant only to be used in function to capture expressions passed to function. Note that this magic only works when the parameter is still in the "promise" state and hasn't been evaluated by any previous code in the function. This is why the 4th example "works" because that extra code forces the promise to be evaluated.

Upvotes: 1

Related Questions