以编程方式在变量变量上调用group_by()

时间:2015-02-08 00:22:12

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

使用dplyr,我想通过一个我可以改变的变量来总结[sic](例如在循环或apply-style命令中)。

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

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

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

2 个答案:

答案 0 :(得分:11)

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

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

来自new features in dplyr 0.3

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

答案 1 :(得分:0)

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

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 ) )