我在 R 中有一个...使用 tidyeval 的简单函数。是否可以将这些更改为字符串?
simple_paste <- function(...){
my_vars <- enquos(...)
paste(..., sep = "_x_")
}
Run Code Online (Sandbox Code Playgroud)
simple_paste(hello, world)
作为输出,我想得到"hello_x_world". 我也可以考虑使用glue函数 orstr_c代替paste,尽管我不确定这会更好。
我想捕获传递给函数的传入参数。我怎样才能做到这一点?下面的功能并不完全是我想要的。我想要的输出是"Using mtcars and am". 我的印象rlang是可以帮助解决这个问题,但我还没有找到一个函数来完成这项工作。
fx_capture<- function(fx_data, fx_var) {
name_data <- quote(fx_data)
name_var <- quote(fx_var)
paste("Using", name_data, "and", name_var)
}
fx_capture(mtcars, am)
> "Using fx_data and fx_var"
Run Code Online (Sandbox Code Playgroud) 我正在尝试使用tidyeval进行编程。
我想编写一个函数为选定的结果变量运行逻辑回归模型:
library(tidyverse)
set.seed(1234)
df <- tibble(id = 1:1000,
group = sample(c("Group 1", "Group 2", "Group 3"), 1000, replace = TRUE),
died = sample(c(0,1), 1000, replace = TRUE))
myfunc <- function(data, outcome){
enquo_var <- enquo(outcome)
fit <- tidy(glm(!!enquo_var ~ group, data=data,
family = binomial(link = "logit")),
exponentiate = TRUE, conf.int=TRUE)
fit
}
myfunc(df, died)
Run Code Online (Sandbox Code Playgroud)
但是得到:
!enquo_outcome错误:参数类型无效
(请注意,实际情况涉及更复杂的功能)。
这可能吗?
我已经阅读了几个关于dplyr编程的指南,我仍然对如何解决使用非标准评估(NSE)评估构造/连接字符串的问题感到困惑.我意识到有更好的方法来解决这个例子,而不是使用NSE,但想要学习如何.
t <- tibble( x_01 = c(1, 2, 3), x_02 = c(4, 5, 6))
i <- 1
Run Code Online (Sandbox Code Playgroud)
这是我想要的结果,但是想要mutate()构造变量:
t %>% mutate(d_01 = x_01 * 2)
#> A tibble: 3 x 3
#> x_01 x_02 d_01
#> <dbl> <dbl> <dbl>
#> 1 1.00 4.00 2.00
#> 2 2.00 5.00 4.00
#> 3 3.00 6.00 6.00
Run Code Online (Sandbox Code Playgroud)
这是我第一次尝试使用字符串:
new <- sprintf("d_%02d", i)
var <- sprintf("x_%02d", i)
t %>% mutate(new = var * 2)
#> Error in mutate_impl(.data, dots) : …Run Code Online (Sandbox Code Playgroud) 我只是想了解这里出了什么问题.在第一种情况(工作)中,我将enquo()-ted参数分配给变量,在第二种情况下,我在调用中直接使用了enquoted参数mutate.
library("dplyr")
df <- tibble(x = 1:5, y= 1:5, z = 1:5)
# works
myfun <- function(df, transformation) {
my_transformation <- rlang::enquo(transformation)
df %>%
gather("key","value", x,y,z) %>%
mutate(value = UQ(my_transformation))
}
myfun(df,exp(value))
# does not work
myfun_2 <- function(df, transformation) {
df %>%
gather("key","value", x,y,z) %>%
mutate(value = UQ(rlang::enquo(transformation)))
}
myfun_2(df,exp(value))
#>Error in mutate_impl(.data, dots) : Column `value` is of unsupported type closure
Run Code Online (Sandbox Code Playgroud)
编辑 这里有更多的思路:)
将调用包含到quo()中看起来好像要评估的表达式是"正确构建"的
# looks as if the whole thing should be working …Run Code Online (Sandbox Code Playgroud) 试图排除
tidyr::gather() shiny::selectInput)而不是via 作为我的函数的输入...如何通过整洁的eval功能实现这一目标?
由于我经由单个函数参数传递多个列名,以为需要使用!!!(引文结束剪接)而不是!!如在奠定了与dplyr编程.但这似乎并没有很好地发挥作用,tidyselect::vars_select()而且似乎-造成了麻烦.
这是我想要做的基本事情:
library(magrittr)
gather_data_1 <- function(dat, ...) {
dat %>% tidyr::gather("key", "value", ...)
}
mtcars %>% gather_data_1(-mpg, -cyl) %>% head()
#> mpg cyl key value
#> 1 21.0 6 disp 160
#> 2 21.0 6 disp 160
#> 3 22.8 4 disp 108
#> 4 21.4 6 disp 258
#> 5 18.7 8 disp …Run Code Online (Sandbox Code Playgroud) 我试图用R编写一个函数,该函数根据分组变量汇总数据帧。分组变量作为列表给出并传递给group_by_at,我想对其进行参数化。
我现在正在做的是这样的:
library(tidyverse)
d = tribble(
~foo, ~bar, ~baz,
1, 2, 3,
1, 3, 5
4, 5, 6,
4, 5, 1
)
sum_fun <- function(df, group_vars, sum_var) {
sum_var = enquo(sum_var)
return(
df %>%
group_by_at(.vars = group_vars) %>%
summarize(sum(!! sum_var))
)
}
d %>% sum_fun(group_vars = c("foo", "bar"), baz)
Run Code Online (Sandbox Code Playgroud)
但是,我想这样调用该函数:
d %>% sum_fun(group_vars = c(foo, bar), baz)
Run Code Online (Sandbox Code Playgroud)
这意味着不应在调用中评估分组变量,而应在函数中评估分组变量。我将如何重写该功能以启用该功能?
我试过enquo像summary变量一样使用,然后替换group_vars为!! group_vars,但这会导致此错误:
Error in !group_vars : invalid argument type
Run Code Online (Sandbox Code Playgroud)
使用group_by(!!!group_vars)收益:
Column `c(foo, …Run Code Online (Sandbox Code Playgroud) 我想把一堆列传递到pmap()里面mutate()。以后,我想选择那些相同的列。
目前,我正在将列名列表传递给pmap()quosure,这很好用,尽管我不知道这是否是“正确”的方法。但是我无法弄清楚如何使用相同的quosure / list select()。
我几乎没有tidyeval的经验,我只能通过玩耍来达到这一目的。我想必须有一种对pmap()和都使用相同内容的方法select(),最好不必将我的每个列名都用引号引起来,但是我还没有找到它。
library(dplyr)
library(rlang)
library(purrr)
df <- tibble(a = 1:3,
b = 101:103) %>%
print
#> # A tibble: 3 x 2
#> a b
#> <int> <int>
#> 1 1 101
#> 2 2 102
#> 3 3 103
cols_quo <- quo(list(a, b))
df2 <- df %>%
mutate(outcome = !!cols_quo %>%
pmap_int(function(..., word) {
args <- list(...)
# just to be clear this isn't …Run Code Online (Sandbox Code Playgroud) 因此,此示例基本上来自https://tidyeval.tidyverse.org/dplyr.html#patterns-for-single-arguments,它可以正常工作:
library(tidyverse)
group_mean <- function(df, group_var, summary_var){
group_var <- rlang::enquo(group_var)
summary_var <-rlang::enquo(summary_var)
name <- paste0(rlang::quo_name(summary_var), "_mean")
df %>%
dplyr::group_by(!!group_var) %>%
dplyr::summarise(!!name := mean(!!summary_var, na.rm = TRUE))
}
mtcars %>% group_mean(group_var = cyl, summary_var = disp)
#> # A tibble: 3 x 2
#> cyl disp_mean
#> <dbl> <dbl>
#> 1 4 105.
#> 2 6 183.
#> 3 8 353.
Run Code Online (Sandbox Code Playgroud)
我想例如能够有时选择中位数而不是均值,例如将函数名称更改为group_stat()。
这是数据:
library(tidyverse)
col_pre <- c('a', 'b', 'c')
df <- tibble(a1 = 1:3, a2 = 4:6, b1 = 7:9, b2 = 10:12, c1 = 13:15, c2 = 16:18)
Run Code Online (Sandbox Code Playgroud)
我想使用purrr::map()并dplyr::mutate()创建三个新列,它们是df. 我可以map()用来迭代 a、b、c 列前缀的向量。我想出了这些tidyeval操作,以便下面的代码可以正常运行。
out <- col_pre %>%
map_df(~ df %>%
mutate(!!as.name(paste0(.x, '3')) := !!as.name(paste0(.x, '1')) + !!as.name(paste0(.x, '2')))
)
Run Code Online (Sandbox Code Playgroud)
但是,out现在有六个伪行:
a1 a2 b1 b2 c1 c2 a3 b3 c3
1 1 4 7 10 13 16 5 NA NA
2 …Run Code Online (Sandbox Code Playgroud)