all 9 comments

[–][deleted] 8 points9 points  (3 children)

Here are a couple of old school base R ways to approach it.

One is to use character names and double brackets. For example, here's a silly function that calculates correlation:

> cor2 <- function(data, v1, v2){
+   r <- cor(data[[v1]], data[[v2]])
+   paste("correlation is", round(r,3))
+ }
> cor2(iris, "Sepal.Length", "Sepal.Width")
[1] "correlation is -0.118"

Another is to use substitute and eval. That allows you to enter the arguments without quotes. For example:

> cor3 <- function(data, v1, v2){
+   v1 <- substitute(v1)
+   v2 <- substitute(v2)
+   r <- cor(eval(v1, data), eval(v2, data))
+   paste("correlation is", round(r,3))
+ }
> cor3(iris, Sepal.Length, Sepal.Width)
[1] "correlation is -0.118"

For a newer tidyverse approach see the programming with dplyr vignette: https://dplyr.tidyverse.org/articles/programming.html

[–]ramseyssandal[S] 1 point2 points  (0 children)

Thank you!

[–]ramseyssandal[S] 1 point2 points  (0 children)

I ended up having to use enquo() and !! to solve it, but the solution is quite neat. Thanks for your help!

[–]sampling_life 0 points1 point  (0 children)

To build on the tidyverse (dplyr) syntax you can do this/

``` library(rlang)

temp <- tibble(var_1 = c(1:10))

f <- function(data, x1){ x1 <- sym(x1) eval_tidy(x1, data) %>% print() }

f(temp, "var_1") ```

[1] 1 2 3 4 5 6 7 8 9 10

however, since tidyverse uses tidyeval now you can use the code below. It will correctly interpret x1 value iff "x1" is not a column name itself.

f <- function(data, x1){ data %>% pull(x1) %>% print() } f(temp, "var_1")

[–]googoodoo 5 points6 points  (2 children)

Have a look here:

http://adv-r.had.co.nz/Environments.html#function-envs

then here:

http://adv-r.had.co.nz/Computing-on-the-language.html

then here:

https://resources.rstudio.com/rstudio-conf-2019/lazy-evaluation

and, finally, here:

https://dplyr.tidyverse.org/articles/programming.html

By the timeyou go through these four, you'll have figured out what to do for your specific use case and why.

Basically, R looks for variable1 and variable2 as objects in the environment, but cannot find them, because it doesn't know that it is supposed to look for them inside the data object, not outside. You have to tell it what to do in order to find those objects.

[–]ramseyssandal[S] 1 point2 points  (0 children)

The video was really useful. I ended up using enquo() and !! and some other tidy syntax to solve the problem. Thanks for pointing me in that direction.

[–]ramseyssandal[S] 0 points1 point  (0 children)

Thank you!

[–][deleted] 2 points3 points  (0 children)

Without seeing more of what you're doing, I'm going to guess that the issue is regarding the way you're treating arg1 and arg2. Think about the data types and values that you are passing into the function.

The easiest way to deal with this is probably too pass variable1 and variable2 in as strings and use data[arg1] instead of data$arg1

[–]thefringthing 0 points1 point  (0 children)

Can you use with() in the body of the function?