4つのサンプルがあるとします:id = 1、2、3、および4で、これらのサンプルのそれぞれに1つ以上の測定があります。
> 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ごとに1つのエントリ(「値」列の絶対値が最大のもの)のみを残して、重複を削除したいと思います。つまり、これは私が欲しいものです:
> a[c(2,4,5,6), ]
id value
2 1 2
4 2 -4
5 3 -5
6 4 6
Rでこれをどのように行うことができますか?
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
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
のすべての列を返します。
チェックアウト ?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),]
私は自分自身を助けることができず、最後の答えを1つ作成しました。
do.call(rbind,lapply(split(a,a$id),function(x) x[which.max(abs(x$value)),]))
別のアプローチ(コードが少し面倒に見えるかもしれません)は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
ここに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
library(plyr)
ddply(a, .(id), function(x) return(x[which(abs(x$value)==max(abs(x$value))),]))
これは、dplyrを使用して次のように実行できます。
library(dplyr)
a %>%
group_by(name) %>%
filter(n == max(n)) %>%
ungroup()