dat
@agstudyの回答から仮定すると、それaggregate()
はあなたが望むことを簡単に行うことができる素晴らしい基本関数です。(この回答ではwhich.min()
、を使用しています。これは、入力ベクトル内の最小値をとる複数の値が存在する場合に興味深い動作をします。最後の警告を参照してください!)。例えば
aggregate(cbind(Dist1, Dist2) ~ GroupID, data = dat, FUN = which.min)
> aggregate(cbind(Dist1, Dist2) ~ GroupID, data = dat, FUN = which.min)
GroupID Dist1 Dist2
1 1 3 1
2 2 1 3
3 3 2 1
行IDを取得するか、行名を取得するためにこれを行うことができます(例にいくつかの行名を追加した後):
rownames(dat) <- letters[seq_len(nrow(dat))] ## add rownames for effect
## function, pull out for clarity
foo <- function(x, rn) rn[which.min(x)]
## apply via aggregate
aggregate(cbind(Dist1, Dist2) ~ GroupID, data = dat, FUN = foo,
rn = rownames(dat))
これは
> rownames(dat) <- letters[seq_len(nrow(dat))] ## add rownames for effect
>
> ## function, pull out for clarity
> foo <- function(x, rn) rn[which.min(x)]
> ## apply via aggregate
> aggregate(cbind(Dist1, Dist2) ~ GroupID, data = dat, FUN = foo,
+ rn = rownames(dat))
GroupID Dist1 Dist2
1 1 c a
2 2 a c
3 3 b a
私はaggregate()
、より良い出力を提供by()
し、数式インターフェイス(それを使用するための最も効率的な方法ではありませんが)は確かに非常に直感的であることがわかりました。
警告
which.min()
少なくとも重複する値がない場合は素晴らしいです。ある場合は、which.min()
最小値の最初の値を選択します。あるいは、which(x == min(x))
イディオムがありますが、どのソリューションでも、最小値が重複しているという事実を処理する必要があります。
dat2 <- dat
dat2 <- rbind(dat2, data.frame(GroupID = 1, Dist1 = 3, Dist2 = 8))
aggregate(cbind(Dist1, Dist2) ~ GroupID, data = dat2, FUN = which.min)
重複を見逃します。
> aggregate(cbind(Dist1, Dist2) ~ GroupID, data = dat2, FUN = which.min)
GroupID Dist1 Dist2
1 1 3 1
2 2 1 3
3 3 2 1
それをwhich(x == min(x))
イディオムと比較してください。
out <- aggregate(cbind(Dist1, Dist2) ~ GroupID, data = dat2,
FUN = function(x) which(x == min(x)))
> (out <- aggregate(cbind(Dist1, Dist2) ~ GroupID, data = dat2,
+ FUN = function(x) which(x == min(x))))
GroupID Dist1 Dist2
1 1 3, 4 1, 2
2 2 1 3
3 3 2 1
を使用した出力which(x == min(x))
は魅力的ですが、オブジェクト自体はやや複雑で、コンポーネントとしてリストを含むデータフレームです。
> str(out)
'data.frame': 3 obs. of 3 variables:
$ GroupID: num 1 2 3
$ Dist1 :List of 3
..$ 0: int 3 4
..$ 1: int 1
..$ 2: int 2
$ Dist2 :List of 3
..$ 0: int 1 2
..$ 1: int 3
..$ 2: int 1