Passing a column name to a function

I have a data frame with many columns. I want to pass the column names to a function, but the function doesn't seem to recognize the string being passed.
Here's a trivial example:

library(ggplot2)
df <- 
data.frame("Age" = c(21,15, 28, 27, 30), "x" = runif(5), "y"=runif(5),  "z" = runif(5))

function foo(xvar) {
    ggplot(data = df, x = df$xvar, y = df$Age) + geom_point() + labs(x="xvar")
}

foo(x)
foo(y)
foo(z)

I get an error message like:

Unknown or uninitialized column: `xvar`.        

What can fix this?
Thanks!
Andrew

You define a function in R with

x <- function(y) {}

Then, your argument is not the object you're using in the following lines. Moreover, your ggplot is not well formatted. ...

I was just trying to give a simple example. My actual code (yes, it's R) is way more complex. Look closely: I defined the function properly.

I asked what I thought would be a straightforward question and you give me crap for it.

Hi mercator88, and welcome!

There's a few approaches you can take here. For the most current, in order to quote and evaluate a variable within aes(), you have to use tidy evaluation. Here
the use of the double curly brackets ("curly-curly") is the most straightforward.
Some examples can be found at: https://www.tidyverse.org/blog/2019/06/rlang-0-4-0/

library("ggplot2")
library("rlang")

df <- data.frame("Age" = c(21,15, 28, 27, 30), "x" = runif(5), "y"=runif(5), 
"z" = runif(5))

foo <- function(xvar) {
  ggplot(data = df, aes(x = {{xvar}}, y = Age)) +
    geom_point()
  }

foo(x)

foo(y)

foo(z)

Created on 2020-07-23 by the reprex package (v0.3.0)

2 Likes

Because that's what forums like this are for. To help people... I think you're in the wrong language.

@mercator88, just in case you don't notice it among the unhelpful posts I can confirm that the answer from @jrmuirhead above is spot on.

You should include df as an argument, otherwise you're getting trouble some day in the future.

Thanks so much! I've been using R for 4 weeks after writing SAS code for eons. There's a steep learning curve, and I'm glad you were kind enough to provide me with the answer.

You're welcome! It's certainly challenging to starting thinking in a new programming language, even when having experience in another with different structures and syntax. R definitely has its quirks and associated steep learning curve. If the above answer works for you, would you be able to mark it as a solution so that others can read that it solves your question?

Done. Thanks!

What about if I was passing a string argument?
Example:
f <- function (xvar) {ggplot(df, aes(x=x, y=y)) + geom_point() + labs(x=xvar) }
f("Age")

Another but slightly different example:
library(gmodels)
f <- function(xvar) { CrossTable(data = df, x=xvar, y = "z", digits = 3) }
f("Age")

For the first example, I'll change it slightly because labs() doesn't need to evaluate xvar within df, but aes() does.

library("ggplot2")
library("rlang")

df  <- data.frame("Age" = c(21,15, 28, 27, 30), "x" = runif(5),
  "y"=runif(5), "z" = runif(5))


f <- function (xvar) {
  xsym <- ensym(xvar) #Convert the string into a symbol
  
  ggplot(data = df, aes(x = {{xsym}}, y = y)) +
    geom_point() +
    labs(x = xvar)
}

f("Age")

In your second example, CrossTable needs the vectors x and y to be passed as arguments.

There's a couple of ways to do this. The first, in just base R, you can extract
a column from a data.frame by passing the column name as a string.

library(gmodels)

f1 <- function(mydf, xvar, yvar) {
  x <- mydf[[xvar]]
  y <- mydf[[yvar]]
  
  CrossTable(x=x, y = y, digits = 3)
}

In a second rlang approach, you can extract the column from the data.frame
by evaluating the column name within the environment of the data.frame.

f2 <- function(mydf, xvar, yvar) {
  xsym <- ensym(xvar)
  ysym <- ensym(yvar)
  
  x <- rlang::eval_tidy(xsym, data = mydf)
  y <- rlang::eval_tidy(ysym, data = mydf)

  CrossTable(x = x, y = y, digits = 3)
}

f1(mydf = df, xvar = "Age", yvar = "z")
f2(mydf = df, xvar = "Age", yvar = "z")

There's a tidy evaluation with rlang cheat sheet at RStudio Cheatsheets - RStudio
which I've found useful.

1 Like

Jim,

Thank you very much! It worked.
My problem is that coming from (ugh) SAS where arguments can be used inside a macro either within quotes or by itself, R seems quite unfamiliar.
I greatly appreciate the time you took to answer my questions.

Andrew

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.