【问题标题】:After merging, replace resulting NA values with 0, keeping pre-existing NAs合并后,将结果 NA 值替换为 0,保留预先存在的 NA
【发布时间】:2018-06-19 15:08:19
【问题描述】:

合并两个数据框时,如何将合并产生的 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.frames 和 data.tables

【问题讨论】:

  • 只要df3[is.na(df3)] &lt;- 0。
  • @RuiBarradas 检查所需的输出。这不匹配。
  • 我认为您可能必须将初始数据集中的NA 更改为-999 之类的内容,然后在合并后进行更改,即for(j in 2:3) set(df2, i= which(is.na(df2[[j]])), j = j, -999)
  • 好的,抱歉,问题误解了。

标签: r merge


【解决方案1】:

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

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

这很好,但只有在索引匹配时才有效。考虑 df2 中缺少 C 而不是缺少 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

测试数据。

df1 和 df2 是问题中的 data.frames,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
")

【讨论】:

  • 这很好,但只有在索引匹配时才有效。考虑df2 中缺少B 而不是C 的情况。然后df3 中来自df2 的行具有索引1 和3,而df2 中它们具有索引1 和2。
【解决方案2】:

除了@Rui Barradas 解决方案,我们还可以在第二个数据集中创建一个标志变量并更改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

【讨论】:

    猜你喜欢
    • 2021-07-08
    • 2021-11-29
    • 2017-08-29
    • 2012-06-17
    • 1970-01-01
    • 2017-10-28
    • 1970-01-01
    相关资源
    最近更新 更多