如何让整洁的点接受可变范围

How to get tidy dots to accept a variable range

我发现这个 very helpful article 关于如何使用 quosure 和 tidy dots 编写接受变量参数的函数。这是一些代码:

my.summary <- function(df.name=df_tp1, group_var, ...) {
    group_var <- enquo(group_var)
    smry_vars <- enquos(..., .named = TRUE)

    the.mean <- purrr::map(smry_vars, function(var) {
        expr(mean(!!var, na.rm = TRUE))
    })
    names(the.mean) <- paste0("mean-", names(the.mean))

   df.name %>%
        group_by(!!group_var) %>%
        summarise(!!!the.mean)
}

问题是我必须用一长串变量调用函数,如下所示:

cm_all1 <- my.summary(df_tp1_cm, group_var=net_role, so_part_value, cult_ci, cult_sn, cult_ebc, sl_t_lrn, sl_xt_lrn, nl_netops_km, so_rt, nl_netops_trust)

我很高兴能够用

之类的东西来调用它
so_part_value:nl_netops_trust

相反,但这会产生如下错误:

Error in so_part_value:nl_netops_trust : NA/NaN argument

我还尝试将变量名放入字符向量中,然后使用 enquo() 和 !!但这没有用。

如果有任何想法,我将不胜感激。

这里是我根据一夫的思路改写的函数。这适用于我的假数据集,但不适用于真实数据。

my.summary <- function(df.name=df_tp1, group_var, ...) {
##    group_var <- enquo(group_var)
    smry_vars <- df.name %>% select(...) %>% colnames()

    df.name %>%
        ##        group_by(!!group_var) %>%
        group_by({{group_var}}) %>%
        summarise_at(smry_vars,
                     list(mean=function(x) mean(x, na.rm=TRUE),
                          sd=function(x) sd(x, na.rm=TRUE),
                          min=function(x) min(x, na.rm=TRUE),
                          max=function(x) max(x, na.rm=TRUE),
                          q1=function(x) quantile(x, .25, na.rm=TRUE),
                          q2=function(x) quantile(x, .50, na.rm=TRUE),
                          q3=function(x) quantile(x, .75, na.rm=TRUE),
                          n=function(x) n()
                          ))
}

您只需要确保 ... 处于正确的环境中(您在此示例中提供的 df)。然后你可以使用 colnames() 来提取列名。

library(rlang)
get_column_range <- function(df,...){

    writeLines("Column names as string:")
    print(df %>% select(...) %>% colnames())
    writeLines("Convert back to symbols")
    print(syms(df %>% select(...) %>% colnames()))
}

get_column_range(df = iris,Sepal.Length:Petal.Width)
Column names as string:
[1] "Sepal.Length" "Sepal.Width"  "Petal.Length" "Petal.Width" 
Convert to symbol
[[1]]
Sepal.Length

[[2]]
Sepal.Width

[[3]]
Petal.Length

[[4]]
Petal.Width

dplyr 后缀为 _at 的函数也接受字符串作为变量,您不必将它们转换为 quosure 然后取消引用它们。

请注意 {{}} 是一种更容易学习的语法,它同时引用和取消引用:

my.summary <- function(df,group_var,...){
    column_names <- df %>% select(...) %>% colnames()

    df %>%
        group_by({{group_var}}) %>%
        summarise_at(column_names,list(mean = mean))
}

my.summary(df = iris,group_var = Species,Sepal.Length:Petal.Width)
# A tibble: 3 x 5
  Species    Sepal.Length_mean Sepal.Width_mean Petal.Length_mean Petal.Width_mean
  <fct>                  <dbl>            <dbl>             <dbl>            <dbl>
1 setosa                  5.01             3.43              1.46            0.246
2 versicolor              5.94             2.77              4.26            1.33 
3 virginica               6.59             2.97              5.55            2.03 

更多信息,您可以阅读:https://rlang.r-lib.org/reference/quotation.html