R - левое соединение (слияние) с частью данных (т.е. с отсутствующими метками)?

У меня есть большой набор данных пациентов с их медицинскими картами.

Почти у всех есть MainSpecialtyCode, но соответствующее MainSpecialtyDescription более разрежено.

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

Возможно ли левое соединение только для тех, у кого отсутствуют метки?

Или мне нужно разделить данные и объединить их, как я сделал ниже.

Интересно, есть ли одношаговая альтернатива для этого.

  library(dplyr)

  # Mock data
  set.seed(1)
  MyData <- data.frame(
   patientID = c(LETTERS[seq(from=1, to=10)]),
   MainSpecialtyCode = c(1,2,3,4,6,11,8,1,2,3),
   MainSpecialtyDescription = c(NA, NA, NA, NA, "Geriatric", "Nursing", 
   "Cardiology","Nephrology", NA, NA)
  )
  SpecialtyDictionary <- data.frame(
   MainSpecialtyCode = c(1,2,3,4,5,6,7,8,9,10),
   MainSpecialtyDescription = c("Cardiology", "Nephrology", "Respiratory", 
   "Cancer", "General", "Paediatric", "Urinary", "Diabetes", "Podiatry",  
   "Nursing")
  )

  # Subset data with missing descriptions
  MissingData <- MyData[is.na(MyData$MainSpecialtyDescription), ]

  # Merge descriptions onto this
  MergedData <- MissingData %>% 
    select(-MainSpecialtyDescription) %>% 
    left_join(SpecialtyDictionary, by="MainSpecialtyCode")

  # Append onto data without missing descriptions
  MyData2 <- rbind(MyData[!is.na(MyData$MainSpecialtyDescription), ], MergedData)

person Dani    schedule 06.02.2019    source источник
comment
В вашем словаре код для Nursing равен 10, а для MyData — 11. Это опечатка?   -  person utubun    schedule 06.02.2019
comment
@utubun Нет, это преднамеренно - я хочу сохранить существующие описания, даже если они неверны. По сути, я не хочу перезаписывать существующие описания в MyData.   -  person Dani    schedule 06.02.2019


Ответы (1)


Purrr может быть лучшим пакетом для этого, но одним из способов сделать это с dplyr может быть:

MyData %>% 
    filter(is.na(MainSpecialtyDescription)) %>% # deal only with NAs
    select(-MainSpecialtyDescription) %>% # remove column to be overwritten
    left_join(SpecialtyDictionary, by = "MainSpecialtyCode") %>% # get the values from dictionary
    bind_rows(MyData %>%  
                  filter(!is.na(MainSpecialtyDescription))) # bind the result to the original input

Урожайность:

> MyData %>% 
+     filter(is.na(MainSpecialtyDescription)) %>% 
+     select(-MainSpecialtyDescription) %>% 
+     left_join(SpecialtyDictionary, by = "MainSpecialtyCode") %>% 
+     bind_rows(MyData %>%  filter(!is.na(MainSpecialtyDescription)))
   patientID MainSpecialtyCode MainSpecialtyDescription
1          A                 1               Cardiology
2          B                 2               Nephrology
3          C                 3              Respiratory
4          D                 4                   Cancer
5          I                 2               Nephrology
6          J                 3              Respiratory
7          E                 6                Geriatric
8          F                11                  Nursing
9          G                 8               Cardiology
10         H                 1               Nephrology

РЕДАКТИРОВАТЬ: Вот альтернативное решение с использованием purrr::map по запросу OP:

MyData %>% 
    mutate(MainSpecialtyDescription = as.character(MainSpecialtyDescription)) %>% 
    mutate(MainSpecialtyDescription = 
           ifelse(is.na(MainSpecialtyDescription),
           purrr::map_chr(.x = .$MainSpecialtyCode, ~ as.character(SpecialtyDictionary$MainSpecialtyDescription[match(.x, SpecialtyDictionary$MainSpecialtyCode)])), 
           MainSpecialtyDescription))

Урожайность:

> MyData %>% 
+     mutate(MainSpecialtyDescription = as.character(MainSpecialtyDescription)) %>% 
+     mutate(MainSpecialtyDescription = 
+            ifelse(is.na(MainSpecialtyDescription),
+            purrr::map_chr(.x = .$MainSpecialtyCode, ~ as.character(SpecialtyDictionary$MainSpecialtyDescription[match(.x, SpecialtyDictionary$MainSpecialtyCode)])), 
+            MainSpecialtyDescription))
   patientID MainSpecialtyCode MainSpecialtyDescription
1          A                 1               Cardiology
2          B                 2               Nephrology
3          C                 3              Respiratory
4          D                 4                   Cancer
5          E                 6                Geriatric
6          F                11                  Nursing
7          G                 8               Cardiology
8          H                 1               Nephrology
9          I                 2               Nephrology
10         J                 3              Respiratory

Обратите внимание на преобразование факторов в строки. Преимущество в том, что вы можете обойтись указанием условия только один раз.

Кредит должен быть в основном здесь: Как Я использую purrr для сопоставления записей из таблицы поиска?

person Radim    schedule 06.02.2019
comment
Большой! Благодарю вас! - person Dani; 06.02.2019
comment
Если не сложно, не могли бы вы поделиться, как использовать для этого пакет purrr? - person Dani; 06.02.2019
comment
Рад, что это работает для вас, так или иначе. Единственная хитрость в дополнение к уже опубликованному решению для сопоставления таблиц поиска с purrr::map — это условное mutate. - person Radim; 06.02.2019
comment
Великолепно! Спасибо, мне нужно будет использовать много таблиц поиска, так что это действительно удобно. Я еще почитаю, как работает пакет purrr. - person Dani; 06.02.2019