В R условное левое соединение двух таблиц в зависимости от значения индикаторной переменной в левой таблице

avatar
logjammin
8 августа 2021 в 21:55
52
1
0

Фон

У меня есть два фрейма данных о бейсбольных карточках и их рыночной стоимости. Эта информация взята из «Альманаха бейсбольных карточек», справочников по стоимости карт, публикуемых каждый год.

Первая, d, представляет собой таблицу с card_id каждой карты, а также индикатор almanac_flag, который сообщает вам, были ли card_id в этой строке из 1999 или 2009 года. выпуски Альманаха бейсбольных карточек:

d <- data.frame(card_id = c("48","2100","F7","2729","F4310","27700"), 
                almanac_flag = c(0,0,1,0,1,0), # 0 = 1999 Almanac, 1 = 2009 almanac 
                stringsAsFactors=T) 

Это выглядит так:

d

Второй кадр данных - d2, который содержит (не все) эквивалентные id за 1999 и 2009 годы, а также описание того, какой бейсболист изображен на этой карточке. Обратите внимание, что d2 не имеет всех идентификаторов, которые появляются в d — у него есть только 3 "совпадения", и это совершенно нормально.

d2 <- data.frame(card_id_1999 = c("48","2100","31"),
                card_id_2009 = c("J18","K02","F7"),
                description = c("Wade Boggs","Frank Thomas","Mickey Mantle"),
                stringsAsFactors=T) 

d2 выглядит так:

d2

Проблема

Я хочу соединить эти две таблицы, чтобы получить таблицу, которая выглядит следующим образом:

d_esired

Что я пробовал

Конечно, я мог бы использовать left_join с ключом card_id = card_id_1999 или card_id = card_id_2009, но это дает мне только половину того, что мне нужно, например:

d_tried <- left_join(d, d2, by = c("card_id" = "card_id_1999"))

Что дает мне следующее:

d_tried

В каком-то смысле я прошу сделать 2 соединения за один раз, но не знаю, как это сделать.

Есть мысли?

Источник

Ответы (1)

avatar
akrun
8 августа 2021 в 22:01
2

Если мы изменим форму на "длинный" формат из "d2", это должно сработать

library(dplyr)
library(tidyr)
d2 %>%
     pivot_longer(cols = starts_with('card'),
       values_to = 'card_id', names_to = NULL) %>% 
     right_join(d) %>%
     select(names(d), everything())

-выход

# A tibble: 6 x 3
  card_id almanac_flag description  
  <fct>          <dbl> <fct>        
1 48                 0 Wade Boggs   
2 2100               0 Frank Thomas 
3 F7                 1 Mickey Mantle
4 2729               0 <NA>         
5 F4310              1 <NA>         
6 27700              0 <NA>        

или другой вариант — match отдельно для каждого столбца (или объединить отдельно), а затем выполнить coalesce, например, будет выбран первый не-NA

d %>% 
   mutate(description = coalesce(d2$description[match(card_id, 
       d2$card_id_1999)], d2$description[match(card_id, d2$card_id_2009)]))
  card_id almanac_flag   description
1      48            0    Wade Boggs
2    2100            0  Frank Thomas
3      F7            1 Mickey Mantle
4    2729            0          <NA>
5   F4310            1          <NA>
6   27700            0          <NA>