77

2 つのデータ フレームをマージして、そのうちの 1 つの元の行の順序を維持したい (df.2下の例)。

以下にいくつかのサンプル データを示します (class列のすべての値は両方のデータ フレームで定義されています)。

df.1 <- data.frame(class = c(1, 2, 3), prob = c(0.5, 0.7, 0.3))
df.2 <- data.frame(object = c('A', 'B', 'D', 'F', 'C'), class = c(2, 1, 2, 3, 1))

私が行った場合:

merge(df.2, df.1)

出力は次のとおりです。

  class object prob
1     1      B  0.5
2     1      C  0.5
3     2      A  0.7
4     2      D  0.7
5     3      F  0.3

私が追加した場合sort = FALSE

merge(df.2, df.1, sort = F)                                                        

結果は次のとおりです。

  class object prob
1     2      A  0.7
2     2      D  0.7
3     1      B  0.5
4     1      C  0.5
5     3      F  0.3

しかし、私が欲しいのは:

  class object prob
1     2      A  0.7
2     1      B  0.5
3     2      D  0.7
4     3      F  0.3    
5     1      C  0.5
4

12 に答える 12

62

df.2 で行番号を指定する変数を作成するだけです。次に、データをマージしたら、この変数に従って新しいデータ セットを並べ替えます。例を次に示します。

df.1<-data.frame(class=c(1,2,3), prob=c(0.5,0.7,0.3))
df.2<-data.frame(object=c('A','B','D','F','C'), class=c(2,1,2,3,1))
df.2$id  <- 1:nrow(df.2)
out  <- merge(df.2,df.1, by = "class")
out[order(out$id), ]
于 2013-07-26T09:54:48.570 に答える
15

inner_joinまた、Hadley のdplyrパッケージ (の次の反復) で関数を確認することもできますplyr。最初のデータ セットの行の順序が保持されます。目的のソリューションとの小さな違いは、最初のデータ セットの元の列の順序も保持されることです。したがって、マージに使用した列が最初の位置にあるとは限りません。

上記の例を使用すると、inner_join結果は次のようになります。

inner_join(df.2,df.1)
Joining by: "class"
  object class prob
1      A     2  0.7
2      B     1  0.5
3      D     2  0.7
4      F     3  0.3
5      C     1  0.5
于 2014-07-18T07:51:18.517 に答える
3

受け入れられた回答は、使用時に順序を維持する手動の方法を提案しています。mergeこれはほとんどの場合機能しますが、不要な手作業が必要です。この解決策は、並べ替えなしで ddply() を行う方法の裏にありますか? 、順序を維持する問題を扱いますが、分割-適用-結合のコンテキストで:

これはしばらく前に plyr のメーリング リストで取り上げられました (@kohske によって提起されました)。

#Peter's version used a function gensym to
# create the col name, but I couldn't track down
# what package it was in.
keeping.order <- function(data, fn, ...) { 
  col <- ".sortColumn"
  data[,col] <- 1:nrow(data) 
  out <- fn(data, ...) 
  if (!col %in% colnames(out)) stop("Ordering column not preserved by function") 
  out <- out[order(out[,col]),] 
  out[,col] <- NULL 
  out 
} 

したがって、この汎用keeping.order関数を使用して、merge呼び出しの元の行順序を維持できます。

df.1<-data.frame(class=c(1,2,3), prob=c(0.5,0.7,0.3))
df.2<-data.frame(object=c('A','B','D','F','C'), class=c(2,1,2,3,1))
keeping.order(df.2, merge, y=df.1, by = "class")

要求に応じて、次のようになります。

> keeping.order(df.2, merge, y=df.1, by = "class")
  class object id prob
3     2      A  1  0.7
1     1      B  2  0.5
4     2      D  3  0.7
5     3      F  4  0.3
2     1      C  5  0.5

したがってkeeping.order、受け入れられた回答のアプローチを効果的に自動化します。

于 2014-09-23T15:59:37.443 に答える
2

@PAC のおかげで、次のようなものを思いつきました:

merge_sameord = function(x, y, ...) {
    UseMethod('merge_sameord')
}

merge_sameord.data.frame = function(x, y, ...) {
    rstr = paste(sample(c(0:9, letters, LETTERS), 12, replace=TRUE), collapse='')
    x[, rstr] = 1:nrow(x)
    res = merge(x, y, all.x=TRUE, sort=FALSE, ...)
    res = res[order(res[, rstr]), ]
    res[, rstr] = NULL
    res
}

これは、最初のデータ フレームの順序を維持することを前提としており、マージされたデータ フレームには最初のデータ フレームと同じ数の行が含まれます。余分な列のないクリーンなデータ フレームが得られます。

于 2013-08-09T13:35:28.337 に答える