#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 Большое спасибо!! В настоящее время у меня недостаточно репутации для голосования