问题描述
我想编写一个函数,该函数采用列的符号名称并将其传递给执行特定操作(子任务)的后续函数。
让我给你举个例子:
数据:
> ( d <- data.frame(A=1:3,B=3:1) )
A B
1 1 3
2 2 2
3 3 1
现在我的功能:
fn <- function(data,cols) {
return(data %>% mutate(across({{cols}},~. * 2)))
}
它有效:
> d %>% fn(A)
A B
1 2 3
2 4 2
3 6 1
现在,假设这个函数做了一些重要且可分离的单元任务。现在我想在另一个函数中使用这个函数,以 dplyr 方式取列名:
another_fn <- function(data,cols) {
result <- data %>% fn(cols)
# .... more code
return(result)
}
这不起作用。
> 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.
当我将列作为字符串提供时,它运行良好。所以我知道当我只提供符号名称 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
请注意,我不想使用三点(省略号)运算符。我确实想控制我传递的内容和变量。
编辑:
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
>
解决方法
只需像在第一个函数中那样使用 {{}}
another_fn <- function(data,cols) {
result <- data %>% fn({{cols}})
return(result)
}