我正在寻找一种方法来连接 quosure 和一个结果是 quosure 的字符串。实际上,如果我使用paste0()and quo_name(),我就可以做到。但我想知道是否有更优雅的替代方案可以在我的包中编写函数。这是一个通用示例:
library(dplyr)
df <- data_frame(
z_1 = 1,
z_2 = 2,
y_1 = 10,
y_2 = 20
)
get_var <- function(.data, var) {
xx = enquo(var)
select(.data, paste0(quo_name(xx), "_1"), paste0(quo_name(xx), "_2"))
}
get_var(df, z)
# A tibble: 1 x 2
z_1 z_2
<dbl> <dbl>
1 1 2
Run Code Online (Sandbox Code Playgroud) 参考:http://dplyr.tidyverse.org/articles/programming.html
此代码工作正常:
df <- tibble(
g1 = c(1, 1, 2, 2, 2),
g2 = c(1, 2, 1, 2, 1),
a = sample(5),
b = sample(5)
)
my_summarise <- function(df, group_by) {
group_by <- enquo(group_by)
print(group_by)
df %>%
group_by(!!group_by) %>%
summarise(a = mean(a))
}
my_summarise(df, g1)
Run Code Online (Sandbox Code Playgroud)
但是,如果我们将此函数包装在另一个函数中并进行调用,则它将无效.是因为名称只传递了一个级别?
wrapped_my_Summarize <- function(wdf, w_group_by){
my_summarise(wdf, w_group_by)
}
wrapped_my_Summarize(df, g1)
Run Code Online (Sandbox Code Playgroud)
总的来说,我觉得上面的例子是一个冒险的例子
我试图理解rlang包中解释的非标准评估。考虑到这个目标,我的问题是:
如何编写
dplyr::select.list()符合整洁评估原则的函数?
这是我当前如何编写包装器的示例dplyr::select():
select_wrapper <- function(x, ...) {
vars <- rlang::quos(...)
dplyr::select(x, !!!vars)
}
Run Code Online (Sandbox Code Playgroud)
适用于数据框,例如,
> select_wrapper(mtcars, cyl, mpg)
> ## cyl mpg
> ## Mazda RX4 6 21.0
> ## Mazda RX4 Wag 6 21.0
> ## Datsun 710 4 22.8
> ## Hornet 4 Drive 6 21.4
> ## Hornet Sportabout 8 18.7
> ## Valiant 6 18.1
Run Code Online (Sandbox Code Playgroud)
但不在列表中:
attr(mtcars, "test") <- "asdf"
mtcars_list <- attributes(mtcars)
select_wrapper(mtcars_list, row.names, test)
> ## 1: …Run Code Online (Sandbox Code Playgroud) 我想在数据框中创建几个新的空变量,在其中指定向量中的变量名称。如果我只指定一个变量名,但会中断多个变量名,则此方法有效。我尝试了一些以前的解决方案,但在这种情况下它们似乎不起作用,例如:
library(dplyr)
add_columns <- function(df, columns){
columns <- quo(columns)
mutate(df, !!columns := NA_character_)
}
columns <- c("x", "y")
iris %>%
add_columns(columns)
Error: The LHS of `:=` must be a string or a symbol
Run Code Online (Sandbox Code Playgroud)
所需的输出是:
# A tibble: 150 x 7
Sepal.Length Sepal.Width Petal.Length Petal.Width Species x y
<dbl> <dbl> <dbl> <dbl> <fct> <chr> <chr>
1 5.10 3.50 1.40 0.200 setosa NA NA
2 4.90 3.00 1.40 0.200 setosa NA NA
3 4.70 3.20 1.30 …Run Code Online (Sandbox Code Playgroud) 我正在尝试搜索数据库,然后"derived_name"在下面的可重现示例中使用从原始搜索派生的名称标记输出.我正在使用dplyr管道%>%,我在准静态评估和/或非标准评估方面遇到了麻烦.具体而言,使用在最终函数中count_colname派生自的字符对象无法对数据帧进行子集化."derived_name"top_n()
search_name <- "derived_name"
set.seed(1)
letrs <- letters[rnorm(52, 13.5, 5)]
letrs_count.df <- letrs %>%
table() %>%
as.data.frame()
count_colname <- paste0(search_name, "_letr_count")
colnames(letrs_count.df) <- c("letr", count_colname)
letrs_top.df <- letrs_count.df %>%
top_n(5, count_colname)
identical(letrs_top.df, letrs_count.df)
# [1] TRUE
Run Code Online (Sandbox Code Playgroud)
根据这个讨论,我认为上面的代码可行.而这篇文章引起我去尝试top_n_(),这似乎不存在.
我正在学习vignette("programming")哪个有点过头了.这篇文章让我尝试了!! sym()语法,这有效,但我不明白为什么!帮助理解为什么下面的代码工作将非常感激.谢谢.
colnames(letrs_count.df) <- c("letr", count_colname)
letrs_top.df <- letrs_count.df %>%
top_n(5, (!! sym(count_colname)))
letrs_top.df
# letr derived_name_letr_count
# 1 l 5 …Run Code Online (Sandbox Code Playgroud) 我想从用户那里动态获取条件,所以我构建了一个闪亮的应用程序,可以从输入字段中获取它们。问题是as.formula不适用于带有逗号的字符向量(没有效果的话)。
码:
all_conditions =
"condition1 ~ 0,
condition2 ~ 1,
condition3 ~ 2"
my_dataset %>% group_by(id) %>%
summarise(FLAG = case_when(
as.formula(all_conditions) )
)
Run Code Online (Sandbox Code Playgroud)
我得到:
评估错误:: 2:100:意外的','
我尝试使用paste和转义逗号没有成功。
假设我有一个函数,它使用非标准评估(NSE)从该数据框中获取数据框和不同数量的变量.是否有更快/更直接的方法来计算提供的变量数量而不是select()这些变量并计算列数?
# Works but seems non-ideal
nvar <- function(df, vars) {
vars_en <- rlang::enquo(vars)
df_sub <- dplyr::select(df, !!vars_en)
ncol(df_sub)
}
nvar(mtcars, mpg:hp)
#> 4
Run Code Online (Sandbox Code Playgroud) 可重现的例子
cats <-
data.frame(
name = c(letters[1:10]),
weight = c(rnorm(5, 10, 1), rnorm(5, 20, 3)),
type = c(rep("not_fat", 5), rep("fat", 5))
)
get_means <- function(df, metric, group) {
df %>%
group_by(.[[group]]) %>%
mutate(mean_stat = mean(.[[metric]])) %>%
pull(mean_stat) %>%
unique()
}
get_means(cats, metric = "weight", group = "type")
Run Code Online (Sandbox Code Playgroud)
我试过的
我希望得到两个值,而不是我得到一个值。看来 groupby 失败了。
我尝试了所有方法,包括使用 quo()、eval() 和替换 ()、UQ()、!! 以及许多其他方法来尝试使 group_by() 中的内容起作用。
这看起来非常简单,但我无法弄清楚。
代码推理
将变量放在引号中的决定是因为我在 ggplot aes_string() 调用中使用它们。我在函数中排除了 ggplot 代码以简化代码,否则会很容易,因为我们可以使用标准评估。
我在评论者建议!! ensym的地方回答这个问题,我认为这可能是使用卷曲{{的好地方,但我无法使其正常工作(也许不适用?)。
在不使用filter_,eval / parse或quote-unquote的情况下,如何执行此过滤器操作?会帮助吗?
我的解决方案(1g)使用filter_和使用粘贴建立的条件。1a有效(但是可以使用{{}}吗?)
如果我们想按多个变量过滤该怎么办?这是您看到2g在下面工作的地方(而2a不再工作了)。
library(tidyverse)
set.seed(1234)
A <- matrix(rnorm(30),nrow = 10, ncol = 3) %>% as_tibble() %>% set_names(paste("var", seq(1:3), sep = ""))
varnames_1 <- c("var2")
(expected_result_1 <- filter(A, var2 > 0))
#> # A tibble: 3 x 3
#> var1 var2 var3
#> <dbl> <dbl> <dbl>
#> 1 -2.35 0.0645 0.460
#> 2 0.429 0.959 -0.694
#> 3 -0.890 2.42 -0.936
(answer_1a <- filter(A,!!ensym(varnames_1) > 0)) # works (thanks joran and aosmith)
#> # A …Run Code Online (Sandbox Code Playgroud) 我有一个stacked_plot()使用整洁评估来制作堆叠图的函数。我想将它包含在我的包中,并从该包中调用另一个函数来调用它。这是最小的例子:
stacked_plot <- function(data, what, by = NULL, date_col = date){
by <- rlang::enquo(by)
what <- rlang::ensym(what)
date_col <- rlang::ensym(date_col)
data <- data %>%
dplyr::group_by(!!date_col, !!by) %>%
dplyr::summarise(!!what := sum(!!what, na.rm = TRUE)) %>%
dplyr::ungroup() %>%
tidyr::complete(!!date_col, !!by, fill = rlang::list2(!!what := 0))
p <- data %>%
ggplot2::ggplot(ggplot2::aes(!!date_col, !!what, fill = !!by)) +
ggplot2::geom_area(position = 'stack')
print(p)
}
#' @importFrom rlang .data
call_plot <- function() {
to_plot <- data.frame(date = rep(seq(lubridate::ymd('2020-01-01'),
lubridate::ymd('2020-03-30'),
by = '1 day'), each = …Run Code Online (Sandbox Code Playgroud)