首页 文章

合并不相等的数据帧并用0替换缺失的行

提问于
浏览
56

我有两个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

5 回答

  • 83

    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))]
    
  • 0

    看一下合并的帮助页面 . 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
    

    Updated many years later to address follow up question

    您需要在第二个数据表中标识未合并的变量名称 - 我使用 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包创建于2019-01-03(v0.2.1)

  • 2

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

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

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

    我有一个费率框架(用户,下载)和用户合并的总框架(用户,下载),我想包括每个费率,即使没有相应的总数 . 但是,可能没有丢失的总数,在这种情况下,选择用于将NA替换为零的行将会失败 .

    第一行代码执行合并 . 接下来的两行更改合并帧中的列名称 . 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
    }
    
  • 7

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

    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))
    

相关问题