Dplyr, объединить последовательные кадры данных в существующие столбцы, суммируя их значения - PullRequest
0 голосов
/ 23 апреля 2020

Я хочу выполнить несколько соединений с исходным кадром данных из одного источника с разными идентификаторами каждый раз. В частности, мне действительно нужно сделать только два объединения, но когда я выполняю второе объединение, объединяемые столбцы уже существуют во входном файле 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, но у меня будет гораздо большее количество переменных в самом наборе данных. Мне интересно, если это лучший способ сделать это.

Ответы [ 2 ]

2 голосов
/ 23 апреля 2020

Вы можете попробовать изменить ваши данные и использовать 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
1 голос
/ 29 апреля 2020

Вы можете использовать мой пакет safejoin , если для вас приемлемо использовать пакет github.

Идея состоит в том, что у вас есть конфликтующие столбцы, dplyr и база Чтобы справиться с конфликтом, переименуйте их, в то время как safejoin более гибок, вы можете использовать функцию, которую хотите применить в случае конфликтов. Здесь вы хотите добавить их, поэтому мы будем использовать conflict = `+`, для того же эффекта, который вы могли бы использовать conflict = ~ .x + .y или conflict = ~ ..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

Создано в 2020-04-29 представляет пакет (v0.3.0)

...