创建dplyr函数,可以判断变量输入是字符串还是符号

时间:2018-06-07 23:23:15

标签: r dplyr non-standard-evaluation quosure

我一直在研究"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))
}

2 个答案:

答案 0 :(得分:3)

我们可以使用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

答案 1 :(得分: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))
}