我试图将我对plyr的理解转移到dplyr,但我无法弄清楚如何按多列分组 .
# make data with weird column names that can't be hard coded
data = data.frame(
asihckhdoydkhxiydfgfTgdsx = sample(LETTERS[1:3], 100, replace=TRUE),
a30mvxigxkghc5cdsvxvyv0ja = sample(LETTERS[1:3], 100, replace=TRUE),
value = rnorm(100)
)
# get the columns we want to average within
columns = names(data)[-3]
# plyr - works
ddply(data, columns, summarize, value=mean(value))
# dplyr - raises error
data %.%
group_by(columns) %.%
summarise(Value = mean(value))
#> Error in eval(expr, envir, enclos) : index out of bounds
将plyr示例转换为dplyr-esque语法我缺少什么?
Edit 2017 :Dplyr已更新,因此可以使用更简单的解决方案 . 查看当前选择的答案 .
9 回答
dplyr对此的支持目前相当薄弱,最终我认为语法类似于:
但那可能不会存在一段时间(因为我需要考虑所有后果) .
在此期间,您可以使用
regroup()
,其中包含符号列表:如果您有列名称的字符向量,则可以使用
lapply()
和as.symbol()
将它们转换为正确的结构:自此问题发布以来,dplyr添加了范围版本的
group_by
(documentation here) . 这使您可以使用与select
相同的函数,如下所示:您的示例问题的输出符合预期(请参阅上面的plyr和下面的输出的比较):
请注意,由于
dplyr::summarize
一次只剥离一层分组,因此您仍然会在生成的分组中进行一些分组(有时可能会让人感到困惑) . 如果您希望绝对安全地避免意外的分组行为,您可以在汇总后始终将%>% ungroup
添加到管道中 .如果你传递对象(好吧,你不是,但是......)而不是作为一个字符向量,它是有效的:
df
是你的data
.?group_by
说:我解释为不是名字的字符版本,而是如何在
foo$bar
中引用它们;这里没有引用bar
. 或者你如何引用公式中的变量:foo ~ bar
.@Arun还提到你可以这样做:
但是你不能传递一些未评估的东西不是数据对象中变量的名称 .
我认为这是由于Hadley用于查找通过
...
参数传递的内容的内部方法 .这里的答案中缺少的一个(微小的)案例,我希望明确表示,分组变量是在流水线的中游动态生成的:
这基本上说明了如何使用
grep
与group_by_(.dots = ...)
一起实现这一点 .现在,
dplyr
函数的变体支持dplyr
中列的字符串规范,其名称以下划线结尾 . 例如,对应于group_by
函数,有一个group_by_
函数可以接受字符串参数 . This vignette详细描述了这些函数的语法 .下面的代码片段干净地解决了@sharoz最初提出的问题(注意需要写出
.dots
参数):(请注意,dplyr现在使用
%>%
运算符,并且不推荐使用%.%
) .为了完整地编写代码,这里是关于Hadley使用新语法的答案的更新:
输出:
在dplyr完全支持字符串参数之前,这个要点可能很有用:
https://gist.github.com/skranz/9681509
它包含一堆使用字符串参数的包装器函数,如s_group_by,s_mutate,s_filter等 . 您可以将它们与正常的dplyr函数混合使用 . 例如
使用
.dots
参数作为dplyr::group_by
函数的字符向量输入的一般示例:或者没有分组变量的硬编码名称(由OP询问):
以OP为例:
另见dplyr vignette on programming,它解释了代词,quasiquotation,quosures和tidyeval .