合并后,将所得NA值替换为0,并保留先前存在的NA

时间:2018-06-19 15:08:20

标签: r merge

合并两个数据帧时,如何将合并产生的NA值设置为0,同时将先前存在的NA值保留为NA

library(data.table)

df1 <- fread("
TYPE
A
B
C
")

df2 <- fread("
   TYPE Num Dollar
      A  NA 215.77
      B  11 NA
")

merge(df1, df2, all.x = T)

实际输出:

   TYPE Num Dollar
1:    A  NA 215.77
2:    B  11     NA
3:    C  NA     NA

所需的输出:

   TYPE Num Dollar
1:    A  NA 215.77
2:    B  11     NA
3:    C   0      0

编辑:这是一个更好的示例,显示了为什么在更一般的情况下不能依赖索引

df1 <- fread("
TYPE
A
B
C
", data.table = F)

df2 <- fread("
   TYPE Num Dollar
      A  NA 215.77
      C  11 NA
", data.table = F)

merge(df1, df2, all.x = T)
#   TYPE Num Dollar
# 1    A  NA 215.77
# 2    B  NA     NA
# 3    C  11     NA
inx <- which(is.na(df2), arr.ind = TRUE)
df3 <- merge(df1, df2, all.x = T)
df3[is.na(df3)] <- 0
df3[inx] <- NA
df3
#   TYPE Num Dollar
# 1    A  NA 215.77
# 2    B   0     NA
# 3    C  11   0.00

编辑:Rui Barradas和akrun的答案均有效。由于没有其他差异化因素,我接受Rui的回答,因为它适用于data.framedata.table

2 个答案:

答案 0 :(得分:3)

也许有更简单的方法,但是下面的方法可以做到。

注意:
原始代码已被完全修改,以应对OP引用中的注释中所述的可能性。

  

这很好,但是仅在索引匹配时才有效。考虑一下   而不是C丢失,而df2中B丢失的情况。然后   来自df2的df3中的行具有索引1和3,而在df2中它们具有索引   有索引1和2

新代码解决了这两种情况,因此我将其放在函数中。

library(data.table)

fun <- function(DF1, DF2){
  res <- merge(DF1, DF2, all.x = T, by = 'TYPE')
  inx <- which(!(DF1$TYPE %in% DF2$TYPE))
  res[inx, which(is.na(res[inx, ]))] <- 0
  res
}

fun(df1, df2)
#   TYPE Num Dollar
#1:    A  NA 215.77
#2:    B  11     NA
#3:    C   0   0.00

fun(df1, df3)
#   TYPE Num Dollar
#1:    A  NA 215.77
#2:    B   0   0.00
#3:    C  11     NA

测试数据。

df1df2是问题中的data.frame,df3是OP注释中的df。

df1 <- fread("
TYPE
A
B
C
")

df2 <- fread("
   TYPE Num Dollar
             A  NA 215.77
             B  11 NA
             ")

df3 <- fread("
   TYPE Num Dollar
      A  NA 215.77
      C  11 NA
")

答案 1 :(得分:2)

除了@Rui Barradas解决方案之外,我们还可以在第二个数据集中创建一个flag变量并更改merge的输出

out <- merge(df1, df2[, flag := TRUE], all.x = TRUE)
nm1 <- c("Num", "Dollar")
for(j in nm1) set(out, i = which(is.na(out$flag)), j=j, value = 0)
out[, flag := NULL][]
#   TYPE Num Dollar
#1:    A  NA 215.77
#2:    B  11     NA
#3:    C   0   0.00

或使用加入

out <- copy(df1)
out[df2, c(nm1, 'flag') := c(mget(nm1), list(TRUE)), on = .(TYPE)]

然后如上所述将NA替换为0