Замена значений символов из фрейма данных в R на основе другого фрейма данных - PullRequest
0 голосов
/ 19 марта 2020

Я пытаюсь заменить большое количество значений во фрейме данных на основе «кодовой книги» значений. У меня есть два тиббла:

head(df)
# A tibble: 6 x 6
  responseid color  q1_first_choice q1_second_choice q1_third_choice 
       <dbl> <chr>  <chr>           <chr>            <chr>                     
1         34 red    q1_red_b        q1_red_a         Pomegranate     
2         35 blue   q1_blue_a       q1_blue_c        q1_blue_b       
3         36 green  Tangerine       q1_green_b       q1_green_a      
4         37 purple q1_purple_b     q1_purple_a      q1_purple_c     
5         38 red    q1_red_a        Watermelon       q1_red_c        
6         39 green  q1_green_a      q1_green_c       q1_green_b    

head(codes)
# A tibble: 6 x 2
  Code      Name     
  <chr>     <chr>    
1 q1_red_a  Apple    
2 q1_red_b  Raspberry
3 q1_red_c  Cherry   
4 q1_blue_a Banana   
5 q1_blue_b Orange   
6 q1_blue_c Pineapple

Я хотел бы заменить значения в df в большом количестве столбцов кодами $ Name-значения. В команде слишком много значений для ввода, поэтому я хочу сослаться на столбцы в кодах.

Я думаю, что ответом может быть какое-то изменение case_when, recode или chartr, но я могу ' Кажется, я не могу понять, как определить это в этих функциях.

Ответы [ 2 ]

0 голосов
/ 19 марта 2020

Вот мой вывод:

Сначала переведите набор данных в длинную форму. Это особенно полезно, если варианты ответов являются общими для каждого столбца.

Затем объедините длинный набор данных со своей кодовой книгой, чтобы получить новые имена.

Наконец, (необязательно?) Объедините два столбца вместе, чтобы сохранить варианты ответов, которые не отображаются в вашей кодовой книге. Я говорю опционально, потому что этот шаг необходим, только если есть оригинальные варианты ответа, которые не отображаются в вашей кодовой книге.

library(tidyverse)

df <- tribble(
  ~responseid,   ~color,  ~q1_first_choice, ~q1_second_choice, ~q1_third_choice,
           34,    "red",        "q1_red_b",        "q1_red_a",    "Pomegranate",
           35,   "blue",       "q1_blue_a",       "q1_blue_c",      "q1_blue_b",
           36,  "green",       "Tangerine",      "q1_green_b",     "q1_green_a",
           37, "purple",     "q1_purple_b",     "q1_purple_a",    "q1_purple_c",
           38,    "red",        "q1_red_a",      "Watermelon",       "q1_red_c",
           39,  "green",      "q1_green_a",      "q1_green_c",     "q1_green_b"
)

codes <- tribble(
        ~Code,       ~Name,
   "q1_red_a",     "Apple",
   "q1_red_b", "Raspberry",
   "q1_red_c",    "Cherry",
  "q1_blue_a",    "Banana",
  "q1_blue_b",    "Orange",
  "q1_blue_c", "Pineapple"
)

df_long <- df %>%
  pivot_longer(
    cols = starts_with("q"),
    values_to = "Code"
  )
df_long
#> # A tibble: 18 x 4
#>    responseid color  name             Code       
#>         <dbl> <chr>  <chr>            <chr>      
#>  1         34 red    q1_first_choice  q1_red_b   
#>  2         34 red    q1_second_choice q1_red_a   
#>  3         34 red    q1_third_choice  Pomegranate
#>  4         35 blue   q1_first_choice  q1_blue_a  
#>  5         35 blue   q1_second_choice q1_blue_c  
#>  6         35 blue   q1_third_choice  q1_blue_b  
#>  7         36 green  q1_first_choice  Tangerine  
#>  8         36 green  q1_second_choice q1_green_b 
#>  9         36 green  q1_third_choice  q1_green_a 
#> 10         37 purple q1_first_choice  q1_purple_b
#> 11         37 purple q1_second_choice q1_purple_a
#> 12         37 purple q1_third_choice  q1_purple_c
#> 13         38 red    q1_first_choice  q1_red_a   
#> 14         38 red    q1_second_choice Watermelon 
#> 15         38 red    q1_third_choice  q1_red_c   
#> 16         39 green  q1_first_choice  q1_green_a 
#> 17         39 green  q1_second_choice q1_green_c 
#> 18         39 green  q1_third_choice  q1_green_b

df_out <- df_long %>%
  left_join(codes, by = "Code") %>%
  mutate(Code = coalesce(Name, Code)) %>%
  select(responseid, color, name, Code) %>%
  pivot_wider(
    names_from = "name",
    values_from = "Code"
  )
df_out
#> # A tibble: 6 x 5
#>   responseid color  q1_first_choice q1_second_choice q1_third_choice
#>        <dbl> <chr>  <chr>           <chr>            <chr>          
#> 1         34 red    Raspberry       Apple            Pomegranate    
#> 2         35 blue   Banana          Pineapple        Orange         
#> 3         36 green  Tangerine       q1_green_b       q1_green_a     
#> 4         37 purple q1_purple_b     q1_purple_a      q1_purple_c    
#> 5         38 red    Apple           Watermelon       Cherry         
#> 6         39 green  q1_green_a      q1_green_c       q1_green_b

Создано в 2020-03-19 пакетом представ. (v0.3.0)

Для получения дополнительной информации о повороте взгляните на Поворотная виньетка в тидире.

0 голосов
/ 19 марта 2020

Мы можем использовать mutate_at до l oop над столбцами, которые начинаются с 'q1', и выполнить замену, передав именованный вектор, созданный из набора данных 'codes'

library(dplyr)
df %>%
    mutate_at(vars(starts_with('q1')), ~  setNames(codes$Name, codes$Code)[.])

Или другой вариант - сделать left_join после преобразования в 'длинный' формат

library(tidyr)
df %>%
   pivot_longer(cols = -c(responseid, color)) %>% 
   left_join(codes, by = c('value' = 'Code')) %>%
   mutate(value = coalesce(Name, value)) %>% 
   select(-Name) %>% 
   pivot_wider(names_from = name, values_from = value)

Или использовать base R

i1 <- startsWith(names(df), "q1")
v1 <- setNames(codes$Name, codes$Code)
df[i1] <- lapply(df[i1], function(x) v1[x])
...