Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ssh/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如果我想让一个类似dplyr的函数能够同时使用NSE和SE,如何解决{{}和all_off()的问题?_R_Dplyr_Curly Braces_Nse - Fatal编程技术网

如果我想让一个类似dplyr的函数能够同时使用NSE和SE,如何解决{{}和all_off()的问题?

如果我想让一个类似dplyr的函数能够同时使用NSE和SE,如何解决{{}和all_off()的问题?,r,dplyr,curly-braces,nse,R,Dplyr,Curly Braces,Nse,我想写一个函数,它将接受列的符号名和作为变量(字符串)传递的名称 让我给你举个例子: 数据: > ( d <- data.frame(A=1:3, B=3:1) ) A B 1 1 3 2 2 2 3 3 1 B)作为字符串传递的名称 > d %>% fn(cols = A) A B 1 2 3 2 4 2 3 6 1 > d %>% fn(cols = B) A B 1 1 6 2 2 4 3 3 2 > d %>% fn(co

我想写一个函数,它将接受列的符号名和作为变量(字符串)传递的名称

让我给你举个例子:

数据:

> ( d <- data.frame(A=1:3, B=3:1) )
  A B
1 1 3
2 2 2
3 3 1
B)作为字符串传递的名称

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

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

> d %>% fn(cols = c(A, B))
  A B
1 2 6
2 4 4
3 6 2
> column <- "A"
> d %>% fn(cols = column)
  A B
1 2 3
2 4 2
3 6 1

> d %>% fn(cols = c("A", "B"))
  A B
1 2 6
2 4 4
3 6 2

如何修复此问题,以启用这两种方法并避免警告?

我的建议是保留原始实现及其附带的警告,因为情况确实不明确。考虑:

d <- data.frame(A=1:3, B=3:1, columns=4:6)  # Note the new column named columns
columns <- c("A","B")
d %>% fn(cols = columns)                    # Which `columns` should this use?
编辑:虽然我推荐上述方法,但另一种方法是检查调用环境中是否存在变量。如果变量存在,则假定它包含列名,并在
all_of()
中使用它;否则,假设列名按原样提供:

fn <- function(data, cols) {
  varExist <- rlang::enexpr(cols) %>% 
    rlang::expr_deparse() %>%
    exists(envir=rlang::caller_env())
  
  if(varExist)
    data %>% mutate( across(all_of(cols), ~. *2) )
  else
    data %>% mutate( across({{cols}}, ~. * 2) )
}

rm(A)              # Ensure there is no variable called A
d %>% fn(cols=A)   # Mutate will operate on column A only

A <- c("A","B")    # A now contains column names
d %>% fn(cols=A)   # Mutate will operate on A and B
fn%
存在(envir=rlang::caller_env())
if(varExist)
数据%>%突变(跨越(所有列,~*2))
其他的
数据%>%突变(跨越({{cols}},~.*2))
}
rm(A)#确保没有称为A的变量
d%>%fn(cols=A)#Mutate将仅对A列进行操作
A%fn(cols=A)#突变将作用于A和B

啊,明白了,我放错地方了!不幸的是,这将主要用于动态脚本,其中列的名称将从web服务接收,但此功能也将提供给不熟悉dplyr和NSE的最终用户。它们将“自动”提供字符串向量。我不能指望他们读手册(理论上我应该读,实际上我被经理杀了)。在我使用的生产环境中,这个名称“columns”不太可能出现在数据帧中。我必须找到另一种方法。。。或者辞去dplyr来完成这项任务。更重要的是,这现在是一个注释,但将来它只会抛出错误,这将破坏整个代码。@Bastian听起来您的函数将主要用于生产中的标准求值。我的建议是致力于这一点并放弃NSE支持。不过,请看我的编辑,如果你绝对必须支持这两个。这是美丽的工作。rlang是如此强大,我必须最终探索它,因为它为R打开了难以置信的可能性。非常感谢你,Artem。这绝对符合我的需要。所以你想让函数同时适用于符号和字符串吗?是的,没错。只要列的名称是明确提供的:fn(A,B)或fn(“A”,“B”),它就工作得很好。当我提供一个外部向量时,它会打印一个关于选择中的模糊性的注释。在将来,此注释将变成警告,然后变成错误。理论上,我可以提供两个函数,比如NSE的fn()和SE的fn_u2;(),但我真的希望避免这种情况。也许对参数进行一些条件检查?
fn <- function(data, cols) {
  return(data %>% mutate(across(all_of({{cols}}), ~. * 2)))
}

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

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

> d %>% fn(cols = c(A, B))

 Error: Problem with `mutate()` input `..1`.
x object 'A' not found
i Input `..1` is `across(all_of(c(A, B)), ~. * 2)`.
Run `rlang::last_error()` to see where the error occurred. 
d <- data.frame(A=1:3, B=3:1, columns=4:6)  # Note the new column named columns
columns <- c("A","B")
d %>% fn(cols = columns)                    # Which `columns` should this use?
d %>% fn(cols = all_of(columns))     # works without a warning
fn <- function(data, cols) {
  varExist <- rlang::enexpr(cols) %>% 
    rlang::expr_deparse() %>%
    exists(envir=rlang::caller_env())
  
  if(varExist)
    data %>% mutate( across(all_of(cols), ~. *2) )
  else
    data %>% mutate( across({{cols}}, ~. * 2) )
}

rm(A)              # Ensure there is no variable called A
d %>% fn(cols=A)   # Mutate will operate on column A only

A <- c("A","B")    # A now contains column names
d %>% fn(cols=A)   # Mutate will operate on A and B