在R中选择组内变量最大值的行

9
a.2<-sample(1:10,100,replace=T)
b.2<-sample(1:100,100,replace=T)
a.3<-data.frame(a.2,b.2)

r<-sapply(split(a.3,a.2),function(x) which.max(x$b.2))

a.3[r,]

返回的是列表索引,而不是整个数据框的索引。

我试图为每个 a.2 子组返回最大的 b.2 值。如何高效地实现?


melt(a.3,id=c("a.2"))->h.2; cast(h.2,a.2~,max)在这个例子中确实起到了作用,但是当我将其应用于我的原始数据集时,计算机会耗尽内存,所以并没有真正帮助我。 - Misha
6个回答

10

ddplyave方法都很耗费资源。在当前问题中(67,608行,有四列用于定义唯一键),ave由于内存不足而失败。 tapply是一个方便的选择,但我通常需要选择每个唯一键最大(或最小)某值的所有整行(通常由多个列定义)。我找到的最佳解决方案是排序,然后使用duplicated的否定来仅选择每个唯一键的第一行。对于这里的简单示例:

a <- sample(1:10,100,replace=T)
b <- sample(1:100,100,replace=T)
f <- data.frame(a, b)

sorted <- f[order(f$a, -f$b),]
highs <- sorted[!duplicated(sorted$a),]

我认为相比于aveddply,性能提升是相当大的。对于多列键来说,稍微有点复杂,但order可以处理许多需要排序的内容,而duplicated可以用于数据框,因此可以继续使用这种方法。


这是最容易使用的,对于多列也非常有效--你所需要做的就是在duplicated内部使用cbind - Josephine Moeller

8
library(plyr)
ddply(a.3, "a.2", subset, b.2 == max(b.2))

我尝试使用ddply函数,但它非常慢。我没有测量时间,但它持续了一杯咖啡和一趟洗手间的时间,而ave版本在我的原始数据集(210列*16000行)中只用了0.2秒。 - Misha
1
下一个版本会解决这个问题。但是,除非您提供一个现实的例子,否则您不能期望得到适用于您的数据的答案! - hadley

6
a.2<-sample(1:10,100,replace=T)
b.2<-sample(1:100,100,replace=T)
a.3<-data.frame(a.2,b.2)

Jonathan Chang的回答给出了你明确要求的内容,但我猜你想要的是数据框中实际的行。
sel <- ave(b.2, a.2, FUN = max) == b.2
a.3[sel,]

我必须承认,那要简单得多了。然而,== b.2 的逻辑超出了我的理解范围... - Misha
ave 生成一个向量,其中仅包含每个 a.2 的 b.2 最大值。因此,当 it == b.2 时,只要数据框具有行,就会设置真值。您可以使用逻辑向量选择数据框中的行。如果您想查看它的工作方式,请将 ave 命令的结果添加到您的数据框中并查看它,与 b.2 列进行比较--a.3$b.max <- ave(b.2, a.2, FUN = max)。此外,您可以创建 sel 变量,并在上下文中查看它--a.3$sel <- a.3$b.2 == a.3$b.max。 - John

1
a.2<-sample(1:10,100,replace=T)
b.2<-sample(1:100,100,replace=T)
a.3<-data.frame(a.2,b.2)
m<-split(a.3,a.2)
u<-function(x){
    a<-rownames(x)
    b<-which.max(x[,2])
    as.numeric(a[b])
    }
r<-sapply(m,FUN=function(x) u(x))

a.3[r,]

这个方法虽然有点繁琐,但是它可以让我获取分组最大值的行。还有其他想法吗?


1
> a.2<-sample(1:10,100,replace=T)
> b.2<-sample(1:100,100,replace=T)
> tapply(b.2, a.2, max)
 1  2  3  4  5  6  7  8  9 10 
99 92 96 97 98 99 94 98 98 96 

0
a.2<-sample(1:10,100,replace=T)
b.2<-sample(1:100,100,replace=T)
a.3<-data.frame(a.2,b.2)

使用aggregate,您可以在一行中获取每个组的最大值:

aggregate(a.3, by = list(a.3$a.2), FUN = max)

这将产生以下输出:

   Group.1 a.2 b.2
1        1   1  96
2        2   2  82
...
8        8   8  85
9        9   9  93
10      10  10  97

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