Dplyr case_when программно сравнивая варианты и условия в разных фреймах данных

Итак, у меня есть несколько студентов, которые написали анкету в Google. Опрос находится в строковой форме, где они выбирают раскрывающееся меню с такими параметрами, как:

Мне не грустно
Иногда мне грустно
Мне часто грустно
Мне все время грустно

Это тип вопроса, смоделированный на основе инвентаризации депрессии Бека. Каждому элементу соответствует 0,1,2,3 соответственно.

Всего таких переменных около 20.

Итак, у меня есть 2 фрейма данных.

df1 содержит данные опроса (строки ответов). Вот 2 из этих переменных

    head(df1[1:7,c('sad','optimism')])
    sad                                       optimism                                
     <chr>                                     <chr>                                   
    1 Throughout the day I sometimes feel sad   I am somewhat optimistic about my future
    2 Throughout the day I sometimes feel sad   I am somewhat optimistic about my future
    3 Throughout the day I sometimes feel happy I feel discouraged about the future     
    4 Throughout the day I sometimes feel happy I am optimistic about my future         
    5 Throughout the day I sometimes feel happy I am somewhat optimistic about my future
    6 Throughout the day I sometimes feel happy I am somewhat optimistic about my future
    7 Throughout the day I sometimes feel happy I feel discouraged about the future   

df2 имеет ключ условий

    head(df2[1:4,c('sad','optimism')])
     sad                                   optimism                                              
      <chr>                                 <chr>                                                 
    1 Throughout the day I feel happy       I am optimistic about my future                       
    2 Throughout the day I sometimes feel … I am somewhat optimistic about my future              
    3 Throughout the day I sometimes feel … I feel discouraged about the future                   
    4 Throughout the day I feel sad         I feel the future is hopeless and that things cannot …

Имена переменных одинаковы во всех фреймах данных.

Я хочу использовать case_when dplyr, используя каналы, чтобы взять каждую переменную из df1 и сравнить ее с соответствующим столбцом в df2.

Следующий код действительно работает при преобразовании строки в число, но если вы заметили, что case_when conditional проверяет всю строку фрейма данных, что совершенно не нужно. Я хочу просто проверить переменную df1$sad из опроса с df2$sad ключа.

    df1 %>%   mutate(across(x,~case_when(

    # The following lines of code checks a given record statement 
    # with ALL columns. Should only check indexed column
                                          . %in% df2[2,] ~ 0, #checks across all variables in df2; I just want to check a single column  
                                          . %in% df2[3,] ~ 1,
                                          . %in% df2[4,] ~ 2,
                                          . %in% df2[5,] ~ 3)))

Итак, несколько вопросов:

  1. Я не уверен, что case_when смогу это сделать
  2. Если это так, мне интересно, нужно ли мне использовать точечную нотацию
  3. или, может быть, есть лучшее решение

возможные ответы, которые я не понимаю (пока)

[1.]: dplyr case_when Это может быть лучшим выбором ... Не знаю, как обдумать все это .

[2.]: dplyr case_when Программно

  1. dplyr case_when multiple cases выглядит многообещающим

person Brian Holt    schedule 03.03.2021    source источник


Ответы (2)


Я думаю, для этого нужны left_joins, а не case_when ().

Создайте таблицы:

library(tidyverse)

df1 <- tibble::tribble(
  ~x, ~sad, ~optimism,
  "1", "Throughout the day I sometimes feel sad", "I am somewhat optimistic about my future",
  "2", "Throughout the day I sometimes feel sad", "I am somewhat optimistic about my future",
  "3", "Throughout the day I sometimes feel happy", "I feel discouraged about the future",
  "4", "Throughout the day I sometimes feel happy", "I am optimistic about my future",
  "5", "Throughout the day I sometimes feel happy", "I am somewhat optimistic about my future",
  "6", "Throughout the day I sometimes feel happy", "I am somewhat optimistic about my future",
  "7", "Throughout the day I sometimes feel happy", "I feel discouraged about the future"
)

df2 <- tibble::tribble(
  ~y, ~sad, ~optimism,
   "1", "Throughout the day I feel happy", "I am optimistic about my future"
  ,"2", "Throughout the day I sometimes feel happy", "I am somewhat optimistic about my future"
  ,"3", "Throughout the day I sometimes feel sad", "I feel discouraged about the future"
  ,"4", "Throughout the day I feel sad", "I feel the future is hopeless and that things cannot"
)

Присоединяйтесь к таблице поиска df2. Обратите внимание, что можно уменьшить таблицу поиска до одного столбца за раз (поэтому сначала грустно, а во-вторых - оптимизм):

df1 %>% 
  left_join(df2 %>% 
              select(y,
                     sad), by = "sad") %>% 
  left_join(df2 %>% 
              select(y,
                     optimism), by = "optimism") %>% 
# columns can be renamed within the select statement which is useful to reorder the coded columns next to the text
  select(x,
         sad,
         sad_coded = y.x,
         optimism,
         optimism_coded = y.y
         )

Надеюсь, это поможет - дайте мне знать, ожидали ли вы другого результата.

# A tibble: 7 x 5
  x     sad                        sad_coded optimism                  optimism_coded
  <chr> <chr>                      <chr>     <chr>                     <chr>         
1 1     Throughout the day I some~ 3         I am somewhat optimistic~ 2             
2 2     Throughout the day I some~ 3         I am somewhat optimistic~ 2             
3 3     Throughout the day I some~ 2         I feel discouraged about~ 3             
4 4     Throughout the day I some~ 2         I am optimistic about my~ 1             
5 5     Throughout the day I some~ 2         I am somewhat optimistic~ 2             
6 6     Throughout the day I some~ 2         I am somewhat optimistic~ 2             
7 7     Throughout the day I some~ 2         I feel discouraged about~ 3  
person Zoë Turner    schedule 03.03.2021
comment
Спасибо. Я приходил к выводу, что left_join, но сейчас я пытаюсь сделать это со многими переменными. Так что вместо «грусти» и «оптимизма» для этого есть еще 20 переменных. Трубопровод работает для нескольких переменных, но я не вижу способа его масштабировать. - person Brian Holt; 04.03.2021
comment
Думаю изменить характер 2-го фрейма данных. Вместо того, чтобы он был широким, я бы сделал его длинным / высоким, чтобы первый столбец содержал все возможные утверждения опроса, а второй столбец повторял 0: 3. И я думаю, что тогда left_join будет работать для всех переменных. - person Brian Holt; 04.03.2021
comment
Да, определенно лучший подход, делающий df2 длиннее. - person Zoë Turner; 04.03.2021

Вместо использования case_when и сопоставления каждого предложения в df2 по отдельности вы можете использовать match, который даст индекс соответствия. В базе R вы можете использовать Map.

cols <- names(df1)
df1[paste0(cols, '_num')] <- Map(match, df1[cols], df2[cols])

df1
# A tibble: 7 x 4
#   sad                                       optimism                                sad_num optimism_num
#  <chr>                                     <chr>                                     <int>        <int>
#1 Throughout the day I sometimes feel sad   I am somewhat optimistic about my futu…       3            2
#2 Throughout the day I sometimes feel sad   I am somewhat optimistic about my futu…       3            2
#3 Throughout the day I sometimes feel happy I feel discouraged about the future           2            3
#4 Throughout the day I sometimes feel happy I am optimistic about my future               2            1
#5 Throughout the day I sometimes feel happy I am somewhat optimistic about my futu…       2            2
#6 Throughout the day I sometimes feel happy I am somewhat optimistic about my futu…       2            2
#7 Throughout the day I sometimes feel happy I feel discouraged about the future           2            3

Или map2 в purrr, если вам нужен вариант tidyverse -

df1[paste0(cols, '_num')] <- purrr::map2(df1[cols], df2[cols], match)

данные

df1 <- structure(list(sad = c("Throughout the day I sometimes feel sad", 
"Throughout the day I sometimes feel sad", "Throughout the day I sometimes feel happy", 
"Throughout the day I sometimes feel happy", "Throughout the day I sometimes feel happy", 
"Throughout the day I sometimes feel happy", "Throughout the day I sometimes feel happy"
), optimism = c("I am somewhat optimistic about my future", "I am somewhat optimistic about my future", 
"I feel discouraged about the future", "I am optimistic about my future", 
"I am somewhat optimistic about my future", "I am somewhat optimistic about my future", 
"I feel discouraged about the future")), row.names = c(NA, -7L
), class = c("tbl_df", "tbl", "data.frame"))

df2 <- structure(list(sad = c("Throughout the day I feel happy", "Throughout the day I sometimes feel happy", 
"Throughout the day I sometimes feel sad", "Throughout the day I feel sad"
), optimism = c("I am optimistic about my future", "I am somewhat optimistic about my future", 
"I feel discouraged about the future", "I feel the future is hopeless and that things cannot"
)), row.names = c(NA, -4L), class = c("tbl_df", "tbl", "data.frame"
))
person Ronak Shah    schedule 20.05.2021