tidyverse pivot_longer несколько наборов столбцов, но избегайте промежуточных шагов mutate_wider - PullRequest
1 голос
/ 22 апреля 2020

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

dat <- data.frame(id         = c("A", "B", "C"),
                  Q1r1_pepsi = c(1,0,1),
                  Q1r1_cola  = c(0,0,1),
                  Q1r2_pepsi = c(1,1,1),
                  Q1r2_cola  = c(0,1,1),
                  stringsAsFactors = FALSE)

, где Q1r1 и Q1r2 - рейтинговые вопросы в опросе, а pepsi и cola - оцениваемые бренды. Итак, у меня есть два рейтинга (r1 и r2) для двух брендов (pepsi, cola):

id      Q1r1_c1    Q1r1_c2    Q1r2_c1    Q1r2_c2
"A"     1          0          1          0
"B"     0          0          1          1
"C"     1          1          1          1

(Дополнительный вопрос: как мне отформатировать сообщение SO, чтобы оно правильно содержало красиво отформатированный вывод, который я будет получено при вызове dat в консоли R?)

Для анализа данных мне нужно изменить (развернуть) данные таким образом, чтобы в строках были указаны уникальные пары рейтинг-бренд. Таким образом, ожидаемый результат будет следующим:

id      brand   Q1r1    Q1r2
"A"     "pepsi" 1       1
"A"     "cola"  0       0
"B"     "pepsi" 0       1
"B"     "cola"  0       1
"C"     "pepsi" 1       1
"C"     "cola"  1       1

В настоящее время я всегда делаю комбинацию pivot_longer и pivot_wider, но я надеялся, что смогу напрямую получить этот результат с помощью pivoting_longer без выполнения промежуточного шаг:

library(tidyverse)

dat_long <- dat %>%
  pivot_longer(cols = starts_with("Q1")) %>%
  separate(name, into = c("item", "brand"), remove = FALSE)

dat_wide <- dat_long %>%
  pivot_wider(id_cols = c(id, brand),
              names_from = item,
              values_from = value)

В этом текущем примере все еще нормально делать этот промежуточный шаг, но он становится утомительным в других менее чистых примерах, например, предположим, что мои столбцы не были названы в хорошей структуре с Q1r1_c1, Q1r1_c2, Q1r2_c1, Q1r2_c2 , но вместо этого будет Q4, Q5, Q8r1, Q8r2, где карта будет между Q4 и Q8r1 и Q5 / Q8r2, соответственно.

Ответы [ 3 ]

3 голосов
/ 22 апреля 2020

Вы можете использовать:

tidyr::pivot_longer(dat, cols = -id, 
                   names_to = c('.value', 'brand'), 
                   names_sep = "_")


#  id    brand  Q1r1  Q1r2
#  <chr> <chr> <dbl> <dbl>
#1 A     pepsi     1     1
#2 A     cola      0     0
#3 B     pepsi     0     1
#4 B     cola      0     1
#5 C     pepsi     1     1
#6 C     cola      1     1
1 голос
/ 22 апреля 2020

Следуя предложению @Ronak Shah, я вставляю свой код здесь на случай, если имена моих столбцов менее структурированы. Я строю этот код на данных dat, которые я указал в своем первоначальном сообщении.

names(dat) <- c("id", "Q4", "Q5", "Q8r1", "Q8r2")

spec <- data.frame(.name  = names(dat)[-1],
                   .value = c("Q4Q5", "Q4Q5", "Q8", "Q8"),
                   brand  = rep(c("pepsi", "cola"), 2),
                   stringsAsFactors = FALSE)

dat_long <- pivot_longer_spec(dat, spec)

Это дает практически тот же результат, что и для данных с моими структурированными именами, только имена разные сейчас.

Опять же, я не совсем уверен, насколько обобщаем этот подход, но он работал в моем случае.

0 голосов
/ 22 апреля 2020

Мы можем использовать gather/spread

library(tidyr)
library(dplyr)
dat %>%
    gather(brand, value, -id) %>%
    separate(brand, into = c('name', 'brand')) %>% 
    spread(name, value)
#  id brand Q1r1 Q1r2
#1  A  cola    0    0
#2  A pepsi    1    1
#3  B  cola    0    1
#4  B pepsi    0    1
#5  C  cola    1    1
#6  C pepsi    1    1
...