通过匹配至少两列中的一列来合并数据帧

Sta*_*bre 5 merge r

我一直在寻找解决方案并进行试验,但我似乎无法执行我应该做的简单任务。

我有两个数据框的格式类似于下面的玩具示例

DF1 = data.frame(A=c("cats","dogs",NA,"dogs"), B=c("kittens","puppies","kittens",NA), C=c(88,99,101,110))

    A       B           C
1   cats    kittens     88
2   dogs    puppies     99
3   NA      kittens     101
4   dogs    NA          110


DF2 = data.frame(D=c(1,2), A=c("cats","dogs"), B=c("kittens","puppies"))

    D   A       B
1   1   cats    kittens
2   2   dogs    puppies
Run Code Online (Sandbox Code Playgroud)

我希望合并两个数据集,这样输出是:

      A     B         C     D
1   cats    kittens   88    1
2   dogs    puppies   99    2
3   dogs    NA        110   2
4     NA    kittens   101   1
Run Code Online (Sandbox Code Playgroud)

换句话说,任何带有标签 A=="cats" 或 B=="kittens" 的行将被映射到 D 列中的 1,任何带有 A=="dogs" 或 B=="puppies" 的行将被映射到 2。

我已经使用了命令

merge(DF1, DF2, by=c("A","B"), all.x=TRUE)
Run Code Online (Sandbox Code Playgroud)

然而,这不正确匹配第 3 行和第 4 行,只有第 1 行和第 2 行。我得到输出

      A     B         C     D
1   cats    kittens   88    1
2   dogs    puppies   99    2
3   dogs    NA        110   NA
4     NA    kittens   101   NA
Run Code Online (Sandbox Code Playgroud)

请注意我正在使用的实际数据集很长。实际上,DF1 超过 1,000,000 行,DF2 超过 300,000 行,每行数千行,因此我真正需要的是可以缩放的解决方案。

Mat*_*erg 2

这是一种不同的方法:

library(functional)

partial.merge <- function(DF1, DF2) {
  common.cols <- intersect(names(DF1), names(DF2))
  result.col <- names(DF2)[!(names(DF2) %in% common.cols)]

  # This can only handle one result column:
  stopifnot(length(result.col) == 1)

  # Merge in each common column, one at a time.
  # The identical operation is done for each common column, so Reduce is useful:
  r <- Reduce(function(D, C) merge(D, DF2[c(C, result.col)], by=c(C), all.x=TRUE), x=common.cols, init=DF1)

  # The merge created cols like c('D.x', 'D.y').  These are the columns:
  merge.cols <- paste(result.col, c('x', 'y'), sep='.')

  # The .x and .y columns are partial, put them together:
  r[[result.col]] <- rowMeans(r[merge.cols], na.rm=TRUE)

  # Remove the temporaries:
  for (i in merge.cols) {
    r[[i]] <- NULL
  }
  return(r)
}

partial.merge(DF1, DF2)
##         B    A   C D
## 1 kittens cats  88 1
## 2 kittens <NA> 101 1
## 3 puppies dogs  99 2
## 4    <NA> dogs 110 2
Run Code Online (Sandbox Code Playgroud)