У меня есть данные онлайн-опроса, в котором респонденты задают цикл вопросов 1-3 раза. Обзор программного обеспечения (Qualtrics) записывает эти данные в нескольких столбцах, то есть, В3.2 в обзоре будет иметь столбцы Q3.2.1.
, Q3.2.2.
и Q3.2.3.
:
df <- data.frame(
id = 1:10,
time = as.Date('2009-01-01') + 0:9,
Q3.2.1. = rnorm(10, 0, 1),
Q3.2.2. = rnorm(10, 0, 1),
Q3.2.3. = rnorm(10, 0, 1),
Q3.3.1. = rnorm(10, 0, 1),
Q3.3.2. = rnorm(10, 0, 1),
Q3.3.3. = rnorm(10, 0, 1)
)
# Sample data
id time Q3.2.1. Q3.2.2. Q3.2.3. Q3.3.1. Q3.3.2. Q3.3.3.
1 1 2009-01-01 -0.2059165 -0.29177677 -0.7107192 1.52718069 -0.4484351 -1.21550600
2 2 2009-01-02 -0.1981136 -1.19813815 1.1750200 -0.40380049 -1.8376094 1.03588482
3 3 2009-01-03 0.3514795 -0.27425539 1.1171712 -1.02641801 -2.0646661 -0.35353058
...
Я хочу объединить все столбцы QN.N * в аккуратные отдельные столбцы QN.N, в конечном итоге получится что-то вроде этого:
id time loop_number Q3.2 Q3.3
1 1 2009-01-01 1 -0.20591649 1.52718069
2 2 2009-01-02 1 -0.19811357 -0.40380049
3 3 2009-01-03 1 0.35147949 -1.02641801
...
11 1 2009-01-01 2 -0.29177677 -0.4484351
12 2 2009-01-02 2 -1.19813815 -1.8376094
13 3 2009-01-03 2 -0.27425539 -2.0646661
...
21 1 2009-01-01 3 -0.71071921 -1.21550600
22 2 2009-01-02 3 1.17501999 1.03588482
23 3 2009-01-03 3 1.11717121 -0.35353058
...
В tidyr
библиотеке есть gather()
функция, которая отлично подходит для объединения одного набора столбцов:
library(dplyr)
library(tidyr)
library(stringr)
df %>% gather(loop_number, Q3.2, starts_with("Q3.2")) %>%
mutate(loop_number = str_sub(loop_number,-2,-2)) %>%
select(id, time, loop_number, Q3.2)
id time loop_number Q3.2
1 1 2009-01-01 1 -0.20591649
2 2 2009-01-02 1 -0.19811357
3 3 2009-01-03 1 0.35147949
...
29 9 2009-01-09 3 -0.58581232
30 10 2009-01-10 3 -2.33393981
Результирующий фрейм данных, как и ожидалось, содержит 30 строк (10 индивидов, по 3 цикла в каждой). Однако сбор второго набора столбцов не работает правильно - он успешно создает два объединенных столбца Q3.2
и Q3.3
, но в итоге получается 90 строк вместо 30 (все комбинации из 10 индивидов, 3 петель Q3.2 и 3 петель Q3 .3; комбинации будут существенно увеличиваться для каждой группы столбцов в фактических данных):
df %>% gather(loop_number, Q3.2, starts_with("Q3.2")) %>%
gather(loop_number, Q3.3, starts_with("Q3.3")) %>%
mutate(loop_number = str_sub(loop_number,-2,-2))
id time loop_number Q3.2 Q3.3
1 1 2009-01-01 1 -0.20591649 1.52718069
2 2 2009-01-02 1 -0.19811357 -0.40380049
3 3 2009-01-03 1 0.35147949 -1.02641801
...
89 9 2009-01-09 3 -0.58581232 -0.13187024
90 10 2009-01-10 3 -2.33393981 -0.48502131
Есть ли способ использовать для gather()
этого несколько вызовов , комбинируя небольшие подмножества столбцов, как это, с сохранением правильного количества строк?
df %>% gather(loop_number, Q3.2, starts_with("Q3."))
seperate()
чтобы разделить значения Q3.3 (и выше) на их собственные столбцы. Но это все еще кажется действительно окольным хакерским решением…spread
Я работаю над решением сейчас: pdf %>% gather(question_number, Q3.2, starts_with("Q3.")) %>% mutate(loop_number = str_sub(question_number,-2,-2), question_number = str_sub(question_number,1,4)) %>% select(id, time, loop_number, question_number, Q3.2) %>% spread(key = question_number, value = Q3.2)
spread()
. Хотя множественные вызовы кажутся неизбежными в любом случае, будь то связкаgenerate()
работающих или вложенныхspread()
s…Ответы:
Мне такой подход кажется довольно естественным:
Сначала соберите все столбцы с вопросами, используйте
extract()
для разделения наquestion
иloop_number
, затемspread()
снова в столбцы вопросов.источник
Это можно сделать с помощью
reshape
.dplyr
Хотя это возможно .Или используя
dplyr
Обновить
С
tidyr_0.8.3.9000
, мы можем использоватьpivot_longer
для изменения формы нескольких столбцов. (Используя измененные имена столбцов,gsub
указанные выше)ПРИМЕЧАНИЕ. Значения отличаются, поскольку при создании входного набора данных не было заданного начального числа.
источник
mutate(loop_number = as.numeric(L2))
перед сбросомL2
, и это отлично.reshape
метод из-за его компактного кода, хотяdplyr
может быть быстрее для больших наборов данных.reshape()
функцию, увидеть мое решение, которое, как мне кажется, представляет собой довольно чистую реализацию tidyr.С недавним обновлением
melt.data.table
мы теперь можем объединить несколько столбцов. С этим мы можем:Вы можете получить версию для разработки здесь .
источник
Это совсем не связано с tidyr и dplyr, но вот еще один вариант, который стоит рассмотреть:
merged.stack
из моего пакета splitstackshape, V1.4.0 и выше.источник
Если вы похожи на меня и не можете понять, как использовать «регулярное выражение с группами захвата» для
extract
, следующий код копируетextract(...)
строку из ответа Хэдли:Проблема здесь в том, что исходная сборка формирует ключевой столбец, который на самом деле представляет собой комбинацию двух ключей. Я решил использовать
mutate
в своем исходном решении в комментариях, чтобы разделить этот столбец на два столбца с эквивалентной информацией,loop_number
столбец иquestion_number
столбец.spread
затем можно использовать для преобразования данных длинной формы, которые представляют собой пары ключ-значение,(question_number, value)
в данные широкой формы.источник