left_join 两个数据帧并覆盖

Posted

技术标签:

【中文标题】left_join 两个数据帧并覆盖【英文标题】:left_join two data frames and overwrite 【发布时间】:2016-02-25 20:00:20 【问题描述】:

我想合并两个数据帧,其中df2 覆盖NAdf1 中的任何值。 Merge data frames and overwrite values 提供了一个data.table 选项,但我想知道是否有办法使用dplyr 来做到这一点。我已经尝试了所有_join 选项,但似乎都没有这样做。有没有办法用dplyr 做到这一点?

这是一个例子:

df1 <- data.frame(y = c("A", "B", "C", "D"), x1 = c(1,2,NA, 4)) 
df2 <- data.frame(y = c("A", "B", "C"), x1 = c(5, 6, 7))

期望的输出:

  y x1
1 A  5
2 B  6
3 C  7
4 D  4

【问题讨论】:

left_join(df1, df2, by="y") %&gt;% transmute(y, x1 = ifelse(is.na(x1.y), x1.x, x1.y))?也许这可以添加到另一个答案中,而这个答案被骗了? (另一个不是data.table的具体问题) 【参考方案1】:

我认为您想要的是保留 df2 的值,并且只添加 df1 中不存在于 df2 中的值,这就是 anti_join 所做的:

“anti_join 从 x 中返回所有在 y 中没有匹配值的行,只保留来自 x 的列。”

我的解决方案:

df3 <- anti_join(df1, df2, by = "y") %>% bind_rows(df2)

Warning messages:
1: In anti_join_impl(x, y, by$x, by$y) :
  joining factors with different levels, coercing to character vector
2: In rbind_all(x, .id) : Unequal factor levels: coercing to character

> df3
Source: local data frame [4 x 2]

      y    x1
  (chr) (dbl)
1     D     4
2     A     5
3     B     6
4     C     7

这一行给出了所需的输出(以不同的顺序),但是,您应该注意警告消息,在使用数据集时,请务必将 y 作为字符变量读取。

【讨论】:

谢谢!最后!我的背景不是计算机科学,奇怪的是我很难找到这个答案。我应该一直在寻找什么? R merge dataframes with priorityR complete dataframe from other dataframe if values not presentR merge without overwriteR add rows if not present 等等……都失败了……【参考方案2】:

这是我现在使用的习惯用法,此外,它还处理保留不属于更新表的列。我使用了一些与 OP 不同的名称,但味道相似。

我要做的一件事是为连接中使用的键创建一个变量,因为我在几个地方使用它。但除此之外,它会执行所需的操作。

它本身不处理例如“如果值为 NA 则更新此行”的操作,但您应该在创建连接表时执行该条件。

library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union

.keys <- c("key1", "key2")

.base_table <- tribble(
    ~key1, ~key2, ~val1, ~val2,
    "A", "a", 0, 0,
    "A", "b", 0, 1,
    "B", "a", 1, 0,
    "B", "b", 1, 1)

.join_table <- tribble(
    ~key1, ~key2, ~val2,
    "A", "b", 100,
    "B", "a", 111)

# This works
df_result <- .base_table %>%
    # Pull off rows from base table that match the join table
    semi_join(.join_table, .keys) %>%
    # Drop cols from base table that are in join table, except for the key columns
    select(-matches(setdiff(names(.join_table), .keys))) %>%
    # Left join on the join table columns
    left_join(.join_table, .keys) %>%
    # Remove the matching rows from the base table, and bind on the newly joined result from above.
    bind_rows(.base_table %>% anti_join(.join_table, .keys))

df_result %>%
    print()
#> # A tibble: 4 x 4
#>   key1  key2   val1  val2
#>   <chr> <chr> <dbl> <dbl>
#> 1 A     b         0   100
#> 2 B     a         1   111
#> 3 A     a         0     0
#> 4 B     b         1     1

由reprex package (v0.3.0) 于 2019 年 12 月 12 日创建

【讨论】:

以上是关于left_join 两个数据帧并覆盖的主要内容,如果未能解决你的问题,请参考以下文章

如何在行级别上比较两个海量 Spark 数据帧并打印差异

比较两个数据帧并根据第一个df返回差异[重复]

如何在 Scala 中连接两个数据帧并通过索引从数据帧中选择几列?

我应该如何在 Pandas 中减去两个数据帧并显示所需的输出?

Pyspark:内部连接两个 pyspark 数据帧并从第一个数据帧中选择所有列,从第二个数据帧中选择几列

如果匹配,如何合并两个数据帧并从新列中的另一列返回数据?