删除重复项,保留具有最大绝对值的条目

Posted

技术标签:

【中文标题】删除重复项,保留具有最大绝对值的条目【英文标题】:Remove duplicates keeping entry with largest absolute value 【发布时间】:2012-09-30 03:13:44 【问题描述】:

假设我有四个样本:id=1、2、3 和 4,每个样本都有一个或多个测量值:

> a <- data.frame(id=c(1,1,2,2,3,4), value=c(1,2,3,-4,-5,6))
> a
  id value
1  1     1
2  1     2
3  2     3
4  2    -4
5  3    -5
6  4     6

我想删除重复项,每个 ID 只保留一个条目 - “值”列的绝对值最大的条目。也就是说,这就是我想要的:

> a[c(2,4,5,6), ]
  id value
2  1     2
4  2    -4
5  3    -5
6  4     6

我如何在 R 中做到这一点?

【问题讨论】:

您提到“每个 ID 只保留一个条目 - 'value' 列的绝对值最大的那个。”如果有多个条目,期望的行为是什么每个 ID 是否符合该条件?返回两个值,还是其中一个?例如,如果a[3, 2] &lt;- 4,您想要的输出是什么? 啊..这是个好问题。 value 列实际上是一个实数而不是整数,并且很可能永远不会完全相等。理想的期望行为可能应该是放弃这两个观察结果,但这可能不会像我说的那样发生。 感谢大家的帮助。 【参考方案1】:

首先。在id 组中按顺序排序,将不太需要的项目放在最后

 aa <- a[order(a$id, -abs(a$value) ), ] #sort by id and reverse of abs(value)

然后:删除id 组中第一个之后的项目

 aa[ !duplicated(aa$id), ]              # take the first row within each id
  id value
2  1     2
4  2    -4
5  3    -5
6  4     6

【讨论】:

【参考方案2】:

如果您的数据集非常大,可能需要采用data.table 方法:

library(data.table)

aDT <- as.data.table(a)
setkey(aDT,"id")

aDT[J(unique(id)), list(value = value[which.max(abs(value))])]

或者一个不那么快但仍然很快的替代方案:

library(data.table)
as.data.table(a)[, .SD[which.max(abs(value))], by=id]

这个版本返回a的所有列,以防真实数据集中有更多。

【讨论】:

【参考方案3】:

这是dplyr 方法

library(dplyr)
a %>% 
        group_by(id) %>%
        top_n(1, abs(value))

# A tibble: 4 x 2
# Groups:   id [4]
#     id value
#  <dbl> <dbl>
#1     1     2
#2     2    -4
#3     3    -5
#4     4     6

【讨论】:

以防万一其他人需要使用 -1 来获取最小值。 top_n(-1, abs(value)) 这很方便,但有人能解释一下这个逻辑吗? @Negrito top_n() 是用于选择每组顶部或底部条目的包装器。更多详情here。在这里,我们对“值”列top_n(..., wt = abs(value)) 的最大绝对值(top_n(n = 1,...))感兴趣【参考方案4】:

查看?aggregate:

aggregate(value~id,a,function(x) x[which.max(abs(x))])

我喜欢@DWin 的回答,但我想展示这也可以与元数据一起使用:

aa<-merge(aggregate(value~id,a,function(x) x[which.max(abs(x))]),a)
# Fails if the max value is duplicated for a single id without next line.
aa[!duplicated(aa),]

我忍不住想出了最后一个答案:

do.call(rbind,lapply(split(a,a$id),function(x) x[which.max(abs(x$value)),]))

【讨论】:

这符合我的描述,但我应该提供更多信息。实际上,每个 ID 都有一个 ID 和许多其他相同的元数据列,每个 ID 都有许多其他值列。我想保留数据框中的所有列,而不仅仅是一个 id 和 value。【参考方案5】:

另一种方法(虽然代码可能看起来有点麻烦)是使用ave()

a[which(abs(a$value) == ave(a$value, a$id, 
                            FUN=function(x) max(abs(x)))), ]
#   id value
# 2  1     2
# 4  2    -4
# 5  3    -5
# 6  4     6

【讨论】:

@DWin,"I learned it by watching you!"。 ;) 嘿。不是来自我的文化框架,而是我在 youtube 上的“吸毒大脑”剪辑之后所经历的 Scrubs 活动非常有趣。【参考方案6】:
library(plyr)
ddply(a, .(id), function(x) return(x[which(abs(x$value)==max(abs(x$value))),]))

【讨论】:

plyr 非常慢【参考方案7】:

您可以使用 dplyr 执行此操作,如下所示:

library(dplyr)
a %>%
  group_by(name) %>%
  filter(n == max(n)) %>%
  ungroup()

【讨论】:

以上是关于删除重复项,保留具有最大绝对值的条目的主要内容,如果未能解决你的问题,请参考以下文章

Java 8 Streams 减少删除重复项,保留最新条目

删除列表中的最大值,保留重复项

SQL 查询 - 组合两个表,删除重复项并仅保留最新的日期

python pandas:删除A列的重复项,保留B列中具有最高值的行

删除带有警告的重复项

如何在 MS Access 2003 中删除具有唯一 ID 的重复条目?