代码之家  ›  专栏  ›  技术社区  ›  IceCreamToucan

合并后,将生成的NA值替换为0,保留现有的NAS

  •  2
  • IceCreamToucan  · 技术社区  · 8 年前

    在合并两个数据帧时,如何设置 NA 从合并到0的值,同时保留现有的 不适用 值为 不适用 是吗?

    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.frame 以及 data.table S

    2 回复  |  直到 8 年前
        1
  •  3
  •   IceCreamToucan    8 年前

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

    注:
    为了应对报价中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
    

    测试数据。

    df1 df2 数据帧是否存在问题? 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
    ")
    
        2
  •  2
  •   akrun    8 年前

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

    或者使用join

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

    然后像上面一样把NA换成0