如何在 R 数据框中删除除一个特定重复记录之外的所有重复记录?

机器算法验证 r
2022-02-16 13:29:42

我有一个包含一些重复 ID 的数据框。我想删除具有重复 ID 的记录,只保留具有最大值的行。

所以对于这样的结构(其他变量未显示):

id var_1
1 2
1 4
2 1
2 3
3 5
4 2

我想生成这个:

id var_1
1 4
2 3
3 5
4 2

我知道唯一()和重复(),但我不知道如何合并最大化规则......

4个回答

一种方法是对数据进行反向排序并用于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 的元素中选择最大元素。为此,您可以使用ddplyplyr

> 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)))