首页 > 解决方案 > R 在胶水语句中使用 bang-bang

问题描述

我想制作一个简单的函数,该函数采用数据框和用户为该数据框中的两列提供的名称。目的是允许它轻松地与dplyr管道一起工作。它将生成粘合字符串的字符向量:

func <- function(data, last, first) {
  last <- rlang::enquo(last)
  first <- rlang::enquo(first)
  
  glue::glue_data(data, "{!!last}, {!!first}")
}

理想情况下,我希望用户能够调用:

df %>% func(lastName, firstName)

这将产生一个包含多个值的字符向量,格式为Smith, John.

我的功能目前不起作用,因为 bang-bang 运算符在glue_data. 如何在仍然使用 NSE 的同时解决这个问题?我收到的错误是:

Error: Quosures can only be unquoted within a quasiquotation context.

代表:

df <- data.frame(lastName = c("Smith", "Bond", "Trump"), firstName = c("John","James","Donald"))

> df
  lastName firstName
1    Smith      John
2     Bond     James
3    Trump    Donald

预期输出

> glue::glue_data(df, "{lastName}, {firstName}")

Smith, John
Bond, James
Trump, Donald

但是,我希望能够通过使用我的函数并调用来实现预期的输出:

df %>% func(lastName, firstName)

以上是我实际用例的简化版本,我实际上将glue在后续函数中将该语句作为参数调用:

biggerfn <- function(data, subject, first, last) {
  subject <- rlang::enquo(subject)
  first <- rlang::enquo(first)
  last <- rlang::enquo(last)
  
  data %>%
    dplyr::distinct(!!subject, !!first, !!last) %>%
    smallerfunc(!!subject, glue::glue_data(data, "{!!last}, {!!first}"))
}

标签: rrlangnser-glue

解决方案


我不知道您是否致力于glue,但这可以使用以下方法轻松完成tidyr::unite

func <- function(data, last, first) {
    data %>%
        tidyr::unite(result, {{last}}, {{first}}, sep=", ")
}

df %>% func(lastName, firstName)
#           result
#  1   Smith, John
#  2   Bond, James
#  3 Trump, Donald

# Optionally, follow up with: 
#   %>% dplyr::pull(result)
# to retrieve the column

这里,{{x}}是 的简写!!enquo(x)


推荐阅读