创建可以判断变量输入是字符串还是符号的 dplyr 函数
Creating dplyr function that can tell if variable input is a string or a symbol
我一直在研究 "Programming with dplyr" 小插图,因为我想创建使用 dplyr 函数的函数。我想在闪亮的应用程序和交互式 R 工作中使用我制作的功能。为了在 shiny 中使用,我希望这些函数采用字符串参数并使用 sym 函数将它们转换为符号。为了在交互式会话中使用,我希望这些函数可以选择不必使用字符串。所以我制作的函数需要一种方法来判断某些参数是否为字符串。
我找到了解决这个问题的方法。我只是很好奇是否有更好的 and/or 更优雅的方法。
我做了一个简单的函数,"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))
}
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))
}
我们可以用 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
我一直在研究 "Programming with dplyr" 小插图,因为我想创建使用 dplyr 函数的函数。我想在闪亮的应用程序和交互式 R 工作中使用我制作的功能。为了在 shiny 中使用,我希望这些函数采用字符串参数并使用 sym 函数将它们转换为符号。为了在交互式会话中使用,我希望这些函数可以选择不必使用字符串。所以我制作的函数需要一种方法来判断某些参数是否为字符串。
我找到了解决这个问题的方法。我只是很好奇是否有更好的 and/or 更优雅的方法。
我做了一个简单的函数,"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))
}
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))
}
我们可以用 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