【问题标题】:Merge unequal dataframes and replace missing rows with 0合并不相等的数据框并用 0 替换缺失的行
【发布时间】:2011-08-23 08:51:08
【问题描述】:

我有两个 data.frames,一个只有字符,另一个有字符和值。

df1 = data.frame(x=c('a', 'b', 'c', 'd', 'e'))
df2 = data.frame(x=c('a', 'b', 'c'),y = c(0,1,0))
merge(df1, df2)
  x y
1 a 0
2 b 1
3 c 0 

我想合并 df1 和 df2。字符 a、b 和 c 合并得很好,也有 0、1、0,但 d 和 e 什么都没有。我希望 d 和 e 也在合并表中,条件为 0 0。因此,对于 df2 data.frame 中的每一行缺失的行,0 必须放在 df1 表中,例如:

  x y
1 a 0
2 b 1
3 c 0
4 d 0
5 e 0

【问题讨论】:

  • 我们通常将字符也称为值,因此您的 y 列将被称为数字。

标签: r merge dataframe


【解决方案1】:

“all”选项不再起作用,新参数是;

x = pd.merge(df1, df2, how="outer")

【讨论】:

  • 这是一个 r 问题,不是 python 问题
【解决方案2】:

假设df1 具有所有感兴趣的x 值,您可以使用dplyr::left_join() 进行合并,然后使用base::replace()tidyr::replace_na()NAs 替换为0s :

library(tidyverse)

# dplyr only:
df_new <- 
  left_join(df1, df2, by = 'x') %>% 
  mutate(y = replace(y, is.na(y), 0))

# dplyr and tidyr:
df_new <- 
  left_join(df1, df2, by = 'x') %>% 
  mutate(y = replace_na(y, 0))

# In the sample data column `x` is a factor, which will give a warning with the join. This can be prevented by converting to a character before the join:
df_new <- 
  left_join(df1 %>% mutate(x = as.character(x)), 
            df2 %>% mutate(x = as.character(x)), 
            by = 'x') %>% 
    mutate(y = replace(y, is.na(y), 0))

【讨论】:

    【解决方案3】:

    查看合并的帮助页面。 all 参数允许您指定不同类型的合并。这里我们要设置all = TRUE。这将使不匹配的值合并返回NA,我们可以使用is.na()更新为0:

    zz <- merge(df1, df2, all = TRUE)
    zz[is.na(zz)] <- 0
    
    > zz
      x y
    1 a 0
    2 b 1
    3 c 0
    4 d 0
    5 e 0
    

    多年后更新以解决后续问题

    您需要识别第二个数据表中未合并的变量名称 - 我为此使用 setdiff()。查看以下内容:

    df1 = data.frame(x=c('a', 'b', 'c', 'd', 'e', NA))
    df2 = data.frame(x=c('a', 'b', 'c'),y1 = c(0,1,0), y2 = c(0,1,0))
    
    #merge as before
    df3 <- merge(df1, df2, all = TRUE)
    #columns in df2 not in df1
    unique_df2_names <- setdiff(names(df2), names(df1))
    df3[unique_df2_names][is.na(df3[, unique_df2_names])] <- 0 
    

    reprex package (v0.2.1) 于 2019 年 1 月 3 日创建

    【讨论】:

    • 嗨,蔡斯,感谢您的解决方案!它对我有帮助!
    • Hunh——已经使用 R 一年了,我不知道你可以像这样处理 data.frame 中的每个单元格。有时质疑你的假设是值得的。谢谢蔡斯!
    • 嗨,Chase,我可以只对 df1 使用命令“all=true”吗?有时此命令包含 df1 中不可用但在 df2 中可用的数据
    • @jbest - 有参数all.xall.y 其中x == 第一个data.frame 对象和y == 第二个,正是针对这种情况。有关详细信息,请参阅?merge 的帮助页面。
    • 但是如何用另一个值替换 由合并产生的 NA 值?如果我要加入一个已经有一些 NA 的表,则此解决方案不起作用。
    【解决方案4】:

    我使用了 Chase 给出的答案(2011 年 5 月 11 日 14:21 回答),但我添加了一些代码将该解决方案应用于我的特定问题。

    我有一个费率框架(用户,下载)和一个总计框架(用户,下载),要由用户合并,我想包括每个费率,即使没有对应的总计。但是,可能不会缺少总计,在这种情况下,选择行以将 NA 替换为 0 将失败。

    第一行代码进行合并。接下来的两行更改合并框架中的列名。 if 语句将 NA 替换为零,但前提是存在具有 NA 的行。

    # merge rates and totals, replacing absent totals by zero
    graphdata <- merge(rates, totals, by=c("user"),all.x=T)
    colnames(graphdata)[colnames(graphdata)=="download.x"] = "download.rate"
    colnames(graphdata)[colnames(graphdata)=="download.y"] = "download.total"
    if(any(is.na(graphdata$download.total))) {
        graphdata[is.na(graphdata$download.total),]$download.total <- 0
    }
    

    【讨论】:

      【解决方案5】:

      data.table 的另一种选择。

      示例数据

      dt1 <- data.table(df1)
      dt2 <- data.table(df2)
      setkey(dt1,x)
      setkey(dt2,x)
      

      代码

      dt2[dt1,list(y=ifelse(is.na(y),0,y))]
      

      【讨论】:

      • 在 1.10.4 版本中,您不需要 setkey 并且可以在创建 data.tables 后立即使用 df2[df1, on="x"][is.na(y), y := 0] 以产生所需的结果。
      【解决方案6】:

      或者,作为@Chase 代码的替代方案,成为最近具有数据库背景的 plyr 粉丝:

      require(plyr)
      zz<-join(df1, df2, type="left")
      zz[is.na(zz)] <- 0
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-28
        相关资源
        最近更新 更多