R 评价。。。当其他函数参数默认为空时

R 评价。。。当其他函数参数默认为空时,r,dplyr,rlang,R,Dplyr,Rlang,我想提供一个面向用户的函数,允许将任意分组变量传递给摘要函数,并可以选择指定用于筛选的附加参数,但默认情况下这些参数为NULL(因此未计算) 我理解为什么下面的示例会失败(因为homeworld所属位置不明确,而另一个arg优先),但我不确定在这种情况下正确传递圆点的最佳方式是什么。理想情况下,对下面fun的第二次和第三次调用的结果将返回相同的结果 库(dplyr) #> #>正在附加包:“dplyr” #>以下对象已从“package:stats”屏蔽: #> #>滤波器,滞后 #>以下对

我想提供一个面向用户的函数,允许将任意分组变量传递给摘要函数,并可以选择指定用于筛选的附加参数,但默认情况下这些参数为
NULL
(因此未计算)

我理解为什么下面的示例会失败(因为
homeworld
所属位置不明确,而另一个arg优先),但我不确定在这种情况下正确传递圆点的最佳方式是什么。理想情况下,对下面
fun
的第二次和第三次调用的结果将返回相同的结果

库(dplyr)
#> 
#>正在附加包:“dplyr”
#>以下对象已从“package:stats”屏蔽:
#> 
#>滤波器,滞后
#>以下对象已从“package:base”屏蔽:
#> 
#>相交、setdiff、setequal、并集
乐趣%
dplyr::总结(
ht=平均值(.data[[“height”]],na.rm=TRUE),
.groups=“删除”
)
}
乐趣(.df=starwars,.species=c(“人类”、“机器人”)、species、homeworld)
#>#tibble:19 x 3
#>物种家园
#>               
#>1机器人纳布96
#>2机器人塔图因132
#>3机器人148
#>4人类奥德朗176。
#>5人类贝斯平175
#>6人贝斯汀IV 180
#>7人类钱德里拉150
#>8人类协和黎明183
#>9人Corellia 175
#>10人类科洛桑168。
#>11人类埃里亚杜180
#>12人类哈伦卡尔188
#>13人卡米诺183
#>14人类纳布168。
#>15人Serenno 193
#>16人索科罗177
#>17人炖肉Jon 182
#>18人塔图因179。
#>19人权193
乐趣(.df=starwars,.species=NULL,homeworld)
#>#A tibble:49 x 2
#>故乡ht
#>              
#>1奥德朗176。
#>2阿伦小调79
#>3贝斯平175
#>4贝斯汀IV 180
#>5卡托内莫迪亚191
#>6 Cerea 198
#>7尚帕拉196
#>8钱德里拉150
#>9康科德黎明183
#>10科雷利亚175
#>#…还有39行
乐趣(.df=星球大战,家园)
#>乐趣中出错(.df=starwars,homeworld):找不到对象“homeworld”
由[reprex软件包]于2020-06-15创建(https://reprex.tidyverse.org)(v0.3.0)
我知道我可以通过以下方式实现预期结果:

fun <- function(.df, .species = NULL, .groups = NULL) {

  .group_vars <- rlang::syms(purrr::map(.groups, rlang::as_string))

...

}

fun您可以移动参数,使
.species
位于点之后

fun <- function(.df, ..., .species = NULL) {

    .group_vars <- rlang::ensyms(...)

    if (!is.null(.species)) {
        .df <- .df %>%
            dplyr::filter(.data[["species"]] %in% .species)  
    }

    .df %>%
        dplyr::group_by(!!!.group_vars) %>%
        dplyr::summarize(
            ht = mean(.data[["height"]], na.rm = TRUE),
            .groups = "drop"
        )

}

fun(.df = starwars, homeworld)
fun%
dplyr::总结(
ht=平均值(.data[[“height”]],na.rm=TRUE),
.groups=“删除”
)
}
乐趣(.df=星球大战,家园)

> fun(.df = starwars, homeworld)
# A tibble: 49 x 3
   homeworld         ht .groups
   <chr>          <dbl> <chr>  
 1 NA              139. drop   
 2 Alderaan        176. drop   
 3 Aleen Minor      79  drop   
 4 Bespin          175  drop   
 5 Bestine IV      180  drop   
 6 Cato Neimoidia  191  drop   
 7 Cerea           198  drop   
 8 Champala        196  drop   
 9 Chandrila       150  drop   
10 Concord Dawn    183  drop   
# ... with 39 more rows
>乐趣(.df=starwars,homeworld)
#A tibble:49 x 3
家庭世界ht组
1 NA 139。滴
2奥德朗176。滴
3阿伦小调79下降
4贝斯平175滴
5贝斯汀IV 180滴
6卡托内莫迪亚191滴
7塞雷亚198滴
8尚帕拉196滴
9钱德里拉150滴
10协和黎明183降落
# ... 还有39行

这就是你想要发生的。其他示例仍然有效。

传递一个空参数怎么样
fun(.df=starwars,homeworld)
否则你需要在
..
@RonakShah中传递
.species
。空默认值背后的要点是,我希望用户不必担心
.species
传递的内容,并且默认行为是无过滤。按照你的建议做就相当于要求用户明确指定
fun(.df=starwars,.species=NULL,homeworld)
。在你的编辑中,我仍然看不到任何会使我的答案无效的内容。我知道这个解决方案,但我觉得有点不满意,因为它依赖于参数顺序,而不是函数定义中参数的受控计算。你要求的是颠覆参数顺序的东西。我认为没有更好的解决办法。如果.species是第二个参数,而您没有命名这些参数,那么第二个参数将始终引用.species。您的其他示例仍然以完全相同的方式工作。我能想到的唯一其他选择是玩
fun