我可以从文档中看到rlang::enquo()
和rlang::quo()
在不同的上下文中使用。因此,我rlang::enysm()
最近在函数声明中使用了(见下文)。然而,包裹在另一个 SE 函数调用中,我得到了一个意外错误,我猜这与惰性求值有关(如果我force(x)
在 中,它就会消失f_enysm()
)。但似乎我也可以通过简单地使用sym(x)
而不是ensym(x)
因为x
是一个不传达任何关于环境的信息(而不是quosures)的字符串来解决这个问题。
那安全吗?
如果是,我不知道什么时候应该更喜欢ensym()
,sym
并且建议的用途似乎与quo()
/ enquo()
、expr()
/enexpr()
等使用的术语不一致。
library(rlang)
f_ensym <- function(data, x, fun) {
x <- fun(x)
head(dplyr::arrange(data, !!x))
}
f_ensym(mtcars, "cyl", sym)
#> mpg cyl disp hp drat wt qsec vs am gear carb
#> 1 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1
#> 2 24.4 4 146.7 …
Run Code Online (Sandbox Code Playgroud) tibble
作为列名,我得到了几个因素的相互作用(参见下面两个因素的例子).
ex <- structure(list(`Monday*FALSE` = 42.74, `Monday*TRUE` = 70.68,
`Tuesday*TRUE` = 44.05, `Tuesday*FALSE` = 51.25, `Wednesday*TRUE` = 35.57,
`Wednesday*FALSE` = 59.24, `Thursday*TRUE` = 85.3, `Thursday*FALSE` = 59.91,
`Friday*TRUE` = 47.27, `Friday*FALSE` = 47.44, `Saturday*TRUE` = 62.28,
`Saturday*FALSE` = 98.8, `Sunday*TRUE` = 57.11, `Sunday*FALSE` = 65.99), class = c("tbl_df",
"tbl", "data.frame"), row.names = c(NA, -1L))
Run Code Online (Sandbox Code Playgroud)
我想写一个允许gather
这个的函数tibble
,但另外key
根据因子的输入名称创建一个名称.但是,以下内容无法正常工作,因为paste0
返回一个字符串.
my_gather <- function(data, ...){
vars <- enquos(...)
data %>%
gather(key = paste0(!!!vars, sep = '*'), value …
Run Code Online (Sandbox Code Playgroud) 一段时间以来,我一直试图了解 tidy eval 或如何在 tidyverse 中使用变量,但我似乎从未完全掌握它。
例如,我试图将 ggplot 与变量映射一起使用。这将是基本的 R 版本:
library(ggplot2)
var1 = "wt"
var2 = "mpg"
ggplot(mtcars, aes(x = get(var1), y = get(var2))) + geom_point()
Run Code Online (Sandbox Code Playgroud)
但是,根据我所看到的所有文档和讨论,“正确”的 quasiquotation 方式是:
ggplot(mtcars, aes(x = !!sym(var1), y = !!sym(var2))) + geom_point()
Run Code Online (Sandbox Code Playgroud)
也许这更类似于:
ggplot(mtcars, aes(x = !!as.symbol(var1), y = !!as.symbol(var2))) + geom_point()
Run Code Online (Sandbox Code Playgroud)
该get()
方法对我来说更短且更具可读性。为什么 tidyverse 社区会回避它?
我想编写一个在ggplot中执行美学映射的函数。该函数应该有两个参数:var
应该映射到aesthetic
。实际上,下面的第一个代码块有效。
但是,我不想在初始ggplot函数中而是在geom_point函数中进行映射。在这里,我收到以下错误消息:
错误:
:=
只能在准引数中使用
1.阻止:工作正常
library(ggplot2)
myfct <- function(aesthetic, var){
aesthetic <- enquo(aesthetic)
var <- enquo(var)
ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, !! (aesthetic) := !!var)) +
geom_point()
}
myfct(size, Petal.Width)
Run Code Online (Sandbox Code Playgroud)
2.阻止:抛出错误
library(ggplot2)
myfct <- function(aesthetic, var){
aesthetic <- enquo(aesthetic)
var <- enquo(var)
ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width)) +
geom_point(aes(!! (aesthetic) := !!var))
}
myfct(size, Petal.Width)
Run Code Online (Sandbox Code Playgroud)
如果自变量审美作为字符串传递时,也会发生相同的行为sym
。
# 1. block
myfct <- function(aesthetic, var){
aesthetic <- sym(aesthetic)
ggplot(iris, aes(x = …
Run Code Online (Sandbox Code Playgroud) 我已经查看了其他答案,但找不到下面代码的解决方案.基本上,我正在创建一个函数,inner_join
即两个数据框并filter
基于函数中输入的列.
问题是filter
函数的一部分不起作用.但是,如果我将函数过滤掉并将其追加,它就可以工作mydiff("a") %>% filter(a.x != a.y)
任何建议都有帮助.
请注意,我是引号中的函数输入
library(dplyr)
# fake data
df1<- tibble(id = seq(4,19,2),
a = c("a","b","c","d","e","f","g","h"),
b = c(rep("foo",3), rep("bar",5)))
df2<- tibble(id = seq(10, 20, 1),
a = c("d","a", "e","f","k","m","g","i","h", "a", "b"),
b = c(rep("bar", 7), rep("foo",4)))
# What I am trying to do
dplyr::inner_join(df1, df2, by = "id") %>% select(id, b.x, b.y) %>% filter(b.x!=b.y)
#> # A tibble: 1 x 3
#> id b.x b.y
#> <dbl> <chr> …
Run Code Online (Sandbox Code Playgroud) 我正在foo
使用map2
和修改嵌套的数据框mutate
,并且我想根据来在每个嵌套的数据框中命名一个变量foo$name
。我不确定nse
/ tidyeval
取消引号的正确语法在这里。我的尝试:
library(tidyverse)
foo <- mtcars %>%
group_by(gear) %>%
nest %>%
mutate(name = c("one", "two", "three")) %>%
mutate(data = map2(data, name, ~
mutate(.x, !!(.y) := "anything")))
#> Error in quos(...): object '.y' not found
Run Code Online (Sandbox Code Playgroud)
我希望嵌套数据框中的新创建变量的名称分别为“一个”,“两个”和“三个”。
如果我对normal mutate
进行普通操作df
,那么我将基于普通语法使用我的尝试,name
字符串在哪里:
name <- "test"
mtcars %>% mutate(!!name := "anything") # works fine
Run Code Online (Sandbox Code Playgroud)
如果成功,则以下行应返回TRUE
:
foo[1,2] %>% unnest %>% names %>% .[11] == "one"
Run Code Online (Sandbox Code Playgroud) 相对较新的 tidy 评估和我正在制作的函数,我想知道为什么使用不同的辅助函数。例如,enquo
和之间有什么区别ensym
?在我下面制作的用于捕获每日平均值和移动平均值的函数中,它们是可以互换的:
library(dplyr)
library(lubridate)
library(rlang)
library(zoo)
manipulate_for_ma <- function(data, group_var, da_col_name, summary_var, ma_col_name) {
group_var <- ensym(group_var)
summary_var <- enquo(summary_var)
da_col_name <- ensym(da_col_name)
ma_col_name <- enquo(ma_col_name)
data %>%
group_by(!!group_var) %>%
summarise(!!da_col_name := mean(!!summary_var, na.rm = TRUE)) %>%
mutate(!!ma_col_name := rollapply(!!da_col_name,
30,
mean,
na.rm = TRUE,
partial = TRUE,
fill = NA)) %>%
rename(date = !!group_var)
}
lakers %>%
mutate(date = ymd(date)) %>%
manipulate_for_ma(group_var = date,
da_col_name = points_per_play_da,
summary_var = points,
points_per_play_ma)
# A tibble: …
Run Code Online (Sandbox Code Playgroud) 我正在尝试编写一个自定义函数,该函数使用 的rlang
非标准评估来按多个变量对数据帧进行分组。
这就是我已经-
library(rlang)
# function definition
tryfn <- function(data, groups, ...) {
# preparing data
df <- dplyr::group_by(data, !!!rlang::enquos(groups))
print(head(df))
# applying some function `.f` on df that absorbs `...`
# .f(df, ...)
}
Run Code Online (Sandbox Code Playgroud)
这适用于单个分组变量 -
# works
tryfn(mtcars, am)
#> # A tibble: 6 x 11
#> # Groups: am [2]
#> mpg cyl disp hp drat wt qsec vs am gear carb
#> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> …
Run Code Online (Sandbox Code Playgroud) 以下是一些我们使用两个名称进行更广泛旋转的愚蠢数据:
library(tidyr)
df <- data.frame(
food = c('banana','banana','banana','banana','cheese','cheese','cheese','cheese'),
binary = c(rep(c('yes','no'), 4)),
car = c('toyota','subaru','mazda','skoda','toyota','subaru','mazda','skoda'),
fun = c(2,4,3,6,2,4,2,3))
df %>%
pivot_wider(
id_cols = food,
names_from = c(car, binary),
values_from = fun)
Run Code Online (Sandbox Code Playgroud)
如果我们想更改新变量名称的格式,例如从toyota_yes
到yes_toyota
,我们使用names_glue
参数:
df %>%
pivot_wider(
id_cols = food,
names_from = c(car, binary),
names_glue = "{binary}_{car}",
values_from = fun)
Run Code Online (Sandbox Code Playgroud)
我面临的问题是找到正确的语法将变量名称传递给参数names_glue
。将变量传递给 很容易names_from
,例如:
var1 <- 'car'
var2 <- 'binary'
df %>%
pivot_wider(
id_cols = food,
names_from = c(var1, var2),
values_from = fun)
Run Code Online (Sandbox Code Playgroud)
但我们不能直接这样做 …
我想使用实用程序函数来检查给定的列中是否存在给定的data.frame
. 我在 tidyverse 中穿梭。到目前为止我想出的最好的是
library(magrittr)
columnExists <- function(data, col) {
tryCatch({
rlang::as_label(rlang::enquo(col)) %in% names(data)
},
error=function(e) FALSE
)
}
Run Code Online (Sandbox Code Playgroud)
这适用于全球环境
> mtcars %>% columnExists(mpg)
[1] TRUE
> mtcars %>% columnExists(bad)
[1] FALSE
Run Code Online (Sandbox Code Playgroud)
但当从另一个函数中调用时则不然,这是我的实际用例
outerFunction <- function(d, col) {
d %>% columnExists((col))
}
> mtcars %>% outerFunction(mpg) # Expected TRUE
[1] FALSE
> mtcars %>% outerFunction(bad) # Expected FALSE
[1] FALSE
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?是否有可能有一个函数在全局环境中以及嵌套在另一个函数中时也能正常工作?
我发现了几篇与检查给定列是否存在相关的帖子,但它们似乎都假设列名将作为字符串传递,或者检查存在的调用不是嵌套的(或两者兼而有之)。这里情况不同。