【问题标题】:Using rlang Package to Parse Quoted Argument使用 rlang 包解析引用的参数
【发布时间】:2019-04-15 17:44:11
【问题描述】:

我希望将单个参数字符串拆分为两个参数,并在函数的不同部分中使用每个参数。

是否可以使用 quasiquotation (!!) 或其他 rlang 函数来做到这一点?

谢谢!

数据:

person <- tibble(id = 1, age = 20)
friends <- tibble(id = c(2, 3, 4, 5), age = c(48, 29, 20, 48))

(无功能)功能:

different_age_friends <- function(condition, person = person, friends = friends ) {

  person <- person
  friends <- friends

  condition <- str_split(condition, " ~ ", simplify = T)
  condition_statement <- condition[1]
  filter_statement <- condition[2]

  if(!!condition_statement) {
    different_age_friends <- friends %>%
      filter(!!filter_statement)
  }

  return(return_same_age_friends)
}

致电:

different_age_friends(condition = "age == 20 ~ age == 48")

期望的输出

id age
2  48
5  48

【问题讨论】:

  • 这并不能解决问题,但您有 condition = TRUE 在您想要 condition == TRUE 或只是 condition 的地方进行比较
  • 另外,我不清楚条件和过滤器之间的区别。我不明白这两种类型的陈述之间有什么本质上的不同。您是否尝试针对person 测试条件,然后如果为真,则使用第二部分过滤friends
  • 是的,谢谢你的澄清!

标签: r tidyverse rlang


【解决方案1】:

使用rlang::parse_expr 将字符串转换为表达式,使用eval 对它们求值。 eval() 允许您在其第二个参数中为表达式提供上下文,我们在其中向它提供 person 数据框。在filter 的情况下,上下文已经被理解为%&gt;% 管道左侧的数据帧。

我们处理这两个表达式的另一个区别是filter() 有一个额外的内部层quasiquoation。由于您已经有一个表达式,因此不需要再次引用它,因此您可以使用 !! 取消引用它。

different_age_friends <- function(condition, p = person, f = friends) 
{
  stmts <- str_split(condition, " ~ ")[[1]] %>% map( rlang::parse_expr )

  if( eval(stmts[[1]], p) )         # Effectively: eval(age == 20, person)
    f %>% filter(!!stmts[[2]])      # Effectively: friends %>% filter(age == 48)
  else
    f
}

different_age_friends(condition = "age == 20 ~ age == 48")
# # A tibble: 2 x 2
#      id   age
#   <dbl> <dbl>
# 1     2    48
# 2     5    48

小提示:

  • 当条件为假时,您没有为different_age_friends 提供值。我做了一个假设,在这种情况下,将返回整个朋友列表。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-08
    • 1970-01-01
    • 1970-01-01
    • 2016-04-09
    • 2014-06-07
    • 2018-07-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多