Bastian
Bastian

Reputation: 363

How to pass a symbolic variable name between nested functions in the dplyr-way?

I want to write a function, which takes symbolic names of columns and pass it to subsequent functions doing something specific (sub-tasks).

Let me show you an example:

The data:

> ( d <- data.frame(A=1:3, B=3:1) )
  A B
1 1 3
2 2 2
3 3 1

Now my function:

fn <- function(data, cols) {
  return(data %>% mutate(across({{cols}}, ~. * 2)))
}

It works:

> d %>% fn(A)
  A B
1 2 3
2 4 2
3 6 1

Now, suppose this function does something important and separable as a unit task. Now I want to use this function in another function, taking column names in the dplyr-way:

another_fn <- function(data, cols) {
  result <- data %>% fn(cols)
  # .... more code
  
  return(result)
}

This doesn't work.

> d %>% another_fn(cols = A)
Error: Problem with `mutate()` input `..1`.
x object 'A' not found
i Input `..1` is `across(cols, ~. * 2)`.
Run `rlang::last_error()` to see where the error occurred.

When I provide the column as a string, it works well. So I understand the context is lost somewhere when I provide just the symbolic name A

> d %>% another_fn(cols = "A")
Note: Using an external vector in selections is ambiguous.
i Use `all_of(cols)` instead of `cols` to silence this message.
i See <https://tidyselect.r-lib.org/reference/faq-external-vector.html>.
This message is displayed once per session.
  A B
1 2 3
2 4 2
3 6 1

My question is: how to pass the symbolic name across nested calls?

Please note, I DO NOT WANT using three-dot (ellipsis) operator. I DO WANT to control what I pass and to which variable.


EDIT:

OK, I found the answer. The {{ }} should be added in the nested calls

another_fn <- function(data, cols) {
  result <- data %>% fn({{cols}})
  # .... more code
  
  return(result)
}


> d %>% another_fn(cols = A)
  A B
1 2 3
2 4 2
3 6 1
> d %>% another_fn(cols = "A")
  A B
1 2 3
2 4 2
3 6 1
> column
[1] "A"
> d %>% another_fn(cols = column)
  A B
1 2 3
2 4 2
3 6 1
> 

Upvotes: 0

Views: 164

Answers (1)

MrFlick
MrFlick

Reputation: 206207

Just use {{}} as you did in the first function

another_fn <- function(data, cols) {
  result <- data %>% fn({{cols}})
  
  return(result)
}

Upvotes: 1

Related Questions