Сворачивание ранжированной информации в один столбец

#r #for-loop #dplyr #tibble

#r #цикл for #dplyr #tibble

Вопрос:

У меня есть опрос, в котором люди оценивают некоторые школы. В результате опроса получается несколько столбцов с номерами 1 и 2. Мне нужно разделить их на людей первого и второго выбора. Вот пример данных, которые у меня есть.

 df1 <- tibble(Person  = c(1 , 2 , 3 , 4 , 5 , 6 , 7), 
School1 = c(NA, 1 , 2 , NA, NA, NA, 1 ), 
School2 = c(NA, 2 , 1 , NA, NA, 1 , NA), 
School3 = c(1 , NA, NA, NA, NA, 2 , NA),
School4 = c(2 , NA, NA, 1 , 2 , NA, NA), 
School5 = c(NA, NA, NA, 2 , 1 , NA, 2))

  Person School1 School2 School3 School4 School5
   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>
1      1      NA      NA       1       2      NA
2      2       1       2      NA      NA      NA
3      3       2       1      NA      NA      NA
4      4      NA      NA      NA       1       2
5      5      NA      NA      NA       2       1
6      6      NA       1       2      NA      NA
7      7       1      NA      NA      NA       2
  

Вот результат, который мне нужен.

 df2 <- tibble(Person  = c(1 , 2 , 3 , 4 , 5 , 6 , 7), 
School1 = c(NA, 1 , 2 , NA, NA, NA, 1 ), 
School2 = c(NA, 2 , 1 , NA, NA, 1 , NA), 
School3 = c(1 , NA, NA, NA, NA, 2 , NA), 
School4 = c(2 , NA, NA, 1 , 2 , NA, NA), 
School5 = c(NA, NA, NA, 2 , 1 , NA, 2), 
Firstchoice = c('School3', 'School1', 'School2', 'School4', 'School5', 'School2', 'School1'), 
Secondchoice = c('School4', 'School2', 'School1', 'School5', 'School4', 'School3', 'School5'))

  Person School1 School2 School3 School4 School5 Firstchoice Secondchoice
   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl> <chr>       <chr>       
1      1      NA      NA       1       2      NA School3     School4     
2      2       1       2      NA      NA      NA School1     School2     
3      3       2       1      NA      NA      NA School2     School1     
4      4      NA      NA      NA       1       2 School4     School5     
5      5      NA      NA      NA       2       1 School5     School4     
6      6      NA       1       2      NA      NA School2     School3     
7      7       1      NA      NA      NA       2 School1     School5 
  

Я посмотрел на mutate и, используя цикл for, однако я не могу понять, как заставить их работать, поскольку им нужно было бы выполнять встроенные обновления столбца.

Будем признательны за любую помощь.

Ответ №1:

Одной tidyverse возможностью может быть:

  df1 %>%
  gather(var, val, -Person) %>%
  mutate(val = ifelse(val == 1, "Firstchoice", 
                      ifelse(val == 2, "Secondchoice", NA_character_))) %>%
  na.omit() %>%
  spread(val, var) %>%
  left_join(df1, by = c("Person" = "Person"))

  Person Firstchoice Secondchoice School1 School2 School3 School4 School5
   <dbl> <chr>       <chr>          <dbl>   <dbl>   <dbl>   <dbl>   <dbl>
1      1 School3     School4           NA      NA       1       2      NA
2      2 School1     School2            1       2      NA      NA      NA
3      3 School2     School1            2       1      NA      NA      NA
4      4 School4     School5           NA      NA      NA       1       2
5      5 School5     School4           NA      NA      NA       2       1
6      6 School2     School3           NA       1       2      NA      NA
7      7 School1     School5            1      NA      NA      NA       2
  

Ответ №2:

Проще простого с tidyr:

 choices <- gather(df1, key = "school", value = "choice", -Person, na.rm=TRUE)
choices <- arrange(choices, Person, choice)