1

次のようなデータフレームがあります。それを A と呼びます。

GroupID  Dist1   Dist2 ...
1        4       4 
1        5       4 
1        3       16 
2        0       4 
2        7       2 
2        8       0 
2        6       4 
2        7       4 
2        8       2 
3        7       4 
3        5       6
...

GroupID は係数、Dist1、Dist2 は整数です。

派生データフレーム SummaryA があります

GroupID  AveD1  AveD2 ...
1        4       8 
2        6       2
3        6       5
...

各 groupID について、最小の ROW NUMBER を見つけ、さらに操作を行い、データを要約セットに抽出する必要があります。たとえば、次のものが必要です。

GroupID  MinRowD1  
1        1 
2        4 
3        11 

試合では、どちらを選んでも構いませんが、どうやってこれを手に入れるかについては行き詰まっています. which() は使用できません。なぜなら、それは因子に対して適切に動作しないためです。最小値ではなく位置が必要なため、ave(Fun=min) を使用できません。各グループのマッチングを最小限に抑えて何かを行うと、複数のマッチングが可能になり、台無しになります。

これを行う方法について何か提案はありますか?

4

6 に答える 6

7

あなたのデータの使用byrownames

> dat$row <- 1:nrow(dat)
>  by(dat,dat$GroupID,FUN = function(x) rownames(x)[which.min(x$Dist1)])
dat$GroupID: 1
[1] "3"
---------------------------------------------------------------------------------------- 
dat$GroupID: 2
[1] "4"
---------------------------------------------------------------------------------------- 
dat$GroupID: 3
[1] "11"

ここで私はdatを仮定します

dat <- read.table(text = 'GroupID  Dist1   Dist2
1        4       4 
1        5       4 
1        3       16 
2        0       4 
2        7       2 
2        8       0 
2        6       4 
2        7       4 
2        8       2 
3        7       4 
3        5       6', header = T)

編集data.tableパッケージを使用した別のソリューション

私は data.table がよりエレガントなソリューションを提供すると思います:

library(data.table)

dat$row <- 1:nrow(dat)
dtb <- as.data.table (dat)
dtb [,.SD[which.min(Dist1)],by=c('GroupID')]
   GroupID Dist1 Dist2 row
1:       1     3    16   3
2:       2     0     4   4
3:       3     5     6  11

行列を作成せずに1行テーブルを編集 (@Arun コメント)

dtb[, {i = which.min(Dist1); list(Dist1=Dist1[i], 
    Dist2=Dist2[i], rowNew=.I[i])}, by=GroupID]

  GroupID Dist1 Dist2 rowNew
1:       1     3    16   3
2:       2     0     4   4
3:       3     5     6  11
于 2013-01-24T17:36:24.897 に答える
5

これが基本的な R ソリューションです。基本的な考え方は、データを GroupID で分割し、それぞれの最小値を持つ行を取得してから、元に戻すことです。plyr関数はこれを行うためのより直感的な方法であると考える人もいます。それらの1つを使用したソリューションがまもなく表示されると確信しています...

A$row <- 1:nrow(A)
As <- split(A, A$GroupID)
sapply(As, function(Ai) {Ai$row[which.min(Ai$Dist1)]})

大規模なデータ セットのsplit場合、このようにデータ フレームではなくスカラーに対して実行すると高速になります。

rows <- split(1:nrow(A), A$GroupID)
sapply(rows, function(rowi) {rowi[which.min(A$Dist1[rowi])]})
于 2013-01-24T17:32:29.517 に答える
3

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
于 2013-01-24T18:45:02.573 に答える
2

dFrame にデータが含まれていると仮定します

 install.packages('plyr')
 library('plyr')

これを試して:

 dFrame$GroupID<-as.numeric(dFrame$GroupID) ## casting to numeric type
 dFrame<-arrange(dFrame,Dist1) ## sorting the frame by Dist1 to find min by Dist1
 dFrame$row_name<-1:nrow(dFrame) ## will use this to pick out the index

 newFrame<-data.frame(GroupID = unique(dFrame$GroupID), MinRowD1 = as.numeric(tapply(dFrame$row_name,dFrame$GroupID,FUN = function(x){return (x[1])})
于 2013-01-24T17:24:33.710 に答える
1

少し複雑ですが、これでうまくいくはずです:

x <- data.frame(GroupID=rep(1:3,each=3),Dist1=rpois(9,5))
x
  GroupID Dist1
1       1    10
2       1     5
3       1     3
4       2     9
5       2     9
6       2    13
7       3    10
8       3    10
9       3     4
sapply(lapply(lapply(split(x,x$GroupID),
    function(y) y[order(y[2]),]),head,1),rownames)
  1   2   3 
"3" "4" "9"
于 2013-01-24T17:30:09.177 に答える
0

これにより、各グループの最初の最小値に関連付けられた両方の列から行名が返されます。そして、名前付きの列を持つデータフレームとしてそれらを返します:

do.call(rbind, 
   by(dat,dat$GroupID,FUN = function(x) c(
                               minD1=rownames(x)[which.min(x[['Dist1']])], 
                               minD2=rownames(x)[which.min(x[['Dist2']])] ) ) )
#-------------
  minD1 minD2
1 "3"   "1"  
2 "4"   "6"  
3 "11"  "10" 
于 2013-01-24T17:50:58.417 に答える