【问题标题】:Creating dplyr function that can tell if variable input is a string or a symbol创建可以判断变量输入是字符串还是符号的 dplyr 函数
【发布时间】:2018-11-17 23:15:43
【问题描述】:

我一直在研究 "Programming with dplyr" 小插图,因为我想创建使用 dplyr 函数的函数。我想使用我在闪亮的应用程序和交互式 R 工作中创建的功能。为了在闪亮中使用,我希望这些函数采用字符串参数并使用 sym 函数将它们转换为符号。为了在交互式会话中使用,我希望这些函数可以选择不必使用字符串。所以我制作的函数需要一种方法来判断某些参数是否是字符串。

我想出了一个办法。我只是好奇是否有更好和/或更优雅的方式来做到这一点。

我做了一个简单的函数“my_summarise”作为例子。它是与小插图不同的函数“my_summarise”版本。它使用 tryCatch 来检查 group_var 参数是否为字符串。

library(dplyr)
df <- data.frame(g1 = c(1, 1, 2, 2, 2),
  g2 = c(1, 2, 1, 2, 1),
  a = c(1, 5, 4, 3, 2),
  b = c(3, 1, 2, 5, 4))

# df:

#  g1 g2 a b
#  1  1 1 3
#  1  2 5 1
#  2  1 4 2
#  2  2 3 5
#  2  1 2 4

my_summarise <- function(df, group_var) {

  is_string <- tryCatch(sym(group_var), error = function(group_var) group_var)

  if ("error" %in% class(is_string)) { 
    group_var <- enquo(group_var)      
  } else {
    group_var <- sym(group_var)   
  }

  df %>% group_by(!! group_var) %>% 
    summarise(a = mean(a))
}

my_summarise(df, g1)
# g1     a
# 1     3
# 2     3

my_summarise(df, "g1")
# g1     a
# 1     3
# 2     3

编辑: Onyambu 的答案是完美的。我只是对其进行了调整以使用一些 rlang 函数而不是它们的基本等效函数。

my_summarise <- function(df, group_var) {

  group_var <- enexpr(group_var)

  if(!is_symbol(group_var)) group_var <- sym(group_var) # instead of is.name and as.name you can use is.symbol and as.symbol or a mixture. 

  group_var <- enquo(group_var)      

  df %>% group_by(!! group_var) %>% 
    summarise(a = mean(a))
}

【问题讨论】:

    标签: r dplyr non-standard-evaluation quosure


    【解决方案1】:

    我们可以通过parse_expr 做到这一点

    my_summarise <- function(df, group_var) {    
    
    
      group_var <- parse_expr(quo_name(enquo(group_var)))   
    
      df %>%
         group_by(!! group_var) %>% 
         summarise(a = mean(a))
    }
    

    -检查

    my_summarise(df, g1)
    # A tibble: 2 x 2
    #     g1     a
    #  <dbl> <dbl>
    #1     1     3
    #2     2     3
    
    my_summarise(df, 'g1')
    # A tibble: 2 x 2
    #     g1     a
    #  <dbl> <dbl>
    #1     1     3
    #2     2     3
    

    【讨论】:

      【解决方案2】:
      my_summarise <- function(df, group_var) {
      
        group_var <- substitute(group_var)
      
       if(!is.name(group_var)) group_var <- as.name(group_var) # instead of is.name and as.name you can use is.symbol and as.symbol or a mixture. 
      
        group_var <- enquo(group_var)      
      
        df %>% group_by(!! group_var) %>% 
          summarise(a = mean(a))
      }
      

      您也可以完全忽略if 条件:

      my_summarise <- function(df, group_var) {
      
      group_var<- as.name(substitute(group_var))
      
        group_var <- enquo(group_var)      
      
        df %>% group_by(!! group_var) %>% 
          summarise(a = mean(a))
      }
      

      【讨论】:

      • 有趣!作品!我对其进行了一些调整,以便它使用 rlang 函数(enexpr 代替替代,is_symbol 代替 is.name,sym 代替 as.name)。 my_summarise % group_by(!! group_var) %>% summarise(a = mean(a)) }
      • 刚刚注意到我没有想到你的答案!谢谢!!超级有用 只是为了确保我理解它是如何工作的……替代(group_var)捕获参数 group_var 而不对其进行评估。然后 is_symbol(group_var) 评估参数并返回 FALSE 如果它是一个字符串。那么如果参数group_var是字符串的话if(!is_symbol(group_var))为真,并且字符串变成了符号?
      • 太棒了!再次感谢!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-06
      • 1970-01-01
      • 1970-01-01
      • 2012-11-12
      • 1970-01-01
      • 2021-06-22
      相关资源
      最近更新 更多