【问题标题】:Merge 2 R dataframes keeping matched rows from 2nd dataframe and unmatched from 1st合并 2 个 R 数据帧,保持第二个数据帧的匹配行和第一个数据帧不匹配
【发布时间】:2021-03-28 18:14:38
【问题描述】:

我想通过以下方式匹配 id 列来合并 2 个数据帧

dfmain = 
  id  name val res
1  1    a    
2  2    b    
3  3    c    
4  4    d    
5  5    e   

dfsub = 
  id name  val    res
1  2 two   true   thanks
2  4 four  false  Sorry

得到

dfmain =
   id  name  val    res
1:  1  a      
2:  2  two   true   thanks
3:  3  c      
4:  4  four  false  Sorry
5:  5  e      

请注意-

  1. 两个数据框中的列的数量和名称将保持不变
  2. 第二个数据帧中的 id 值始终是第一个数据帧中的子集

目前我正在使用 anti_join 函数在第一个数据帧中获取不匹配的行并将第二个数据帧加入这些行

有没有更有效的方法来做到这一点?

尝试使用 data.table 库中的 setDT,但我一次只能更新一列的值。

很抱歉,如果我缺少任何明显的解决方案,因为我是 R 新手,任何帮助都将不胜感激

【问题讨论】:

  • 我认为惯用的方式是cols <- c("name", "val", "res"); dfmain[dfsub, on=.(id), (cols) := mget(paste0("i.", cols))]。这很可能是一个骗局。例如,stackoverflow.com/questions/15005666/…

标签: r dataframe dplyr data.table


【解决方案1】:

你可以试试(感谢@Anoushiravan R 提供的数据)

library(data.table)
library(dplyr)

setDT(dfsub)[setDT(dfmain),
  on = "id"
][,
  names(dfmain),
  with = FALSE
][
  ,
  Map(coalesce, .SD, dfmain)
]

给了

   id name   val    res
1:  1    a    NA   <NA>
2:  2  two  TRUE thanks
3:  3    c    NA   <NA>
4:  4 four FALSE  Sorry
5:  5    e    NA   <NA>

【讨论】:

  • 我还想要第一个数据名中不匹配的行(类似于左连接)
【解决方案2】:

我希望这是您的想法,否则请告诉我。我注意到您仅通过保留 dfsub 的列将 dfmain 中的行替换为 dfsub 中具有相同 id 的行,所以我认为这可能会让您得到您想要的:

library(dplyr)

dfmain <- tribble(
    ~id,  ~name, ~ val, ~ res,
  1,    "a",    NA,     NA,
  2,    "b",    NA,     NA,
  3,    "c",    NA,     NA,
  4,    "d",    NA,     NA,
  5,    "e" ,   NA,     NA
)

dfsub <- tribble(
    ~id, ~name,  ~val,    ~res,
  2, "two",   TRUE,   "thanks",
  4 ,"four",  FALSE,  "Sorry"
)

dfmain %>%
  filter(! id %in% dfsub$id) %>%
  bind_rows(dfsub) %>%
  arrange(id)

# A tibble: 5 x 4
     id name  val   res   
  <dbl> <chr> <lgl> <chr> 
1     1 a     NA    NA    
2     2 two   TRUE  thanks
3     3 c     NA    NA    
4     4 four  FALSE Sorry 
5     5 e     NA    NA  

【讨论】:

  • 是的,这与我想要做的类似,但只是为了澄清数据框一个也将有列 val 和 res 但它们最初将为空(空白或 NA)(即两个数据框将具有相同的列)。我只是在 dplyr 中使用 anti_join 做同样的过程,只是由于数据的绝对大小(数据帧 1 超过 150000 行,20 列,数据帧 2 高达 2000 行,20 列)我正在寻找一种更有效的方法,会试试这个,让你知道。谢谢!
  • 我通过将valres 列添加到 dfmain 来编辑我的答案,并得到了相同的答案,希望你这样做。
  • 另外,如果我的数据没有唯一键,我是否可以在过滤器语句中使用多列来正确匹配行 - 即过滤器 ( ! (name1 %in% dfsub$name1 & name2 %in% dfsub$name2 &......)) 前提是 name1 和 name2 列在两个数据帧中具有相同的条目
  • 如果您的数据没有唯一 id,您可以在使用我建议的代码之前对两个数据框使用 mutate(id = row_number) 自己创建它。
  • 从您共享的数据中,我意识到实现所需输出的一种方法是用收集 dfsub 列的 dfsub 行替换 dfmain 行。如果涉及更多场景,我们需要您分享更多信息,以便建议的解决方案更加高效和稳定。
猜你喜欢
  • 2021-03-10
  • 1970-01-01
  • 2013-06-23
  • 2018-04-28
  • 1970-01-01
  • 2020-10-09
  • 1970-01-01
  • 2018-11-12
相关资源
最近更新 更多