【问题标题】:Passing (function) user-specified column name to dplyr do()将(函数)用户指定的列名传递给 dplyr do()
【发布时间】:2023-03-31 04:31:01
【问题描述】:

原始问题

谁能向我解释为什么 unquote 在下面不起作用?

我想在 dplyr 的 0.7.4 版本中调用 do 时传递(函数)用户指定的列名。与使用 do_ 的旧标准评估方法相比,这似乎没有那么尴尬。一个基本(成功)示例忽略在此处使用 do 是非常不必要的事实将类似于:

sum_with_do <- function(D, x, ...) {
    x <- rlang::ensym(x)
    gr <- quos(...)

    D %>%
        group_by(!!! gr) %>%
        do(data.frame(y=sum(.[[quo_name(x)]])))
}

D <- data.frame(group=c('A','A','B'), response=c(1,2,3))
sum_with_do(D, response, group)

# A tibble: 2 x 2
# Groups:   group [2]
  group     y
  <fct> <dbl>
1 A        3.
2 B        3.

从 dplyr 0.7.5 开始,rlang:: 是不必要的,现在导出 ensym。我已经将 Lionel 关于在此处使用 ensym 而不是 enquo 的建议包括在内,因为前者保证了 x 的值是一个符号(而不是表达式)。

在这里取消引用没有用(例如其他dplyr examples),将上面的quo_name(x)替换为!! x会产生以下错误:

Error in ~response : object 'response' not found

说明

根据接受的响应,根本原因是do 没有在其他 dplyr 函数(例如mutate)使用的相同环境中评估表达式。

我从文档或源代码中都没有发现这一点非常清楚(例如,比较 mutate and do for data.frames 的源代码,如果你愿意,可以跟着 Alice 走下兔子洞),但本质上 - 这可能不是什么新鲜事对大多数人来说;

  • do 在其父环境是调用环境的环境中计算表达式,并将 data.frame 的当前组(切片)附加到符号 .,并且;
  • 其他 dplyr 函数“或多或少”评估 data.frame 环境中的表达式,其中 parent 是调用环境。

另请参阅Advanced R. 22. Evaluation,了解有关“数据屏蔽”的说明。

【问题讨论】:

    标签: r dplyr tidyeval


    【解决方案1】:

    这是因为常规的do() 语义,除了. 之外没有数据屏蔽:

    do(df, data.frame(y = sum(.$response)))
    #>   y
    #> 1 6
    
    do(df, data.frame(y = sum(.[[response]])))
    #> Error: object 'response' not found
    

    因此您只需将裸列名称捕获为字符串,无需取消引用,因为没有数据屏蔽:

    sum_with_do <- function(df, x, ...) {
      # ensym() guarantees that `x` is a simple column name and not a
      # complex expression:
      x <- as.character(ensym(x))
    
      df %>%
        group_by(...) %>%
        do(data.frame(y = sum(.[[x]])))
    }
    

    【讨论】:

    • 我不明白你所说的数据屏蔽是什么意思。
    • 这时候就可以直接参考数据了。我们称其为数据屏蔽,因为数据列的优先级(屏蔽)高于用户定义的对象。这类似于包对象如何相互屏蔽以及全局工作区中的对象如何屏蔽包对象。
    • 你的意思是传递给mutate()这样的函数的表达式是在data.frame的环境中计算的,而传递给do()的表达式是在不同的环境中计算的?跨度>
    • 对,do() 环境只包含代词.
    猜你喜欢
    • 1970-01-01
    • 2017-09-12
    • 1970-01-01
    • 2018-03-18
    • 2018-05-09
    • 1970-01-01
    • 2017-09-14
    • 1970-01-01
    • 2021-01-19
    相关资源
    最近更新 更多