我试图将我对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语法,我会遗漏什么?
编辑2017:Dplyr已经更新,因此可以使用更简单的解决方案。查看当前选择的答案。
发布于 2017-07-07 00:46:53
自从这个问题发布后,dplyr添加了group_by
的作用域版本(documentation here)。这使您可以使用与select
相同的函数,如下所示:
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]
library(dplyr)
df1 <- data %>%
group_by_at(vars(one_of(columns))) %>%
summarize(Value = mean(value))
#compare plyr for reference
df2 <- plyr::ddply(data, columns, plyr::summarize, value=mean(value))
table(df1 == df2, useNA = 'ifany')
## TRUE
## 27
您的示例问题的输出与预期一致(参见与上面的plyr和下面的输出的比较):
# A tibble: 9 x 3
# Groups: asihckhdoydkhxiydfgfTgdsx [?]
asihckhdoydkhxiydfgfTgdsx a30mvxigxkghc5cdsvxvyv0ja Value
<fctr> <fctr> <dbl>
1 A A 0.04095002
2 A B 0.24943935
3 A C -0.25783892
4 B A 0.15161805
5 B B 0.27189974
6 B C 0.20858897
7 C A 0.19502221
8 C B 0.56837548
9 C C -0.22682998
请注意,由于dplyr::summarize
一次只剥离了一层分组,因此在生成的tibble中仍然有一些分组正在进行(这有时会让人感到惊讶,后来会出人意料)。如果您想绝对安全地避免意外的分组行为,您始终可以在汇总之后将%>% ungroup
添加到您的管道中。
发布于 2015-01-28 07:58:42
为了完整地编写代码,这里使用新语法更新Hadley的答案:
library(dplyr)
df <- data.frame(
asihckhdoydk = sample(LETTERS[1:3], 100, replace=TRUE),
a30mvxigxkgh = sample(LETTERS[1:3], 100, replace=TRUE),
value = rnorm(100)
)
# Columns you want to group by
grp_cols <- names(df)[-3]
# Convert character vector to list of symbols
dots <- lapply(grp_cols, as.symbol)
# Perform frequency counts
df %>%
group_by_(.dots=dots) %>%
summarise(n = n())
输出:
Source: local data frame [9 x 3]
Groups: asihckhdoydk
asihckhdoydk a30mvxigxkgh n
1 A A 10
2 A B 10
3 A C 13
4 B A 14
5 B B 10
6 B C 12
7 C A 9
8 C B 12
9 C C 10
发布于 2014-01-21 04:42:31
目前在dplyr中对此的支持非常弱,最终我认为其语法将是这样的:
df %.% group_by(.groups = c("asdfgfTgdsx", "asdfk30v0ja"))
但这可能不会有一段时间(因为我需要考虑所有的后果)。
同时,您可以使用regroup()
,它接受一个符号列表:
library(dplyr)
df <- data.frame(
asihckhdoydk = sample(LETTERS[1:3], 100, replace=TRUE),
a30mvxigxkgh = sample(LETTERS[1:3], 100, replace=TRUE),
value = rnorm(100)
)
df %.%
regroup(list(quote(asihckhdoydk), quote(a30mvxigxkgh))) %.%
summarise(n = n())
如果您有一个列名的字符矢量,可以使用lapply()
和as.symbol()
将它们转换为正确的结构
vars <- setdiff(names(df), "value")
vars2 <- lapply(vars, as.symbol)
df %.% regroup(vars2) %.% summarise(n = n())
https://stackoverflow.com/questions/21208801
复制相似问题