Соедините два набора данных с двумя идентификаторами столбцов с отсутствующими данными в R

Мне нужно объединить два data.frame в R, и у обоих из них есть два кандидата id, но много недостающих данных (поэтому я не могу просто выбрать один и отфильтровать остальные).

ИЗМЕНИТЬ воспроизводимый пример обоих наборов данных и желаемого результата:

messy1 <- data.frame(id1 = c(11, NA, 13, 11, 12, NA), id2 = c(NA, 22, 23, 21, NA, 23), time = rep(1:2, each = 3))
messy2 <- data.frame(id1 = c(12, NA, 14, 14), id2 = c(22, 23, 24, NA), time = c(1, 1, 1, 2))
desired1 <- data.frame(id1 = rep(11:13, 2), id2 = rep(21:23, 2), time = rep(1:2, each = 3)) # 12/22 is only available in messy2
desired2 <- data.frame(id1 = c(12:13, 14, 14), id2 = c(22:23, 24, 24), time = c(rep(1, 3), 2)) # 13/23 is only available in messy1

desired_joined <- full_join(desired1, desired2)

> messy1
  id1 id2 time
1  11  NA    1
2  NA  22    1
3  13  23    1
4  11  21    2
5  12  NA    2
6  NA  23    2
> messy2
  id1 id2 time
1  12  22    1
2  NA  23    1
3  14  24    1
4  14  NA    2
> desired_joined
  id1 id2 time
1  11  21    1
2  12  22    1
3  13  23    1
4  11  21    2
5  12  22    2
6  13  23    2
7  14  24    1
8  14  24    2

ПОСЛЕДНИЕ РЕДАКТИРОВАНИЯ

приведенный выше пример теперь точно отражает проблему, которую я пытался решить. После выяснения этого комментарий, предоставленный @Ben, является фактическим решением.

Устаревшие части вопроса были удалены, чтобы не сбивать с толку тех, кто столкнется с этим в будущем.


person philsf    schedule 09.05.2021    source источник
comment
Рассмотрите возможность использования fill из tidyr — вы можете group_by id1 и fill на id2 (и наоборот).   -  person Ben    schedule 09.05.2021
comment
Это хорошее начало, спасибо! Я все еще не могу воспроизвести цель выше с этим подходом. Я отредактирую свою текущую попытку, чтобы увидеть, где я могу ошибаться.   -  person philsf    schedule 09.05.2021


Ответы (1)


Как я указал в своем последнем редактировании вопроса, решение состоит в том, чтобы сделать fill(). Что я обнаружил в реальном RWD, так это то, что лучше выполнить двойное заполнение с помощью id1 и id2 в каждом из наборов данных перед присоединением. Любой, кому нужно сделать что-то подобное, может использовать следующие шаги:

fill1 <- messy1 %>%
  group_by(id1) %>% fill(id2, .direction = "downup") %>%
  group_by(id2) %>% fill(id1, .direction = "downup") %>%
  ungroup()

fill2 <- messy2 %>%
  group_by(id1) %>% fill(id2, .direction = "downup") %>%
  group_by(id2) %>% fill(id1, .direction = "downup") %>%
  ungroup()

full_join(messy1, messy2) %>%
  group_by(id1) %>% fill(id2, .direction = "downup") %>%
  group_by(id2) %>% fill(id1, .direction = "downup") %>%
  ungroup() %>%
  distinct()

Joining, by = c("id1", "id2", "time")
# A tibble: 8 x 3
# Groups:   id2 [4]
    id1   id2  time
  <dbl> <dbl> <dbl>
1    11    21     1
2    12    22     1
3    13    23     1
4    11    21     2
5    12    22     2
6    13    23     2
7    14    24     1
8    14    24     2

Примечание. Мои фактические наборы данных имеют ~ 65 тыс. строк каждый, но если я join перед fill, я получаю 2,5 млн строк (причина ускользает от меня). Выполняя все эти fill, я получаю гораздо более разумные 73 тыс. строк.

person philsf    schedule 09.05.2021