【问题标题】:Programmatically calling group_by() on a varying variable以编程方式在变量上调用 group_by()
【发布时间】:2015-04-07 23:21:50
【问题描述】:

使用 dplyr,我想通过一个我可以改变的变量来总结 [原文如此](例如,在循环或应用样式命令中)。

直接输入名称可以正常工作:

library(dplyr)
ChickWeight %>% group_by( Chick, Diet ) %>% summarise( mw = mean( weight ) )

group_by 不是为获取字符向量而编写的,因此传递结果更难。

v <- "Diet"
ChickWeight %>% group_by( c( "Chick", v ) ) %>% summarise( mw = mean( weight ) )
## Error

我将发布一个解决方案,但很想看看其他人是如何解决这个问题的。

【问题讨论】:

  • :-) summarize [sic] +1
  • 只做group_by_( c( "Chick", v ) ) 而不是group_by( c( "Chick", v ) )....
  • 当然,如果 dplyr 无法做到这一点,您也可以使用 data.table 轻松做到这一点 :) 就像在 library(data.table) ; as.data.table(ChickWeight)[, .(mw = mean(weight)), c("Chick", v)] 中一样
  • @KonradRudolph - 我也使用summarise,主要是因为没有summarize_each。少一件我必须记住的事情。
  • @Richard 在 Hadley 的图书馆中使用英国英语是一个不幸(= 糟糕)的决定。 API 应该是统一的,而不是个性化的。我喜欢在我所有的写作中使用英式拼写,但我在我的代码中坚持统一、成熟的美式拼写。当其他代码违反该规则时,这非常烦人并且违反了 API 设计的各种原则(非英语编程语言通常被视为失败的实验是有原因的)。因此,我强烈建议遵守美国拼写(缺少summarize_each 可能是疏忽)。

标签: r group-by dplyr split-apply-combine


【解决方案1】:

dplyr 的下划线功能可能对此有用:

ChickWeight %>% group_by_( "Chick", v )  %>% summarise( mw = mean( weight ) )

来自new features in dplyr 0.3

您现在可以使用 dplyr 进行编程 - 每个使用非标准评估 (NSE) 的函数还有一个以 _ 结尾的标准评估 (SE) 双胞胎。例如,SE 版本的 filter() 称为 filter_()。每个函数的 SE 版本都有类似的参数,但它们必须明确地“引用”。

【讨论】:

    【解决方案2】:

    这是一个解决方案,以及我是如何解决的。

    group_by 期望什么?

    > group_by
    function (x, ..., add = FALSE) 
    {
        new_groups <- named_dots(...)
    

    兔子洞:

    > dplyr:::named_dots
    function (...) 
    {
        auto_name(dots(...))
    }
    <environment: namespace:dplyr>
    > dplyr:::auto_name
    function (x) 
    {
        names(x) <- auto_names(x)
        x
    }
    <environment: namespace:dplyr>
    > dplyr:::auto_names
    function (x) 
    {
        nms <- names2(x)
        missing <- nms == ""
        if (all(!missing)) 
            return(nms)
        deparse2 <- function(x) paste(deparse(x, 500L), collapse = "")
        defaults <- vapply(x[missing], deparse2, character(1), USE.NAMES = FALSE)
        nms[missing] <- defaults
        nms
    }
    <environment: namespace:dplyr>
    > dplyr:::names2
    function (x) 
    {
        names(x) %||% rep("", length(x))
    }
    

    使用这些信息,如何着手制定解决方案?

    # Naive solution fails:
    ChickWeight %>% do.call( group_by, list( Chick, Diet ) ) %>% summarise( mw = mean( weight ) )
    
    # Slightly cleverer:
    do.call( group_by, list( x = ChickWeight, Chick, Diet, add = FALSE ) ) %>% summarise( mw = mean( weight ) )
    ## But still fails with,
    ## Error in do.call(group_by, list(x = ChickWeight, Chick, Diet, add = FALSE)) : object 'Chick' not found
    

    解决方案在于引用参数,以便将它们的评估延迟到包含x tbl 的环境中:

    do.call( group_by, list( x = ChickWeight, quote(Chick), quote(Diet), add = FALSE ) ) %>% summarise( mw = mean( weight ) )
    ## Bingo!
    v <- "Diet"
    do.call( group_by, list( x = ChickWeight, quote(Chick), substitute( a, list( a = v ) ), add = FALSE ) ) %>% summarise( mw = mean( weight ) )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-14
      • 2011-01-08
      • 1970-01-01
      相关资源
      最近更新 更多