标签: rlang

为什么在 R 中只有 `case_when` 给出不同的结果?

dplyr::case_when当我使用而不是if参考本文时,我注意到下面的这种行为。如果第二个分支的输出是显式字符串,则它会按预期工作,但如果x指定了其本身,则结果会发生变化。

为什么只case_when给出不同的结果?

x <- character(0)

dplyr::case_when(rlang::is_empty(x) ~ "Empty", !rlang::is_empty(x) ~ "Not empty")
#> [1] "Empty"
dplyr::case_when(rlang::is_empty(x) ~ "Empty", !rlang::is_empty(x) ~ x)
#> character(0)

if (rlang::is_empty(x)) "Empty" else if (!rlang::is_empty(x)) "Not empty"
#> [1] "Empty"
if (rlang::is_empty(x)) "Empty" else if (!rlang::is_empty(x)) x
#> [1] "Empty"

ifelse(rlang::is_empty(x), "Empty", "Not empty")
#> [1] "Empty"
ifelse(rlang::is_empty(x), "Empty", x)
#> [1] "Empty"
Run Code Online (Sandbox Code Playgroud)

由reprex 包于 2022 年 8 月 16 日创建(v2.0.1)

r dplyr rlang

14
推荐指数
1
解决办法
703
查看次数

dplyr 0.7.0 tidyeval in package

前言

我通常dplyr在我的包中使用.在此之前0.7.0,我使用dplyr动词的强调版本来避免在注释期间R CMD CHECK.例如,代码:

x <- tibble::tibble(v = 1:3, w = 2)
y <- dplyr::filter(x, v > w)
Run Code Online (Sandbox Code Playgroud)

本来会产生这样的R CMD CHECK说明:

* checking R code for possible problems ... NOTE
no visible binding for global variable ‘v’
Run Code Online (Sandbox Code Playgroud)

相比之下,使用标准评估版:

y <- dplyr::filter_(x, ~v > w)
Run Code Online (Sandbox Code Playgroud)

没有发出这样的说明.

但是,使用dplyr编程dplyr 0.7.0的插图表示在包中包含函数的适当语法(以避免注释)是:dplyr

y <- dplyr::filter(x, .data$v > .data$w)
Run Code Online (Sandbox Code Playgroud)

因此,新闻文件说"不再需要每个主要动词的强调版本,因此这些功能已被弃用(但为了向后兼容性而保持不变)."

小插图说上面的新语法不会产生R CMD checkNOTES,"只要你还导入rlang::.data@importFrom rlang …

r dplyr r-package tidyeval rlang

13
推荐指数
1
解决办法
529
查看次数

定制管道以消除警告

此问题相关.

我想构建一个自定义管道%W>%,可以使一个操作的警告静音

library(magrittr)
data.frame(a= c(1,-1)) %W>% mutate(a=sqrt(a)) %>% cos
Run Code Online (Sandbox Code Playgroud)

将相当于:

w <- options()$warn
data.frame(a= c(1,-1)) %T>% {options(warn=-1)} %>%
  mutate(a=sqrt(a))    %T>% {options(warn=w)}  %>%
  cos
Run Code Online (Sandbox Code Playgroud)

这两次尝试不起作用:

`%W>%` <- function(lhs,rhs){
  w <- options()$warn
  on.exit(options(warn=w))
  options(warn=-1)
  lhs %>% rhs
}

`%W>%` <- function(lhs,rhs){
  lhs <- quo(lhs)
  rhs <- quo(rhs)
  w <- options()$warn
  on.exit(options(warn=w))
  options(warn=-1)
  (!!lhs) %>% (!!rhs)
}
Run Code Online (Sandbox Code Playgroud)

我怎么能把rlang它变成有效的东西呢?

r dplyr magrittr rlang

13
推荐指数
1
解决办法
636
查看次数

基于tidyeval的非标准评估在mutate右侧重新编码中的使用

考虑一个小标题,其中每一列都是可以采用许多值的字符向量-假设是“ A”到“ F”。

library(tidyverse)
sample_df <- tibble(q1 = c("A", "B", "C"), q2 = c("B", "B", "A"))
Run Code Online (Sandbox Code Playgroud)

我希望创建一个函数,该函数将列名作为参数,并重新编码该列,以使任何答案“ A”都变为NA,否则将按原样返回df。以这种方式设计它的原因是适合于使用给定列执行一系列操作的更广泛的管道。

有很多方法可以做到这一点。但是我有兴趣了解最佳的惯用tidy_eval / tidyverse方法是什么。首先,问题名称必须位于变异动词的左侧,因此我们适当地使用!!and :=运算符。但是,那该放在右边呢?

fix_question <- function(df, question) {
    df %>% mutate(!!question := recode(... something goes here...))
}

fix_question(sample_df, "q1") # should produce a tibble whose first column is (NA, "B", "C")
Run Code Online (Sandbox Code Playgroud)

我最初的想法是,这将起作用:

df %>% mutate(!!question := recode(!!question, "A" = NA_character_))
Run Code Online (Sandbox Code Playgroud)

但是,当然,函数内部的爆炸只是返回文字字符串(例如“ q1”)。我最终采取了一种感觉很拙劣的方法,即使用基本R [[运算符并依靠.dplyr 的构造来在右侧引用数据,并且它起作用了,因此从某种意义上说,我已经解决了我的根本问题:

df %>% mutate(!!question := recode(.[[question]], "A" = NA_character_))
Run Code Online (Sandbox Code Playgroud)

我有兴趣从精通tidyeval的人那里获得反馈,以了解是否有更惯用的方法来执行此操作,希望看到一个可行的示例可以增强我对tidyeval函数集的更一般的理解。有什么想法吗?

r dplyr nse tidyeval rlang

13
推荐指数
3
解决办法
169
查看次数

整洁的评估编程和ggplot2

尝试编写一个相对简单的包装器来生成一些图,但是无法弄清楚如何指定整理评估的分组变量,这些变量被指定为...一个面向变量但不通过分组区分的示例函数...

my_plot <- function(df = starwars,
                    select = c(height, mass),
                    ...){
    results <- list()
    ## Tidyeval arguments
    quo_select <- enquo(select)
    quo_group  <- quos(...)
    ## Filter, reshape and plot
    results$df <- df %>%
                  dplyr::filter(!is.na(!!!quo_group)) %>%
                  dplyr::select(!!quo_select, !!!quo_group) %>%
                  gather(key = variable, value = value, !!!quo_select) %>% 
                  ## Specify what to plot
                  ggplot(aes(value)) +
                  geom_histogram(stat = 'count')  +
                  facet_wrap(~variable, scales = 'free', strip.position = 'bottom')
    return(results)
}
## Plot height and mass as facets but colour histograms by hair_color
my_plot(df …
Run Code Online (Sandbox Code Playgroud)

r ggplot2 dplyr tidyeval rlang

12
推荐指数
1
解决办法
1055
查看次数

'不能在顶层使用`!!!` 是什么意思。是什么意思以及如何解决?

我正在尝试创建一个用于创建棒棒糖图的函数ggplot2。我想将所有参数传递...aes()inside geom_point()。但是,我想排除size传递到aes()内部参数geom_segment()(如果您查看a()下面的输出,原因很明显)。因此,我捕获...usingrlang::enquos()而不是按原样传递它。在功能上a(),我传递dotsaes()ggplot()这个作品没有问题。但在功能上b()我得到了错误Can't use '!!!' at top level.

我被困在这一点上,并感谢任何输入来解决这个问题。

library(ggplot2)
data("mtcars")

d <- dplyr::count(mtcars, cyl, am)

a <- function(data, x, y, ...) {
  x <- rlang::enquo(x)
  y <- rlang::enquo(y)
  dots <- rlang::enquos(...)

  ggplot(data, aes(!!x, !!y, !!!dots)) +
    geom_segment(aes(y = 0, xend = !!x, yend = !!y)) +
    geom_point() …
Run Code Online (Sandbox Code Playgroud)

r ggplot2 non-standard-evaluation tidyverse rlang

12
推荐指数
1
解决办法
1447
查看次数

如何将一个不带引号的列名列表送入`lapply`(以便我可以使用`dplyr`函数)

我正在尝试编写一个函数tidyverse/dplyr,我想最终使用lapply(或map).(我一直在努力回答这个问题,但发现了一个有趣的结果/死胡同.请不要将其标记为重复 - 这个问题是你在那里看到的答案的延伸/背离.)

是否有
1)获取引用变量列表以在dplyr函数内工作
(并且不使用已弃用的SE_函数)的方法, 或者是
2)某种方式通过一个lapply或多个方式提供一个未加引号的字符串列表map

我使用Programming in Dplyr小插图来构建我认为最符合当前使用NSE标准的功能.

样本数据:

sample_data <- 
    read.table(text = "REVENUEID AMOUNT  YEAR REPORT_CODE PAYMENT_METHOD INBOUND_CHANNEL  AMOUNT_CAT
               1 rev-24985629     30  FY18           S          Check            Mail     25,50
               2 rev-22812413      1  FY16           Q          Other      Canvassing   0.01,10
               3 rev-23508794    100  FY17           Q    Credit_card             Web   100,250
               4 rev-23506121    300  FY17           S    Credit_card            Mail   250,500
               5 rev-23550444    100  FY17           S    Credit_card             Web   100,250
               6 rev-21508672 …
Run Code Online (Sandbox Code Playgroud)

r dplyr lazyeval tidyverse rlang

10
推荐指数
1
解决办法
517
查看次数

如何覆盖 R 中的警告

我有一个函数可以生成不需要的警告,但保留该值。

f <- function(a) { 
  
  if (a > 1) { 
    warning("an uninformative warning")
  }
  a
}

g1 <- function(b) {
  
  withCallingHandlers(
    x <-f(b),
    warning = function(w) {
      warning("A more informative warning")
    })
  
  x
}
g1(2)
#> Warning in (function (w) : A more informative warning
#> Warning in f(b): an uninformative warning
#> [1] 2
Run Code Online (Sandbox Code Playgroud)

创建于 2023 年 12 月 12 日,使用reprex v2.0.2

不幸的是,这会出现 2 个警告。

tryCatch()不保留 x 。和withCallingHandlers(),两个警告都会被抛出。

error-handling r rlang

10
推荐指数
1
解决办法
563
查看次数

R quo_name相当于quos

嗨跟随dplyr编程我注意到可以使用quo_name添加名称.我想知道如何为多列执行此操作,例如.像quos_name的种类.例如:

   my_mutate <- function(df, expr) {
  expr <- enquo(expr)
  mean_name <- paste0("mean_", quo_name(expr))
  sum_name <- paste0("sum_", quo_name(expr))

  mutate(df, 
    !!mean_name := mean(!!expr), 
    !!sum_name := sum(!!expr)
  )
}
Run Code Online (Sandbox Code Playgroud)

   my_mutate <- function(df, ...) {
  exprs <-quos(...)
  mean_names <- paste0("mean_", quos_name(exprs))
  sum_names <- paste0("sum_", quos_name(exprs))

  mutate(df, 
    !!!mean_names := mean(!!!exprs), 
    !!!sum_names := sum(!!!exprs)
  )
}
Run Code Online (Sandbox Code Playgroud)

即.为...中指定的所有列添加mean和sum列,当然这仅作为示例,并且quos_names不存在.如果有办法,这将是非常有帮助的.

我知道有可能在data.table中做这样的事情DT[,(Col_names):=lapply(Cols,mean)](这段代码不起作用,但我之前做过类似的事情).

r dplyr nse rlang

9
推荐指数
1
解决办法
626
查看次数

有什么用!!运算符 mean 在 R 中,尤其是在上下文中 !!sym("x")

“!!”是什么意思 在 R 中做,为什么要使用它?

具体来说,我正在查看一个包含短语a = !!sym("x")where "x"is a string的函数 。我认为sym通过将字符串转换为对象来工作,因此a = sym("x")将设置为a等于 object x。有什么!!用?我读到它没有引用它后面的任何内容,但我认为sym它本身没有引用字符串?

我还看到!!与其他功能一起使用。它在做什么?

r operators dplyr rlang

9
推荐指数
1
解决办法
3418
查看次数