Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typo3/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
R 将命名参数传递给调用未变异函数的函数_R_Tidyverse_Rlang_Tidy_Tidyeval - Fatal编程技术网

R 将命名参数传递给调用未变异函数的函数

R 将命名参数传递给调用未变异函数的函数,r,tidyverse,rlang,tidy,tidyeval,R,Tidyverse,Rlang,Tidy,Tidyeval,我正在尝试做一些非常类似的事情 本质上,我需要将一个命名列表传递给一个函数,并将该命名列表作为其参数传递给另一个函数 如果我们遵循这个链接,他们就可以用mutate来实现,而我可以复制它: df <- tribble( ~a, 1 ) foo <- function(x, args) { mutate(x, !!! args) } foo(df, quos(b = 2, c = 3) # A tibble: 1 x 3 a b

我正在尝试做一些非常类似的事情

本质上,我需要将一个命名列表传递给一个函数,并将该命名列表作为其参数传递给另一个函数

如果我们遵循这个链接,他们就可以用mutate来实现,而我可以复制它:

df <- tribble(
    ~a,
    1
)

foo <- function(x, args) {
    mutate(x, !!! args)
}

foo(df, quos(b = 2, c = 3)

# A tibble: 1 x 3
      a     b     c
  <dbl> <dbl> <dbl>
1     1     2     3

df您可以在函数中使用
match.call()
来获取参数列表及其名称:

myfun列表(a=1,b=“hi”,c=“a”)
#> 
#>b美元
#> [1] 5
#>$x
#>[1]“呼叫”
#> 
#>b美元
#>[1]“数字”
您需要
blast()
,它可能包含在rlang 0.5.0中

blast <- function(expr, env = parent.frame()) {
  rlang::eval_bare(rlang::enexpr(expr), env)
}

blast(cbind(!!!letters))

blast我认为区分文字值(又称常量)和未赋值表达式很重要。例如,
quos(b=2,c=3)
将始终计算为2和3,而与上下文无关。在这种情况下,您不需要将它们设置为QUOSURE或表达式,一个简单的值列表就可以了。然后,您可以使用
purrr::lift
将任意函数从获取
..
点转换为获取列表。没有
需要:

arglist <- list( replace=TRUE, size=5, x=1:10 )     # Note: list, not quos
sample2 <- purrr::lift(sample)
sample2( arglist )         # Same as sample( x=1:10, size=5, replace=TRUE)
# [1]  7  3 10  8  3
在上面的例子中,
subset2()
手工构造一个
子集(x、arg1、arg2等)
表达式,然后对其求值。curly-curly操作符用作
的快捷方式!!enquo(x)
将用户表达式直接粘贴到最终表达式中,而
rlang::list2()
展开并拼接所有其他参数。通过使用
rlang::list2()
而不是
base:list()
我们正在添加对
的支持将函数作为一个整体

还值得强调的是
rlang::exec()
rlang::call2()
,它们与基本的
do.call和
call相当。两者都提供无缝的参数拼接支持,支持

subset2 <- function( x, ... )
    rlang::eval_tidy(rlang::expr(subset( {{x}}, !!!rlang::list2(...) )))

# Capture expressions because mpg and cyl are undefined at this point
argexpr <- rlang::exprs( mpg < 15, select=cyl )

# base::subset() doesn't support !!!, but our new function does!
subset( mtcars, !!!argexpr )   # Error in !argexpr : invalid argument type
subset2( mtcars, !!!argexpr )  # Same as subset( mtcars, mpg < 15, select=cyl )
mtcars %>% subset2(!!!argexpr) # Also works with the pipe
#                     cyl
# Duster 360            8
# Cadillac Fleetwood    8
# ...
rlang::exec( sample, !!!arglist )
eval(rlang::call2( subset, mtcars, !!!argexpr ))
最后,@Moody_mudscapper有一个非常好的例子。其中一个标签为任何任意函数添加NSE支持,并与
%%>%%
完全集成:

library(tags)    ## installed with devtools::install_github("moodymudskipper/tags")
using_bang$sample( !!!arglist )
using_bang$subset( mtcars, !!!argexpr )
mtcars %>% using_bang$subset( !!!argexpr )

tidyverse在tidyverse函数中工作。是否有办法在给blast的列表中包含一个未命名的参数,或者单独包含另一个参数?也就是说,如果我的函数有3个参数,我想在第一个参数中使用管道,而在其他2个参数中使用blast?代码类似于
df_to_apply_to%>%blast(func_to_apply(!!!其他参数))
blast()
不是要通过管道传输到。它必须包装应该发生准旋转的表达式。所以:
blast(df%>%f(!!!other))
subset2()
函数非常奇怪。我不明白它想做什么。你好,莱昂内尔汉里。这基本上与相同,只是我在这里使用
list2()
代替
enquos()
,因为表达式已经在
argexpr
中捕获,所以不需要另一个级别的引用。我将补充一些说明。作为旁注,您的技巧对于“修复”使用NSE处理
map()
%>%%
的基函数非常有用。这包括,
list2()
启用了
内部
和外部的
blast()
将参数转发到
subset()
。我想知道我们是否能使这种模式更容易。顺便说一下,我认为最好在
subset2()
的签名中复制尽可能多的命名参数。@LionelHenry:是的,你说得对。我尽量保持简单,因为我的答案已经有点长了。但是我认为在这种情况下保留
x
很重要,特别是因为OP想要使用
%>%
library(tags)    ## installed with devtools::install_github("moodymudskipper/tags")
using_bang$sample( !!!arglist )
using_bang$subset( mtcars, !!!argexpr )
mtcars %>% using_bang$subset( !!!argexpr )