Подтвердить что ты не робот

Удалить дубликаты, сохраняющие запись с наибольшей абсолютной величиной

Скажем, у меня есть четыре образца: 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?

4b9b3361

Ответ 1

 aa <- a[order(a$id, -abs(a$value) ), ] #sort by id and reverse of abs(value)
 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

Подход

A 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

Отъезд ?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)),]))

Ответ 4

Другой подход (хотя код может выглядеть немного громоздким) заключается в использовании 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

Ответ 5

library(plyr)
ddply(a, .(id), function(x) return(x[which(abs(x$value)==max(abs(x$value))),]))