Сопоставление значений на основе части столбца

#r #dplyr

Вопрос:

У меня есть следующие кадры данных:

 df_start <- tibble(
    id = 1:4,
    codes = c("a, d", "d, e", "e, a", "e"),
)

df_mapping <- tibble(
    code = c("a", "b", "c", "d", "e"),
    value = c("first", "first", "first", "second", "third")
)
 

Теперь я хочу сопоставить коды df_start$с кодом df_mapping$, чтобы получить связанное значение кода.

Поэтому, если код df_mapping$появляется в кодах df_start$, он должен получить соответствующее значение, при этом значения имеют определенный порядок (если возможны как «первый», так и «второй», он должен быть «первым». Таким образом, результат должен быть:

 df_start_end <- tibble(
    id = 1:4,
    codes = c("a, d", "d, e", "e, a", "e"),
    value = c("first", "second", "first", "third")
)
 

Вопрос в том, как это сделать? На практике существует ~300 уникальных кодов df_mapping$, ~2500 уникальных кодов df_start$и ~10 уникальных значений df_mapping$.

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

 df_mapping <- df_mapping %>%
    mutate(order = case_when(
        value == "first" ~ 1,
        value == "second" ~ 2,
        value == "third" ~ 3
    ))

df_start <- df_start %>%
    mutate(codes_backup = codes) %>%
    separate_rows(
        codes, 
        sep = ", ")

df_start_end <- df_start %>%
    left_join(df_mapping, by = c("codes" = "code")) %>%
    group_by(codes_backup) %>%
    filter(value == min(value)) %>%
    ungroup() %>%
    mutate(codes = codes_backup) %>%
    select(-c(codes_backup, order))
 

Ответ №1:

Это похоже на ваш подход, но без создания временной переменной.

 library(dplyr)
library(tidyr)

df_start %>%
  separate_rows(codes, sep = ',\s*') %>%
  left_join(df_mapping, by = c('codes' = 'code')) %>%
  arrange(id, codes) %>%
  group_by(id) %>%
  summarise(codes = toString(codes), 
            value = na.omit(value)[1])

#    id codes value 
#  <int> <chr> <chr> 
#1     1 a, d  first 
#2     2 d, e  second
#3     3 a, e  first 
#4     4 e     third 
 

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

1. Спасибо за ответ, это работает только в том случае, если коды df_start$и порядок отображения df_mapping в алфавитном порядке, верно?

2. Да, это верно. Если порядок не является алфавитным, вы можете создать новый столбец с именем order df_mapping , т. е. df_mapping <- df_mapping %>% mutate(order = row_number()) , и теперь упорядочить его в соответствии с этим столбцом.