汇总给定列上的数据框并显示另一列
我有以下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