首页 > 解决方案 > 连接两个数据帧时检查所有值是否已连接的参数

问题描述

我经常有两个希望加入的数据框,我希望所有值都加入其中。如果不是所有值都出现在两个数据框中,我希望它返回一个错误。

这是一个MWE:

library(dplyr, warn.conflicts = FALSE)

df1  <- data.frame(
    id  = c(1:5),
    value1 = rep(1, 5)
)

print(df1)
#>   id value1
#> 1  1      1
#> 2  2      1
#> 3  3      1
#> 4  4      1
#> 5  5      1

df2  <- data.frame(
    id  = c(1:4),
    value2 = rep(2, 4)
)

print(df2)
#>   id value2
#> 1  1      2
#> 2  2      2
#> 3  3      2
#> 4  4      2

df3  <- inner_join(
    df1, 
    df2,
    by = "id")

print(df3)
#>   id value1 value2
#> 1  1      1      2
#> 2  2      1      2
#> 3  3      1      2
#> 4  4      1      2

# Check if all values have joined
stopifnot(
    nrow(df3) == max(nrow(df1), nrow(df2))
)
#> Error: nrow(df3) == max(nrow(df1), nrow(df2)) is not TRUE

reprex 包于 2021-03-31 创建(v1.0.0)

这有效,但我不喜欢stopifnot(). 感觉很麻烦,特别是如果我想覆盖 df2,那么我需要创建一个临时值df2_previous_row_num = nrow(df2),然后执行stopifnot(nrow(df2) == df2_previous_row_num).

此外,该nrow()测试仅在 id 中的所有值都是唯一的情况下才有效。还有其他方法,例如,stopifnot(c(df1$id %in% df3$id, df2$id %in% df3$id))但这些又是丑陋的。

我真正要寻找的是一个参数,如果某些值没有加入,它会使加入失败。像,inner_join(df1, df2, fail_if_not_all_present = TRUE)

我不喜欢 tidyverse - 如果有一个基本的 R 或 data.table 方法可以做到这一点,那么我会考虑这些。

有人知道吗?

标签: rdataframedplyrdata.tabletidyverse

解决方案


您可以尝试编写自定义内部连接函数。

custom_inner_join <- function(data1,data2,by, fail_if_not_all_present = FALSE) {
  if(fail_if_not_all_present) {
    vals1 <- do.call(paste, data1[cols])
    vals2 <- do.call(paste, data2[cols])
    if(all(vals1 %in% vals2) && all(vals2 %in% vals1)) {
      merge(data1, data2, by)
    } else stop('Not all key values are present')
  } else {
    merge(data1, data2, by)
  }
}

custom_inner_join(df1, df2, 'id')

#  id value1 value2
#1  1      1      2
#2  2      1      2
#3  3      1      2
#4  4      1      2

custom_inner_join(df1, df2, 'id', fail_if_not_all_present = TRUE)

custom_inner_join 中的错误(df1,df2,“id”,fail_if_not_all_present = TRUE):并非所有键值都存在


推荐阅读