说我有这个data.frame
data <- data.frame(foo = c(1, 1, 2, 2 ),
bar = c(10,10,10,20),
baz = c(1, 2, 3, 4 ),
qux = c(5, 6, 7, 8 ))
我希望按foo
和bar
列对其进行分组,以达到此目的:
expected <- list(
data.frame(foo = c(1, 1),
bar = c(10, 10),
baz = c(1, 2),
qux = c(5, 6)),
data.frame(foo = 2,
bar = 10,
baz = 3,
qux = 7),
data.frame(foo = 2,
bar = 20,
baz = 4,
qux = 8)
)
我可以为每个组生成一个行,但是我找不到MATCH
函数;当给定具有列foo,bar,baz,qux
的输入框架和具有列foo,bar
的过滤器框架时,返回foo,bar
单元格内容匹配的行。
groups <- unique(data[c("foo","bar")])
MATCH(data, groups[1,]) == expected[[1]]
MATCH(data, groups[2,]) == expected[[2]]
MATCH(data, groups[3,]) == expected[[3]]
或更高级GROUP
函数,它只返回一个框架列表,其中给定的列匹配:
GROUP(data, by=c("foo","bar")) == expected
我最接近的是
out <- aggregate(. ~ foo + bar, data, list)
单元格baz
,qux
是列表:
> out
foo bar baz qux
1 1 10 1, 2 5, 6
2 2 10 3 7
3 2 20 4 8
> class(out[,"baz"])
[1] "list"
因此,每个组都在out
中排成一行,但是如何再次展开这一行,以便out[1,]
成为一个包含两行的data.frame,例如expected[[1]]
?
答案 0 :(得分:7)
看起来你只需要split
。
选项1 :保留“foo”和“bar”组合的所有“级别”,即使它导致空data.frame
。
> split(data, list(data$foo, data$bar))
$`1.10`
foo bar baz qux
1 1 10 1 5
2 1 10 2 6
$`2.10`
foo bar baz qux
3 2 10 3 7
$`1.20`
[1] foo bar baz qux
<0 rows> (or 0-length row.names)
$`2.20`
foo bar baz qux
4 2 20 4 8
选项2 :删除“foo”和“bar”组合的空“级别” - 就像在预期输出中一样。
> split(data, list(data$foo, data$bar), drop=TRUE)
$`1.10`
foo bar baz qux
1 1 10 1 5
2 1 10 2 6
$`2.10`
foo bar baz qux
3 2 10 3 7
$`2.20`
foo bar baz qux
4 2 20 4 8
答案 1 :(得分:3)
dlply
的 plyr
就是为此目的而设计的:
require(plyr)
dlply( data , .(foo , bar) )
$`1.10`
foo bar baz qux
1 1 10 1 5
2 1 10 2 6
$`2.10`
foo bar baz qux
1 2 10 3 7
$`2.20`
foo bar baz qux
1 2 20 4 8
答案 2 :(得分:0)
试试这个,就像@Ananda的解决方案,但使用interaction
:
> split(data,interaction(data$foo,data$bar))
$`1.10`
foo bar baz qux
1 1 10 1 5
2 1 10 2 6
$`2.10`
foo bar baz qux
3 2 10 3 7
$`1.20`
[1] foo bar baz qux
<0 rækker> (eller 0-længde row.names)
$`2.20`
foo bar baz qux
4 2 20 4 8
> split(data,interaction(data$foo,data$bar), drop=TRUE)
$`1.10`
foo bar baz qux
1 1 10 1 5
2 1 10 2 6
$`2.10`
foo bar baz qux
3 2 10 3 7
$`2.20`
foo bar baz qux
4 2 20 4 8