21

2 つの類似したデータ フレームをマージして、重要度の高いデータ フレームを作成するにはどうすればよいですか?

例えば:

データフレーム 1

Date      Col1    Col2
jan         2      1
feb         4      2
march       6      3
april       8      NA

データフレーム 2

Date      Col2    Col3
jan         9      10
feb         8      20
march       7      30
april       6      40

これらを日付別にマージし、データフレーム 1 を優先しますが、データフレーム 2 は空白を埋めます

データフレームマージ

Date      Col1    Col2    Col3
jan         2       1      10
feb         4       2      20
march       6       3      30
april       8       6      40

編集 - 解決策

commonNames <- names(df1)[which(colnames(df1) %in% colnames(df2))]
commonNames <- commonNames[commonNames != "key"]
dfmerge<- merge(df1,df2,by="key",all=T)
for(i in commonNames){
  left <- paste(i, ".x", sep="")
  right <- paste(i, ".y", sep="")
  dfmerge[is.na(dfmerge[left]),left] <- dfmerge[is.na(dfmerge[left]),right]
  dfmerge[right]<- NULL
  colnames(dfmerge)[colnames(dfmerge) == left] <- i
}
4

4 に答える 4

14
merdat <- merge(dfrm1,dfrm2, by="Date")  # seems self-documenting

#  explanation for next line in text below.
merdat$Col2.y[ is.na(merdat$Col2.y) ] <- merdat$Col2.x[ is.na(merdat$Col2.y) ]

次に、「merdat$Col2.y」の名前を「merdat$Col2」に変更し、「merdat$Col2.x」をドロップします。

コメントのリクエストへの返信: ベクトルのセクションのみを更新する 1 つの方法は、インデックス付け用の論理ベクトルを構築し、代入の両側に "[" を使用して適用することです。もう 1 つの方法は、代入の LHS 上にのみある論理ベクトルを考案し、それを使用rep()して と同じ長さのベクトルを作成することsum(logical.vector)です。目標は、両方のインスタンスが、置換されるアイテムと同じ長さ (および順序) で割り当てられるようにすることです。

于 2013-04-16T16:40:41.750 に答える
11

v1.9.6 の data.table のon=引数を使用して更新します (これにより、アドホック結合が可能になります:

setDT(df1)[df2, `:=`(Col2 = ifelse(is.na(Col2), i.Col2, Col2), 
                     Col3 = i.Col3), on="Date"][]

これがdata.table解決策です。df1df2の列が必要なレベルの因子であることを確認してくださいDate(順序付け用)

require(data.table)
dt1 <- data.table(df1, key="Date")
dt2 <- data.table(df2, key="Date")
# Col2 refers to the Col2 of dt1 and i.col2 refers to that of dt2
dt1[dt2, `:=`(Col3 = Col3, Col1 = Col1, 
        Col2 = ifelse(is.na(Col2), i.Col2, Col2))]

# the result is stored in dt1
> dt1
#     Date Col1 Col2 Col3
# 1:   jan    2    1   10
# 2:   feb    4    2   20
# 3: march    6    3   30
# 4: april    8    6   40
于 2013-04-16T19:41:21.030 に答える
8

これがdplyr解決策です。@docendo discimus の功績

df1 <- data.frame(y = c("A", "B", "C", "D"), x1 = c(1,2,NA, 4)) 

  y x1
1 A  1
2 B  2
3 C NA
4 D  4

df2 <- data.frame(y = c("A", "B", "C"), x1 = c(5, 6, 7))

  y x1
1 A  5
2 B  6
3 C  7

dplyr

left_join(df1, df2, by="y") %>% 
transmute(y, x1 = ifelse(is.na(x1.y), x1.x, x1.y))

  y x1
1 A  5
2 B  6
3 C  7
于 2016-02-25T23:39:47.080 に答える
5

次の例を検討してください。

> d1 <- data.frame(x=1:4, a=2:5, b=c(3,4,5,NA))
> d1
  x a  b
1 1 2  3
2 2 3  4
3 3 4  5
4 4 5 NA
> d2 <- data.frame(x=1:4, b=c(6,7,8,9), c=11:14)
> d2
  x b  c
1 1 6 11
2 2 7 12
3 3 8 13
4 4 9 14

とを次のように使用mergeします。withinifelse

> within(merge(d1, d2, by="x"), {b <- ifelse(is.na(b.x),b.y,b.x); b.x <- NULL; b.y <- NULL})
  x a  c b
1 1 2 11 3
2 2 3 12 4
3 3 4 13 5
4 4 5 14 9
于 2013-04-16T16:40:19.293 に答える