合并不相等的数据框架,并将缺少的行替换为0

我有两个 data.frame,一个只包含字符,另一个包含字符和值。

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 也在合并表中,条件是00。因此,对于 df2 data.frame 中缺少的每一行,必须将0放在 df1表中,比如:

  x y
1 a 0
2 b 1
3 c 0
4 d 0
5 e 0
146062 次浏览

查看合并的帮助页面。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 软件包于2019-01-03创作(0.2.1)

或者,作为@Chase 代码的替代品,作为一个拥有数据库背景的 Plyr 粉丝:

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

使用 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))]

我使用了 Chase 给出的答案(答案是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
}

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

这里是一个 data.table的答案。这可以用在改变 cols_added_df2定义的选定列中

df1 = data.frame(x=c('a', 'b', 'c', 'd', 'e'))
df2 = data.frame(x=c('a', 'b', 'c'),y = c(0,1,0))
setDT(df1)
setDT(df2)
df3 <- merge(df1, df2, by = "x", all.x = TRUE)


cols_added_df2 <- setdiff(names(df2), names(df1))
df3[,
paste0(cols_added_df2) := lapply(.SD, function(col){
fifelse(is.na(col), 1, col)
}),
.SDcols = cols_added_df2
]

用{ powerjoin }我们可以做:

df1 = data.frame(x=c('a', 'b', 'c', 'd', 'e'))
df2 = data.frame(x=c('a', 'b', 'c'),y = c(0,1,0))
powerjoin::power_full_join(df1, df2, fill = 0)
#> Joining, by = "x"
#>   x y
#> 1 a 0
#> 2 b 1
#> 3 c 0
#> 4 d 0
#> 5 e 0

Reprex 软件包于2022.04-28年度创作(v2.0.1)