用plyr方法对列表进行子集操作?

5
我经常有按一个或多个变量分组的数据,每个组内有多个注册。我希望从数据框中按各种标准选择组。
我通常使用split-sapply-rbind方法,使用逻辑向量从列表中提取元素。
以下是一个小例子。我从一个具有一个分组变量(“group”)的数据框开始,并希望选择具有最大质量小于45的组:
dd <- data.frame(group = rep(letters[1:3], each = 5), 
                 mass = c(rnorm(5, 30), rnorm(5, 50), 
                          rnorm(5, 40)))
    dd2 <- split(x = dd, f = dd$group)
    dd3 <- dd2[sapply(dd2, function(x) max(x$mass) < 45)]
    dd4 <- do.call(rbind, dd3)

我刚开始使用plyr,现在我想知道:是否有仅基于plyr的替代方法来实现这个功能?
3个回答

4
在这种情况下,这将得到相同的结果。
library(plyr)
dd5 <- ddply(dd,.(group),function(x) x[max(x$mass)<45,])

all(dd4==dd5)
[1] TRUE

2
甚至更简洁的写法是: ddply(dd, "group", subset, max(mass) < 45) - hadley

3
这里有一个 data.table 的解决方案,可以提高代码的优雅性。
library(data.table)
DT <- data.table(dd)

DT[,if(max(mass) < 45){.SD},by=group]
    group     mass
 1:     a 28.80426
 2:     a 31.31232
 3:     a 29.47599
 4:     a 30.35425
 5:     a 29.92833
 6:     c 40.11349
 7:     c 40.17431
 8:     c 39.94652
 9:     c 39.57524
10:     c 40.20791

也许稍微有些复杂
new <- (DT[,index := max(mass) < 45,by=group][force(index)])[,index:=NULL]

非常感谢mnel的帮助。在我发布原始问题后,我实际上考虑更新并询问“数据表方式”。我一定会进一步了解data.table世界的。 - Henrik

2

我知道你特别要求使用plyr解决方案,但是我想分享一种在基本R中实现此操作的替代方法,它不涉及多步骤:

dd[as.logical(ave(dd$mass, dd$group, FUN = function(x) max(x) < 45)), ]

ave函数通常在R中处理分组数据时很方便。这里,我创建了一个逻辑向量,并根据"TRUE"值的索引进行了子集筛选。


谢谢Ananda!我非常感激你提供的替代方案。 - Henrik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接