Tenho dados de uma pesquisa online em que os entrevistados fazem uma série de perguntas de 1 a 3 vezes. O software de pesquisa (Qualtrics) registra esses dados em várias colunas, ou seja, Q3.2 na pesquisa terá colunasQ3.2.1.
, Q3.2.2.
e 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
...
Quero combinar todas as colunas QN.N * em colunas QN.N individuais organizadas, no final das contas acabando com algo assim:
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
...
A tidyr
biblioteca tem a gather()
função, que funciona muito bem para combinar um conjunto de colunas:
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
O quadro de dados resultante tem 30 linhas, como esperado (10 indivíduos, 3 loops cada). No entanto, reunir um segundo conjunto de colunas não funciona corretamente - torna as duas colunas combinadas Q3.2
eQ3.3
, mas termina com 90 linhas em vez de 30 (todas as combinações de 10 indivíduos, 3 loops de Q3.2 e 3 loops de Q3 .3; as combinações aumentarão substancialmente para cada grupo de colunas nos dados reais):
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
Existe uma maneira de usar várias chamadas para gather()
assim, combinando pequenos subconjuntos de colunas como este, mantendo o número correto de linhas?
df %>% gather(loop_number, Q3.2, starts_with("Q3."))
seperate()
para dividir os valores Q3.3 (e além) em suas próprias colunas. Mas isso ainda parece uma solução realmente indireta ...spread
estou trabalhando em uma solução agora: 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()
. Embora várias chamadas pareçam inevitáveis de qualquer maneira, sejam váriosgenerate()
s que funcionam ouspread()
s ...Respostas:
Essa abordagem parece bastante natural para mim:
Primeiro reúna todas as colunas de perguntas, use
extract()
para separar emquestion
eloop_number
, em seguida,spread()
questione de volta nas colunas.fonte
Isso pode ser feito usando
reshape
. É possível comdplyr
embora.Ou usando
dplyr
Atualizar
Com
tidyr_0.8.3.9000
, podemos usarpivot_longer
para remodelar várias colunas. (Usando os nomes de coluna alteradosgsub
acima)NOTA: Os valores são diferentes porque não houve nenhuma semente definida na criação do conjunto de dados de entrada
fonte
mutate(loop_number = as.numeric(L2))
antes de cairL2
, e é perfeito.reshape
método para seu código compacto, emboradplyr
possa ser mais rápido para grandes conjuntos de dados.reshape()
função, veja minha solução para o que me parece uma implementação bem limpa.Com a atualização recente do
melt.data.table
, agora podemos derreter várias colunas. Com isso, podemos fazer:Você pode obter a versão de desenvolvimento aqui .
fonte
Não está relacionado com "tidyr" e "dplyr", mas aqui está outra opção a considerar:
merged.stack
do meu pacote "splitstackshape" , V1.4.0 e superior.fonte
Caso você seja como eu e não consiga descobrir como usar "expressão regular com grupos de captura"
extract
, o código a seguir replica aextract(...)
linha da resposta de Hadleys:O problema aqui é que a coleta inicial forma uma coluna-chave que, na verdade, é uma combinação de duas chaves. Optei por usar
mutate
na minha solução original nos comentários para dividir esta coluna em duas colunas com informações equivalentes, umaloop_number
coluna e umaquestion_number
coluna.spread
pode então ser usado para transformar os dados de formato longo, que são pares de valores-chave,(question_number, value)
em dados de formato amplo.fonte