如何在tidyverse范围动词或映射器的tidyeval上下文中使用准引用?

时间:2019-02-08 12:27:29

标签: r tidyeval

我在映射器函数中使用特殊运算符:=(冒号)时遇到麻烦。我已经找到了使用tidyverse中的作用域动词的变通方法,但是我想知道在mapper函数中以何种方式实现特殊运算符。

基本上,我想分别使用相关的属性标签来重命名一组变量。我编写了用于重命名单个变量的函数,但无法弄清楚如何使用范围动词变体或映射器以相同的样式编写该函数。

这是我的可复制示例:

我可以重命名一个变量:

library(tidyverse)
library(sjlabelled)
library(rlang) 

data(efc)

dat <- efc %>%
  rename(!!paste("c12hour", get_label(., c12hour), sep = "_") := c12hour)

# c12_hour becomes this:
names(dat[1])
[1] "c12hour_average number of hours of care per week"

我想将此功能应用于限定范围的动词rename_all,我认为它看起来像这样,但会导致错误:

dat <- efc %>%
  rename_all(~!!paste(., get_label(.), sep = "_") := .)
Error: `:=` can only be used within a quasiquoted argument

当我尝试使用映射器时也会出现此错误:

geo_rename <- as_mapper(~rename(!!paste(., get_label(.), sep = "_") := .))

dat <- efc %>%
  map_dbl(., geo_rename)
Error: `:=` can only be used within a quasiquoted argument
Call `rlang::last_error()` to see a backtrace

我猜想问题出在:=运算符的使用上,该运算符是为tidyeval框架中出现的准报价问题而发明的。我在函数式编程中使用错了吗?

我找到了一种解决方法,将要粘贴的标签保存在命名列表中:

dat <- efc

dat_labels <- get_label(dat)
dat_recode <- as.list(as.character(dat_labels))
names(dat_recode) <- get_label(dat)

dat <- efc %>%
  select_all(~paste(., dat_recode, sep = "_"))

但是我想知道如何在函数式编程中使用:=。在哈德利·威克汉姆(Hadley Wickham)的书中,它很快被引入,但没有用在范围动词或映射器函数https://adv-r.hadley.nz/quasiquotation.html#tidy-dots

有人可以向我解释吗?

谢谢!

1 个答案:

答案 0 :(得分:0)

诸如rename_all()之类的范围变体不使用整洁的eval。它们就像是purrr或lapply()中的映射器:

mtcars %>% rename_all(toupper)

或者使用lambda函数的公式表示法:

mtcars %>% rename_all(~ toupper(.x))

此外,在rename_all()的情况下,映射函数的输入是列 name ,而不是具有标签属性的列向量。

因此,恐怕您需要找到其他解决方案。整洁的eval和范围变体均不在此问题的解决范围之内。