Объединение нескольких столбцов с несколькими таблицами поиска

#r #join #data-manipulation

#r #Присоединиться #манипулирование данными

Вопрос:

У меня есть задача воспроизвести процесс из SAS в R. У меня есть 1 таблица с 1,4 миллионами строк и 156 столбцами за каждый из последних 71 месяцев. В столбцах есть только идентификаторы, и они должны быть заменены текстом.

Для этого существует 60 таблиц поиска. Некоторые из них используются несколько раз, а некоторые-только один раз.

Я не могу показать реальные данные, но вот небольшой пример того, как выглядит таблица.:

 df lt;-tibble(contract_id = c(1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010),  feature_a = c(1, 2, 3, 1, 2, 3, 1, 2, 3, 1),  feature_b = c(3, 2, 1, 3, 2, 1, 3, 2, 1, 3),  feature_c = c(2, 3, 1, 2, 3, 1, 2, 3, 1, 2),  feature_d = c(1, 2, 1, 2, 1, 2, 1, 2, 1, 2),  feature_e = c(2, 1, 2, 1, 2, 1, 2, 1, 2, 1),  feature_f = c(2, 2, 1, 1, 2, 2, 1, 1, 2, 2))   contract_id feature_a feature_b feature_c feature_d feature_e feature_f  lt;dblgt; lt;dblgt; lt;dblgt; lt;dblgt; lt;dblgt; lt;dblgt; lt;dblgt;  1001 1 3 2 1 2 2  1002 2 2 3 2 1 2  1003 3 1 1 1 2 1  1004 1 3 2 2 1 1  1005 2 2 3 1 2 2  1006 3 1 1 2 1 2  1007 1 3 2 1 2 1  1008 2 2 3 2 1 1  1009 3 1 1 1 2 2  1010 1 3 2 2 1 2  

Это 2 из 60 таблиц поиска, которые используются несколько раз, например, lookup_a используется 8 раз, а lookup_b-15 раз:

 lookup_a = tibble(id = c(1, 2, 3),  value = c("yes", "no", "yes, mandatory"))   lookup_b = tibble(id = c(1, 2),  value = c("yes", "no"))  

Вот как должен выглядеть желаемый результат (feature_a — c использует lookup_a, а feature_d — f использует поиск b):

 df_expected lt;-tibble(contract_id = c(1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010),  feature_a = c("yes", "no", "yes, mandatory", "yes", "no", "yes, mandatory", "yes", "no", "yes, mandatory", "yes"),  feature_b = c("yes, mandatory", "no", "yes", "yes, mandatory", "no", "yes", "yes, mandatory", "no", "yes", "yes, mandatory"),  feature_c = c("no", "yes, mandatory", "yes", "no", "yes, mandatory", "yes", "no", "yes, mandatory", "yes", "no"),  feature_d = c("yes", "no", "yes", "no", "yes", "no", "yes", "no", "yes", "no"),  feature_e = c("no", "yes", "no", "yes", "no", "yes", "no", "yes", "no", "yes"),  feature_f = c("no", "no", "yes", "yes", "no", "no", "yes", "yes", "no", "no"))   contract_id feature_a feature_b feature_c feature_d feature_e feature_f  lt;dblgt; lt;chrgt; lt;chrgt; lt;chrgt; lt;chrgt; lt;chrgt; lt;chrgt;   1001 yes yes, mandatory no yes no no   1002 no no yes, mandatory no yes no   1003 yes, mandatory yes yes yes no yes   1004 yes yes, mandatory no no yes yes   1005 no no yes, mandatory yes no no   1006 yes, mandatory yes yes no yes no   1007 yes yes, mandatory no yes no yes   1008 no no yes, mandatory no yes yes   1009 yes, mandatory yes yes yes no no   1010 yes yes, mandatory no no yes no   

Я, конечно, могу создать объединение для каждого столбца, но это не совсем удовлетворяет. Я хотел бы, чтобы количество соединений было как можно меньше:

 df %gt;%   left_join(lookup_a, by = c("feature_a" = "id")) %gt;%   select(-feature_a) %gt;%   rename(feature_a = value)  

Я также пробовал разные способы работы с data.table или match, но я не нашел способа объединить несколько столбцов одновременно. У меня проблема в том, что изменены все столбцы, а не выбранные.

Вот мои вопросы:

  • есть ли способ выполнить объединение/сопоставление с таблицей поиска для нескольких столбцов одновременно (например, left_join) и использовать имена столбцов для переименования?
  • Или можно ли заменить значения сразу для нескольких столбцов?

Может быть, я сейчас думаю слишком сложно, и решение относительно простое.

Заранее благодарю вас!

Комментарии:

1. Вы должны прочитать о факторах в r. Они функционируют аналогично формату в SAS.

2. Привет @Джим, ты имеешь в виду stringasfactors = да или определишь факторы позже?

Ответ №1:

Добро пожаловать на SO! Вы можете заменить значения нескольких столбцов с помощью across mutate глагола, используя индекс столбца, который вы хотите изменить (от 2 до 4 для столбцов a до c и от 5 до 7 для столбцов d до f).:

 library(dplyr) df %gt;%   mutate(across(2:4,  ~case_when(. == 1 ~ "Yes",  . == 2 ~ "No",  . == 3 ~ "Yes, mandatory",  TRUE ~ "Error"))) %gt;%  mutate(across(5:7,  ~case_when(. == 1 ~ "Yes",  . == 2 ~ "No",  TRUE ~ "Error")))  

Выход:

 # A tibble: 10 x 7  contract_id feature_a feature_b feature_c feature_d feature_e feature_f  lt;dblgt; lt;chrgt; lt;chrgt; lt;chrgt; lt;chrgt; lt;chrgt; lt;chrgt;   1 1001 Yes Yes, mandatory No Yes No No   2 1002 No No Yes, mandatory No Yes No   3 1003 Yes, mandatory Yes Yes Yes No Yes   4 1004 Yes Yes, mandatory No No Yes Yes   5 1005 No No Yes, mandatory Yes No No   6 1006 Yes, mandatory Yes Yes No Yes No   7 1007 Yes Yes, mandatory No Yes No Yes   8 1008 No No Yes, mandatory No Yes Yes   9 1009 Yes, mandatory Yes Yes Yes No No  10 1010 Yes Yes, mandatory No No Yes No   

Комментарии:

1. Как неловко, что я не подумал о простом, но хорошем решении. @MonJeanJean Большое спасибо!! В настоящее время у меня недостаточно репутации для голосования