标签: tidyeval

什么时候使用 rlang::ensym() 而不是 rlang::sym()?

我可以从文档中看到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)

r tidyeval rlang

8
推荐指数
1
解决办法
1333
查看次数

如何使用字符串连接定义收集函数的关键参数

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)

r dplyr tidyeval

7
推荐指数
1
解决办法
251
查看次数

整洁的 eval 与 base 或 get() 与 sym() 与 as.symbol()

一段时间以来,我一直试图了解 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 社区会回避它?

r tidyverse tidyeval rlang

7
推荐指数
1
解决办法
396
查看次数

如何在ggplot geoms中编写带有整齐求值的函数?

我想编写一个在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)

r function ggplot2 tidyeval

7
推荐指数
1
解决办法
80
查看次数

使用dplyr :: filter问题创建R函数

我已经查看了其他答案,但找不到下面代码的解决方案.基本上,我正在创建一个函数,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)

r filter dplyr tidyeval rlang

6
推荐指数
2
解决办法
736
查看次数

如何在`mutate`中的`map`中取消引号(!!)

我正在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)

r dplyr purrr tidyeval rlang

6
推荐指数
1
解决办法
222
查看次数

用dplyr编程时ensym和enquo有什么区别?

相对较新的 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)

r dplyr tidyeval rlang

6
推荐指数
1
解决办法
1023
查看次数

使用“rlang”NSE 按多个变量进行分组

我正在尝试编写一个自定义函数,该函数使用 的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)

r tidyverse tidyeval rlang

6
推荐指数
1
解决办法
445
查看次数

将变量传递到tidyr::pivot_wider 的names_glue 参数中

以下是一些我们使用两个名称进行更广泛旋转的愚蠢数据:

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_yesyes_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)

但我们不能直接这样做 …

r tidyr tidyeval r-glue

6
推荐指数
1
解决办法
6367
查看次数

嵌套函数调用中的 NSE

我想使用实用程序函数来检查给定的列中是否存在给定的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)

我究竟做错了什么?是否有可能有一个函数在全局环境中以及嵌套在另一个函数中时也能正常工作?

我发现了几篇与检查给定列是否存在相关的帖子,但它们似乎都假设列名将作为字符串传递,或者检查存在的调用不是嵌套的(或两者兼而有之)。这里情况不同。

r nse tidyeval

6
推荐指数
1
解决办法
91
查看次数

标签 统计

r ×10

tidyeval ×10

rlang ×6

dplyr ×4

tidyverse ×2

filter ×1

function ×1

ggplot2 ×1

nse ×1

purrr ×1

r-glue ×1

tidyr ×1