r - 简单但不容易的合并任务

标签 r merge na

我有两个不完整的数据框(df_a、df_b):列丢失或 NA 值。 “by”是合并索引,df_a 比 df_b 具有“优先级”。

df_a = structure(list(Datum = structure(c(1635163200, 1635166800, 1635170400, 1635174000), class = c("POSIXct", "POSIXt")), Vorhersage = c(10.297922, 10.155121, 10.044135, 9.699513), Export = c("10.912", "10.47", NA, NA), color = c("rgb(0,128,0)", "rgb(0,128,0)", NA, NA), Status = c("ok", "ok", NA, NA), Plausibilität = c("4", "4", NA, NA), min = c(7.93000000000001, 9.4, 8.7, 8.3), max = c(12.31715325, 12.42822725, 12.51326325, 12.28620625)), row.names = c(NA, -4L), class = "data.frame")
df_b = structure(list(Datum = structure(c(1632510000, 1632513600, 1632517200, 1632520800), class = c("POSIXct", "POSIXt")), Vorhersage = c(14.821988, 14.832919, 14.706179, 14.573527), Referenz = c(16.6, 16.2, 15.9, 16), DWD_Name = c("Elpersbüttel", "Elpersbüttel", "Elpersbüttel", "Elpersbüttel"), Export = c(17.198, 16.713, 16.378, 16.358), color = c("rgb(0,128,0)", "rgb(0,128,0)", "rgb(0,128,0)", "rgb(0,128,0)"), Status = c("ok", "ok", "ok", "ok"), Plausibilität = c(4, 4, 4, 4), min = c(13.05, 12.808, 11.631891, 12.312), max = c(17, 17, 16.9, 16.7)), row.names = c(NA, -4L), class = "data.frame")

所需的输出是:
                Datum Vorhersage Export        color Status Plausibilität  min max Referenz
1 2021-10-25 14:00:00       10.3 10.912 rgb(0,128,0)     ok             4  7.9  12       NA
2 2021-10-25 15:00:00       10.2  10.47 rgb(0,128,0)     ok             4  9.4  12       NA
3 2021-10-25 16:00:00       10.0   <NA>         <NA>   <NA>          <NA>  8.7  13       NA
4 2021-10-25 17:00:00        9.7   <NA>         <NA>   <NA>          <NA>  8.3  12       NA
5 2021-09-24 21:00:00       14.8 17.198 rgb(0,128,0)     ok             4 13.1  17       17
6 2021-09-24 22:00:00       14.8 16.713 rgb(0,128,0)     ok             4 12.8  17       16
7 2021-09-24 23:00:00       14.7 16.378 rgb(0,128,0)     ok             4 11.6  17       16
8 2021-09-25 00:00:00       14.6 16.358 rgb(0,128,0)     ok             4 12.3  17       16
      DWD_Name
1         <NA>
2         <NA>
3         <NA>
4         <NA>
5 Elpersbüttel
6 Elpersbüttel
7 Elpersbüttel
8 Elpersbüttel

# for rebuild:
structure(list(Datum = structure(c(1635163200, 1635166800, 1635170400, 
1635174000, 1632510000, 1632513600, 1632517200, 1632520800), class = c("POSIXct", 
"POSIXt")), Vorhersage = c(10.297922, 10.155121, 10.044135, 9.699513, 
14.821988, 14.832919, 14.706179, 14.573527), Export = c("10.912", 
"10.47", NA, NA, "17.198", "16.713", "16.378", "16.358"), color = c("rgb(0,128,0)", 
"rgb(0,128,0)", NA, NA, "rgb(0,128,0)", "rgb(0,128,0)", "rgb(0,128,0)", 
"rgb(0,128,0)"), Status = c("ok", "ok", NA, NA, "ok", "ok", "ok", 
"ok"), Plausibilität = c("4", "4", NA, NA, "4", "4", "4", "4"
), min = c(7.93000000000001, 9.4, 8.7, 8.3, 13.05, 12.808, 11.631891, 
12.312), max = c(12.31715325, 12.42822725, 12.51326325, 12.28620625, 
17, 17, 16.9, 16.7), Referenz = c(NA, NA, NA, NA, 16.6, 16.2, 
15.9, 16), DWD_Name = c(NA, NA, NA, NA, "Elpersbüttel", "Elpersbüttel", 
"Elpersbüttel", "Elpersbüttel")), row.names = c(NA, -8L), class = "data.frame")


感谢@r2evans 的帮助,我尝试了以下操作:

by = "Datum"

library(data.table)
colnms <- setdiff(intersect(names(df_a), names(df_b)), by)

setDT(df_a)
setDT(df_b)

merge(df_a, df_b, by = by, all = TRUE
)[, (colnms) := lapply(colnms, function(nm) fcoalesce(.SD[[paste0(nm, ".x")]], .SD[[paste0(nm, ".y")]]))
  ][, c(outer(colnms, c(".x", ".y"), paste0)) := NULL ][]
但我收到以下错误:
 Error in fcoalesce(.SD[[paste0(nm, ".x")]], .SD[[paste0(nm, ".y")]]) : 
  Item 2 is type double but the first item is type character. Please coerce 

最佳答案

大多数其他答案都很好,但许多答案要么使结果过于复杂(在我看来),要么执行左连接或右连接,而不是 OP 中预期的完全连接。
这是使用动态列名的快速解决方案。

library(data.table)
colnms <- setdiff(intersect(names(df_a), names(df_b)), "by")
colnms
# [1] "a"

setDT(df_a)
setDT(df_b)

merge(df_a, df_b, by = "by", all = TRUE
  )[, (colnms) := lapply(colnms, function(nm) fcoalesce(.SD[[paste0(nm, ".x")]], .SD[[paste0(nm, ".y")]]))
  ][, c(outer(colnms, c(".x", ".y"), paste0)) := NULL ][]
#       by     b     c     a
#    <num> <num> <num> <num>
# 1:     1     1    NA     1
# 2:     2    NA     2     2
# 3:     3     3     3     3
# 4:     4    NA     4     4
笔记:
  • 正常 data.table::[合并只是一个左连接,所以我们需要使用 data.table::merge为了能够与 all=TRUE 完全连接;
  • 因为它正在使用 merge ,重复的列得到 .x.y后缀,我们可以轻松利用;
  • 使用 (colnms) := ... 时的规范和最高效的方式还包括 .SDcols=colnms ,但这在这里不起作用,因为我们需要后缀列,而不是 colnms列本身;这是一个轻微的性能损失,但肯定不是反模式(我相信)考虑到我们需要做的事情;并且由于我们可能有多个重复的列,我们必须小心地一次处理每一对,而不是一次处理所有的列;
  • 最后 [ -block (使用 outer )用于删除重复列;没有它,输出将具有列名 c("by", "a.x", "b", "a.y", "c", "a") .它使用 outer因为这是获得 1 个或多个 colnms 的直接方法并结合 .x.y给他们每个人;然后它使用 data.table:= NULL删除一列或多列的快捷方式。
  • 关于r - 简单但不容易的合并任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69633238/

    相关文章:

    r - 使用shiny.io访问本地mysql服务器

    r - 在R中使用另一个 bool 向量对向量进行子集化

    c - 段错误合并排序程序

    git - 使用 merge 的提交重新设置Git

    在表中用 NA 替换 0

    r - 如何在ggplot中使用变量指定列名

    r - 在 R 中将函数与矢量参数集成

    ios - 使用 AcroFrom 连接 PDF 文件 - iOS

    根据 R 中的年份范围,将选定列的 NA 替换为 0

    r - 不删除 NA 的子集函数