【问题标题】:Dplyr, join successive dataframes to pre-existing columns, summing their valuesDplyr,将连续的数据帧连接到预先存在的列,将它们的值相加
【发布时间】:2020-08-07 04:01:35
【问题描述】:

我想对原始数据帧执行多个连接,每次都来自具有不同 ID 的同一源。具体来说,我实际上只需要进行两次连接,但是当我执行第二次连接时,正在连接的列已经存在于输入 df 中,而不是使用 .x/.y 后缀添加这些具有新名称的列,我想将值与现有列相加。请参阅下面的代码以获取所需的输出。

# Input data:
values <- tibble(
  id = LETTERS[1:10],
  variable1 = 1:10,
  variable2 = (1:10)*10
)
df <- tibble(
  twin_id = c("A/F", "B/G", "C/H", "D/I", "E/J")
)
> values
# A tibble: 10 x 3
   id    variable1 variable2
   <chr>     <int>     <dbl>
 1 A             1        10
 2 B             2        20
 3 C             3        30
 4 D             4        40
 5 E             5        50
 6 F             6        60
 7 G             7        70
 8 H             8        80
 9 I             9        90
10 J            10       100
> df
# A tibble: 5 x 1
  twin_id
  <chr>  
1 A/F    
2 B/G    
3 C/H    
4 D/I    
5 E/J  

所以这是两个连接:

joined_df <- df %>%
  tidyr::separate(col = twin_id, into = c("left_id", "right_id"), sep = "/", remove = FALSE) %>%
  left_join(values, by = c("left_id" = "id")) %>%
  left_join(values, by = c("right_id" = "id"))

> joined_df
# A tibble: 5 x 7
  twin_id left_id right_id variable1.x variable2.x variable1.y variable2.y
  <chr>   <chr>   <chr>          <int>       <dbl>       <int>       <dbl>
1 A/F     A       F                  1          10           6          60
2 B/G     B       G                  2          20           7          70
3 C/H     C       H                  3          30           8          80
4 D/I     D       I                  4          40           9          90
5 E/J     E       J                  5          50          10         100

这是我想要的输出,使用我能看到的唯一方法来获得它:

output_df_wanted <- joined_df %>%
  mutate(
    variable1 = variable1.x + variable1.y,
    variable2 = variable2.x + variable2.y) %>%
  select(twin_id, left_id, right_id, variable1, variable2)

> output_df_wanted
# A tibble: 5 x 5
  twin_id left_id right_id variable1 variable2
  <chr>   <chr>   <chr>        <int>     <dbl>
1 A/F     A       F                7        70
2 B/G     B       G                9        90
3 C/H     C       H               11       110
4 D/I     D       I               13       130
5 E/J     E       J               15       150

我可以看到如何使用 mutate 语句来获得我想要的东西,但我在实际数据集中会有更多的变量。我想知道这是否是最好的方法。

【问题讨论】:

  • 如果你的数据集更大,但你仍然只做一对id(如twin_id),那么我认为这是最合理的方法。
  • 您也许可以在mutate 中使用dplyr-1.0.0across 来简化您的variable1variable2,...逻辑,但我不'尚未安装 1.0.0,不想未经测试就推测。
  • 有问题的数据集将类似于 twin_id (2 IDS) 但将有 6 个变量。它已经足够小了,我现在只需输入 6 个 mutate 语句就可以做到这一点,但我很感兴趣,因为我在搜索中找不到任何关于它的东西。这可能不是处理这类事情的最佳方式,但现实世界有时会有一些混乱的数据集

标签: r join merge dplyr tidyverse


【解决方案1】:

您可以尝试重塑数据并使用dplyr::summarise_at

library(tidyr)
library(dplyr)

df %>%
  separate(col = twin_id, into = c("left_id", "right_id"), sep = "/", remove = FALSE) %>%
  pivot_longer(-twin_id) %>% 
  left_join(values, by = c("value" = "id")) %>% 
  group_by(twin_id) %>% 
  summarise_at(vars(starts_with("variable")), sum) %>% 
  separate(col = twin_id, into = c("left_id", "right_id"), sep = "/", remove = FALSE)
## A tibble: 5 x 5
#  twin_id left_id right_id variable1 variable2
#  <chr>   <chr>   <chr>        <int>     <dbl>
#1 A/F     A       F                7        70
#2 B/G     B       G                9        90
#3 C/H     C       H               11       110
#4 D/I     D       I               13       130
#5 E/J     E       J               15       150

【讨论】:

    【解决方案2】:

    如果你可以接受使用 github 包,你可以使用我的包 safejoin

    想法是你有冲突的列,dplyr 和 base R 通过重命名它们来处理冲突,而 safejoin 更灵活,你可以使用你想要的功能适用于冲突的情况。您想在此处添加它们,因此我们将使用 conflict = `+`,以获得与使用 conflict = ~ .x + .yconflict = ~ ..1 + ..2 相同的效果。

    # remotes::install_github("moodymudskipper/safejoin")
    library(tidyverse)
    library(safejoin)
    values <- tibble(
      id = LETTERS[1:10],
      variable1 = 1:10,
      variable2 = (1:10)*10
    )
    
    df <- tibble(
      twin_id = c("A/F", "B/G", "C/H", "D/I", "E/J")
    )
    
    joined_df <- df %>%
      tidyr::separate(col = twin_id, into = c("left_id", "right_id"), sep = "/", remove = FALSE) %>%
      left_join(values, by = c("left_id" = "id")) %>%
      safe_left_join(values, by = c("right_id" = "id"), conflict = `+`)
    
    joined_df
    #> # A tibble: 5 x 5
    #>   twin_id left_id right_id variable1 variable2
    #>   <chr>   <chr>   <chr>        <int>     <dbl>
    #> 1 A/F     A       F                7        70
    #> 2 B/G     B       G                9        90
    #> 3 C/H     C       H               11       110
    #> 4 D/I     D       I               13       130
    #> 5 E/J     E       J               15       150
    

    reprex package (v0.3.0) 于 2020 年 4 月 29 日创建

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-08-31
      • 1970-01-01
      • 1970-01-01
      • 2019-05-01
      • 2023-04-05
      • 2021-08-04
      • 1970-01-01
      相关资源
      最近更新 更多