删除重复项,保留具有最大绝对值的条目
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] <- 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()
【讨论】:
以上是关于删除重复项,保留具有最大绝对值的条目的主要内容,如果未能解决你的问题,请参考以下文章