jul*_*635 54 aggregate r plyr greatest-n-per-group
我在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
Run Code Online (Sandbox Code Playgroud)
我想在Score
使用该max
函数的列之后聚合它
> aggregate(data$Score, list(data$Group), max)
Group.1 x
1 1 3
2 2 4
Run Code Online (Sandbox Code Playgroud)
但我还想显示与每个组Info
的Score
列的最大值相关联的列.我不知道该怎么做.我想要的输出是:
Group.1 x y
1 1 3 c
2 2 4 d
Run Code Online (Sandbox Code Playgroud)
任何提示?
Rei*_*son 51
基本R解决方案是将输出aggregate()
与merge()
步骤组合.我发现公式接口aggregate()
比标准接口更有用,部分原因是输出上的名称更好,所以我将使用它:
这aggregate()
一步是
maxs <- aggregate(Score ~ Group, data = dat, FUN = max)
Run Code Online (Sandbox Code Playgroud)
而这merge()
一步很简单
merge(maxs, dat)
Run Code Online (Sandbox Code Playgroud)
这给了我们想要的输出:
R> maxs <- aggregate(Score ~ Group, data = dat, FUN = max)
R> merge(maxs, dat)
Group Score Info
1 1 3 c
2 2 4 d
Run Code Online (Sandbox Code Playgroud)
当然,你可以把它固定在一个单行程中(中间步骤更多用于说明):
merge(aggregate(Score ~ Group, data = dat, FUN = max), dat)
Run Code Online (Sandbox Code Playgroud)
我使用公式接口的主要原因是它返回一个正确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
Run Code Online (Sandbox Code Playgroud)
我们可以merge()
在这些输出上使用,但是我们需要做更多的工作来告诉R哪些列匹配.
mbq*_*mbq 37
首先,使用split
以下方法拆分数据:
split(z,z$Group)
Run Code Online (Sandbox Code Playgroud)
对于每个块,选择具有最大分数的行:
lapply(split(z,z$Group),function(chunk) chunk[which.max(chunk$Score),])
Run Code Online (Sandbox Code Playgroud)
最后减少回data.frame do.call
ing rbind
:
do.call(rbind,lapply(split(z,z$Group),function(chunk) chunk[which.max(chunk$Score),]))
Run Code Online (Sandbox Code Playgroud)
结果:
Group Score Info
1 1 3 c
2 2 4 d
Run Code Online (Sandbox Code Playgroud)
一行,没有魔法,快速,结果有好名字=)
And*_*rie 15
这是使用该plyr
包的解决方案.
以下代码行基本上告诉ddply
您首先按组对数据进行分组,然后在每个组中返回一个子集,其中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
Run Code Online (Sandbox Code Playgroud)
而且,正如@SachaEpskamp指出的那样,这可以进一步简化为:
ddply(df, .(Group), function(x)x[which.max(x$Score), ])
Run Code Online (Sandbox Code Playgroud)
(which.max
如果有的话,它还具有返回多个最大线的优点).
该plyr
包可用于此目的。使用该ddply()
函数,您可以在一个或多个列上拆分一个数据帧,并应用一个函数并返回一个数据帧,然后使用该函数,您可以将拆分后的数据帧summarize()
的列用作变量以创建新的数据帧/;
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
Run Code Online (Sandbox Code Playgroud)
答案很晚,但是使用方法 data.table
library(data.table)
DT <- data.table(dat)
DT[, .SD[which.max(Score),], by = Group]
Run Code Online (Sandbox Code Playgroud)
或者,如果可能有多个相同的最高分数
DT[, .SD[which(Score == max(Score)),], by = Group]
Run Code Online (Sandbox Code Playgroud)
注意(从 ?data.table
.SD
是一个data.table,其中包含每个组(不包括组列)的x的数据子集
加文的答案是:合并之前,不使用公式接口时可以使用特定名称来聚合:
aggregate(data[,"score", drop=F], list(group=data$group), mean)
Run Code Online (Sandbox Code Playgroud)