vehículos vehiculos test services renovar mvcheckweb motores motor licencia gov gorenew florida flhsmv español departamento conducir r reshape dplyr qualtrics tidyr

vehiculos - services flhsmv gov mvcheckweb



Reúna múltiples conjuntos de columnas (5)

Con la actualización reciente de melt.data.table , ahora podemos derretir varias columnas. Con eso, podemos hacer:

require(data.table) ## 1.9.5 melt(setDT(df), id=1:2, measure=patterns("^Q3.2", "^Q3.3"), value.name=c("Q3.2", "Q3.3"), variable.name="loop_number") # id time loop_number Q3.2 Q3.3 # 1: 1 2009-01-01 1 -0.433978480 0.41227209 # 2: 2 2009-01-02 1 -0.567995351 0.30701144 # 3: 3 2009-01-03 1 -0.092041353 -0.96024077 # 4: 4 2009-01-04 1 1.137433487 0.60603396 # 5: 5 2009-01-05 1 -1.071498263 -0.01655584 # 6: 6 2009-01-06 1 -0.048376809 0.55889996 # 7: 7 2009-01-07 1 -0.007312176 0.69872938

Puede obtener la versión de desarrollo desde here .

Tengo datos de una encuesta en línea donde los encuestados pasan por un ciclo de preguntas 1-3 veces. El software de la encuesta (Qualtrics) registra estos datos en varias columnas, es decir, Q3.2 en la encuesta tendrá columnas Q3.2.1. , Q3.2.2. y 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 ...

Quiero combinar todas las columnas QN.N * en ordenadas columnas QN.N individuales, y finalmente terminar con algo como esto:

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 ...

La biblioteca tidyr tiene la función tidyr gather() , que funciona muy bien para combinar un conjunto de columnas:

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

El marco de datos resultante tiene 30 filas, como se esperaba (10 individuos, 3 bucles cada uno). Sin embargo, reunir un segundo conjunto de columnas no funciona correctamente: las dos columnas combinadas son Q3.2 y Q3.3 , pero termina con 90 filas en lugar de 30 (todas las combinaciones de 10 individuos, 3 bucles de Q3.2 y 3 bucles de Q3.3; las combinaciones aumentarán sustancialmente para cada grupo de columnas en los datos reales):

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

¿Hay alguna manera de usar varias llamadas para gather() esta manera, combinando pequeños subconjuntos de columnas como esta mientras se mantiene el número correcto de filas?


En caso de que sea como yo, y no pueda resolver cómo usar "expresión regular con grupos de captura" para el extract , el siguiente código replica la línea de extract(...) en la respuesta de Hadley:

df %>% gather(question_number, value, 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, value) %>% spread(key = question_number, value = value)

El problema aquí es que la recopilación inicial forma una columna de clave que en realidad es una combinación de dos claves. Elegí usar mutate en mi solución original en los comentarios para dividir esta columna en dos columnas con información equivalente, una columna loop_number y una columna question_number . spread se puede usar para transformar los datos de formato largo, que son pares de valores clave (question_number, value) en datos de formato ancho.


Este enfoque me parece bastante natural:

df %>% gather(key, value, -id, -time) %>% extract(key, c("question", "loop_number"), "(Q.//..)//.(.)") %>% spread(question, value)

Primero reúna todas las columnas de preguntas, use extract() para separarlas en question y loop_number , luego spread() pregunta nuevamente en las columnas.

#> id time loop_number Q3.2 Q3.3 #> 1 1 2009-01-01 1 0.142259203 -0.35842736 #> 2 1 2009-01-01 2 0.061034802 0.79354061 #> 3 1 2009-01-01 3 -0.525686204 -0.67456611 #> 4 2 2009-01-02 1 -1.044461185 -1.19662936 #> 5 2 2009-01-02 2 0.393808163 0.42384717


Esto podría hacerse usando reshape . dplyr embargo, es posible con dplyr .

colnames(df) <- gsub("//.(.{2})$", "_//1", colnames(df)) colnames(df)[2] <- "Date" res <- reshape(df, idvar=c("id", "Date"), varying=3:8, direction="long", sep="_") row.names(res) <- 1:nrow(res) head(res) # id Date time Q3.2 Q3.3 #1 1 2009-01-01 1 1.3709584 0.4554501 #2 2 2009-01-02 1 -0.5646982 0.7048373 #3 3 2009-01-03 1 0.3631284 1.0351035 #4 4 2009-01-04 1 0.6328626 -0.6089264 #5 5 2009-01-05 1 0.4042683 0.5049551 #6 6 2009-01-06 1 -0.1061245 -1.7170087

O usando dplyr

library(tidyr) library(dplyr) colnames(df) <- gsub("//.(.{2})$", "_//1", colnames(df)) df %>% gather(loop_number, "Q3", starts_with("Q3")) %>% separate(loop_number,c("L1", "L2"), sep="_") %>% spread(L1, Q3) %>% select(-L2) %>% head() # id time Q3.2 Q3.3 #1 1 2009-01-01 1.3709584 0.4554501 #2 1 2009-01-01 1.3048697 0.2059986 #3 1 2009-01-01 -0.3066386 0.3219253 #4 2 2009-01-02 -0.5646982 0.7048373 #5 2 2009-01-02 2.2866454 -0.3610573 #6 2 2009-01-02 -1.7813084 -0.7838389

Actualizar

Con tidyr_0.8.3.9000 , podemos usar pivot_longer para remodelar múltiples columnas. (Usando los nombres de columna modificados de gsub arriba)

library(dplyr) library(tidyr) df %>% pivot_longer(cols = starts_with("Q3"), names_to = c(".value", "Q3"), names_sep = "_") %>% select(-Q3) # A tibble: 30 x 4 # id time Q3.2 Q3.3 # <int> <date> <dbl> <dbl> # 1 1 2009-01-01 0.974 1.47 # 2 1 2009-01-01 -0.849 -0.513 # 3 1 2009-01-01 0.894 0.0442 # 4 2 2009-01-02 2.04 -0.553 # 5 2 2009-01-02 0.694 0.0972 # 6 2 2009-01-02 -1.11 1.85 # 7 3 2009-01-03 0.413 0.733 # 8 3 2009-01-03 -0.896 -0.271 #9 3 2009-01-03 0.509 -0.0512 #10 4 2009-01-04 1.81 0.668 # … with 20 more rows

NOTA: Los valores son diferentes porque no se estableció una semilla en la creación del conjunto de datos de entrada


No está relacionado en absoluto con "tidyr" y "dplyr", pero aquí hay otra opción a tener en cuenta: merged.stack de mi paquete "splitstackshape" , V1.4.0 y superior.

library(splitstackshape) merged.stack(df, id.vars = c("id", "time"), var.stubs = c("Q3.2.", "Q3.3."), sep = "var.stubs") # id time .time_1 Q3.2. Q3.3. # 1: 1 2009-01-01 1. -0.62645381 1.35867955 # 2: 1 2009-01-01 2. 1.51178117 -0.16452360 # 3: 1 2009-01-01 3. 0.91897737 0.39810588 # 4: 2 2009-01-02 1. 0.18364332 -0.10278773 # 5: 2 2009-01-02 2. 0.38984324 -0.25336168 # 6: 2 2009-01-02 3. 0.78213630 -0.61202639 # 7: 3 2009-01-03 1. -0.83562861 0.38767161 # <<:::SNIP:::>> # 24: 8 2009-01-08 3. -1.47075238 -1.04413463 # 25: 9 2009-01-09 1. 0.57578135 1.10002537 # 26: 9 2009-01-09 2. 0.82122120 -0.11234621 # 27: 9 2009-01-09 3. -0.47815006 0.56971963 # 28: 10 2009-01-10 1. -0.30538839 0.76317575 # 29: 10 2009-01-10 2. 0.59390132 0.88110773 # 30: 10 2009-01-10 3. 0.41794156 -0.13505460 # id time .time_1 Q3.2. Q3.3.