汇总给定列上的数据框并显示另一列

我有以下forms的R中的数据框:

> head(data) Group Score Info 1 1 1 a 2 1 2 b 3 1 3 c 4 2 4 d 5 2 3 e 6 2 1 f 

我想要使​​用max函数在Score列之后进行聚合

 > aggregate(data$Score, list(data$Group), max) Group.1 x 1 1 3 2 2 4 

但是我也希望显示与每个组的Score列的最大值相关的Info列。 我不知道如何做到这一点。 我期望的输出将是:

  Group.1 xy 1 1 3 c 2 2 4 d 

任何提示?

首先,你使用split分割数据:

 split(z,z$Group) 

对于每个块,select具有最高分的行:

 lapply(split(z,z$Group),function(chunk) chunk[which.max(chunk$Score),]) 

最后再减less一个data.frame do.call ing rbind

 do.call(rbind,lapply(split(z,z$Group),function(chunk) chunk[which.max(chunk$Score),])) 

结果:

  Group Score Info 1 1 3 c 2 2 4 d 

一行,没有魔法,快,结果有好名字=)

基本的R解决scheme是将aggregate()的输出与merge()步骤结合起来。 我发现公式接口aggregate()比标准接口更有用,部分原因是输出中的名称更好,所以我将使用:

aggregate()步骤是

 maxs <- aggregate(Score ~ Group, data = dat, FUN = max) 

merge()步骤很简单

 merge(maxs, dat) 

这给了我们所需的输出:

 R> maxs <- aggregate(Score ~ Group, data = dat, FUN = max) R> merge(maxs, dat) Group Score Info 1 1 3 c 2 2 4 d 

当然,你可以把它放在一个单线上(中介步骤更多是为了说明):

 merge(aggregate(Score ~ Group, data = dat, FUN = max), dat) 

我使用公式接口的主要原因是它为合并步骤返回了一个正确names的数据框; 这些是来自原始数据集dat的列的名称。 我们需要让aggregate()的输出具有正确的名称,以便merge()知道原始数据框和聚合数据框中的哪些列匹配。

标准接口给出了奇怪的名字,无论你怎么称呼它:

 R> aggregate(dat$Score, list(dat$Group), max) Group.1 x 1 1 3 2 2 4 R> with(dat, aggregate(Score, list(Group), max)) Group.1 x 1 1 3 2 2 4 

我们可以在这些输出上使用merge() ,但是我们需要做更多的工作来告诉R哪些列匹配。

这是一个使用plyr软件包的解决scheme。

下面这行代码基本上告诉ddply首先按Group分组数据,然后在每个组中返回一个子集,其中Score等于该组中的最大分数。

 library(plyr) ddply(data, .(Group), function(x)x[x$Score==max(x$Score), ]) Group Score Info 1 1 3 c 2 2 4 d 

而且,正如@SachaEpskamp指出的那样,这可以进一步简化为:

 ddply(df, .(Group), function(x)x[which.max(x$Score), ]) 

(也有这样的优点,即如果有的话, which.max将返回多个最大线)。

迟到的答案,但使用data.table方法

 library(data.table) DT <- data.table(dat) DT[, .SD[which.max(Score),], by = Group] 

或者,如果有可能有不止一个同样最高的分数

 DT[, .SD[which(Score == max(Score)),], by = Group] 

注意到(来自?data.table

.SD是一个data.table,包含每个组的x个数据的子集,不包括组列(s)

要添加到Gavin的答案:合并之前,可能会得到聚合使用正确的名称时,不使用公式接口:

 aggregate(data[,"score", drop=F], list(group=data$group), mean) 

plyr包可以用于这个。 使用ddply()函数,您可以在一列或多列上分割一个数据框,并应用一个函数并返回一个数据框,然后使用summarize()函数,可以使用分割的数据框的列作为variables来创build新的dataframe/

 dat <- read.table(textConnection('Group Score Info 1 1 1 a 2 1 2 b 3 1 3 c 4 2 4 d 5 2 3 e 6 2 1 f')) library("plyr") ddply(dat,.(Group),summarize, Max = max(Score), Info = Info[which.max(Score)]) Group Max Info 1 1 3 c 2 2 4 d 

这就是我基本上想到的问题。

 my.df <- data.frame(group = rep(c(1,2), each = 3), score = runif(6), info = letters[1:6]) my.agg <- with(my.df, aggregate(score, list(group), max)) my.df.split <- with(my.df, split(x = my.df, f = group)) my.agg$info <- unlist(lapply(my.df.split, FUN = function(x) { x[which(x$score == max(x$score)), "info"] })) > my.agg Group.1 x info 1 1 0.9344336 a 2 2 0.7699763 e