首页 > 解决方案 > 合并两个数据集,涵盖所有可能的组合

问题描述

我在执行连接操作时遇到问题。

我的两个数据框是:

library(tidiverse)
df_one <- data.frame(
                cohort = c("2019-03-01", "2019-03-01", "2019-03-01", "2019-04-01",
                           "2019-04-01", "2019-05-01"),
               periods = c(1, 2, 3, 1, 2, 1),
                 value = c(13, 24, 35, 22, 38, 21)
          )

df_two <- data.frame(
               periods = c(1, 2, 3, 4),
               value_2 = c(100, 73, 45, 29)
          )

我想要实现的最终结果是一个连接的数据框,其中包含所有可能的组合df_two- 重复的元素df_one- 如下:

df_final <- data.frame(
                  cohort = c("2019-03-01", "2019-03-01", "2019-03-01", "2019-03-01",
                             "2019-04-01", "2019-04-01", "2019-04-01",
                             "2019-04-01", "2019-05-01", "2019-05-01", "2019-05-01",
                             "2019-05-01"),
                 periods = c(1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4),
                   value = c(13, 24, 35, NA, 22, 38, NA, NA, 21, NA, NA, NA),
                 value_2 = c(100, 73, 45, 29, 100, 73, 45, 29, 100, 73, 45, 29)
            )

       cohort periods value value_2
1  2019-03-01       1    13     100
2  2019-03-01       2    24      73
3  2019-03-01       3    35      45
4  2019-03-01       4    NA      29
5  2019-04-01       1    22     100
6  2019-04-01       2    38      73
7  2019-04-01       3    NA      45
8  2019-04-01       4    NA      29
9  2019-05-01       1    21     100
10 2019-05-01       2    NA      73
11 2019-05-01       3    NA      45
12 2019-05-01       4    NA      29

我尝试使用crossing()

crossing(df_one, df_two)

但我得到了错误:

Error: Column name `periods` must not be duplicated.
Run `rlang::last_error()` to see where the error occurred.

一旦修复了唯一列名 - 正如用户 @akrun 所建议的那样 - 通过:

crossing(df_one, df_two, .name_repair = "unique")

我意识到这crossing()不会产生我想要的结果。

我应该遵循什么方法来获得df_final

标签: rjoindplyrtidyverse

解决方案


crossing需要唯一的列名,“句点”是重复的。根据?crossing

穿越(...,.name_repair =“check_unique”)

这意味着默认选项将检查唯一的列名,如果有重复,它将引发错误。

library(dplyr)
library(tidyr)
library(stringr)

我们可以更改.name_repair强制列名为“唯一”

crossing(df_one, df_two, .name_repair = "unique")
#New names:
#* periods -> periods...2
#* periods -> periods...4
# A tibble: 24 x 5
#   cohort     periods...2 value periods...4 value_2
#   <chr>            <dbl> <dbl>       <dbl>   <dbl>
# 1 2019-03-01           1    13           1     100
# 2 2019-03-01           1    13           2      73
# 3 2019-03-01           1    13           3      45
# 4 2019-03-01           1    13           4      29
# 5 2019-03-01           2    24           1     100
# 6 2019-03-01           2    24           2      73
# 7 2019-03-01           2    24           3      45
# 8 2019-03-01           2    24           4      29
# 9 2019-03-01           3    35           1     100
#10 2019-03-01           3    35           2      73
# … with 14 more rows

或者使用“最小”,其中将保留重复的列名(但从长远来看,这会使事情变得更加复杂


为了达到预期,我们可以complete对第一个数据集进行分组,然后left_join对第二个数据集进行分组

df_one %>% 
   group_by(cohort) %>%
   complete(periods = df_two$periods) %>%
   left_join(df_two)
# A tibble: 12 x 4
# Groups:   cohort [3]
#   cohort     periods value value_2
#   <chr>        <dbl> <dbl>   <dbl>
# 1 2019-03-01       1    13     100
# 2 2019-03-01       2    24      73
# 3 2019-03-01       3    35      45
# 4 2019-03-01       4    NA      29
# 5 2019-04-01       1    22     100
# 6 2019-04-01       2    38      73
# 7 2019-04-01       3    NA      45
# 8 2019-04-01       4    NA      29
# 9 2019-05-01       1    21     100
#10 2019-05-01       2    NA      73
#11 2019-05-01       3    NA      45
#12 2019-05-01       4    NA      29

推荐阅读