Answers:
一种方法是对数据进行反向排序,然后使用duplicated
它删除所有重复项。对我而言,此方法在概念上比使用apply方法更简单。我认为它也应该非常快。
# Some data to start with:
z <- data.frame(id=c(1,1,2,2,3,4),var=c(2,4,1,3,5,2))
# id var
# 1 2
# 1 4
# 2 1
# 2 3
# 3 5
# 4 2
# Reverse sort
z <- z[order(z$id, z$var, decreasing=TRUE),]
# id var
# 4 2
# 3 5
# 2 3
# 2 1
# 1 4
# 1 2
# Keep only the first row for each duplicate of z$id; this row will have the
# largest value for z$var
z <- z[!duplicated(z$id),]
# Sort so it looks nice
z <- z[order(z$id, z$var),]
# id var
# 1 4
# 2 3
# 3 5
# 4 2
编辑:我只是意识到上面的反向排序根本不需要排序id
。您可以只使用z[order(z$var, decreasing=TRUE),]
它,它也可以正常工作。
再想一想...如果该var
列是数字列,则有一种简单的排序方式,使之id
递增,但var
递减。这样就无需在末尾进行排序(假设您甚至希望对其进行排序)。
z <- data.frame(id=c(1,1,2,2,3,4),var=c(2,4,1,3,5,2))
# Sort: id ascending, var descending
z <- z[order(z$id, -z$var),]
# Remove duplicates
z <- z[!duplicated(z$id),]
# id var
# 1 4
# 2 3
# 3 5
# 4 2
您实际上想从具有相同ID的元素中选择最大元素。为此,您可以使用plyrddply
软件包:
> dt<-data.frame(id=c(1,1,2,2,3,4),var=c(2,4,1,3,4,2))
> ddply(dt,.(id),summarise,var_1=max(var))
id var_1
1 1 4
2 2 3
3 3 4
4 4 2
unique
并且duplicated
用于删除重复的记录,在您的情况下,您只有重复的ID,而没有记录。
更新:这是有其他变量时的代码:
> dt<-data.frame(id=c(1,1,2,2,3,4),var=c(2,4,1,3,4,2),bu=rnorm(6))
> ddply(dt,~id,function(d)d[which.max(d$var),])
base-R解决方案将涉及split
,如下所示:
z<-data.frame(id=c(1,1,2,2,3,4),var=c(2,4,1,3,4,2))
do.call(rbind,lapply(split(z,z$id),function(chunk) chunk[which.max(chunk$var),]))
split
将数据帧拆分为一个大块列表,在该列表上,我们将数据切割为具有最大值的单行,然后do.call(rbind,...)
将单行列表再次缩小为一个数据帧。
我更喜欢使用 ave
dt<-data.frame(id=c(1,1,2,2,3,4),var=c(2,4,3,3,4,2))
## use unique if you want to exclude duplicate maxima
unique(subset(dt, var==ave(var, id, FUN=max)))
使用base的另一种方法是:
dt<-data.frame(id=c(1,1,2,2,3,4),var=c(2,4,1,3,4,2))
data.frame(id=sort(unique(dt$var)),max=tapply(dt$var,dt$id,max))
id max
1 1 4
2 2 3
3 3 4
4 4 2
我更喜欢mpiktas的plyr解决方案。
如示例中所示,如果列var已经按升序排列,则不需要对数据框进行排序。我们只使用duplicated
传递参数的函数fromLast = TRUE
,因此从反面考虑重复,并保留最后一个元素:
z <- data.frame(id=c(1,1,2,2,3,4),var=c(2,4,1,3,5,2))
z[!duplicated(z$id, fromLast = TRUE), ]
id var
2 1 4
4 2 3
5 3 5
6 4 2
否则,我们将首先按升序对数据框进行排序:
z <- z[order(z$id, z$var), ]
z[!duplicated(z$id, fromLast = TRUE), ]
使用dplyr
包装:
library(dplyr)
z %>%
group_by(id) %>%
summarise(var = max(var))
Source: local data frame [4 x 2]
id var
1 1 4
2 2 3
3 3 5
4 4 2