2011-12-11 19 views
10

Tengo un conjunto de datos con varias columnas, una de las cuales es una columna para los tiempos de reacción. Estos tiempos de reacción se separan por comas para indicar los tiempos de reacción (del mismo participante) para los diferentes ensayos.Convertir entrada separada por comas en las columnas

Por ejemplo: fila 1 (es decir .: los datos de participante 1) tiene los siguientes en la columna "tiempos de reacción"

reaction_times 
2000,1450,1800,2200 

Por lo tanto estos son los tiempos de reacción de participante 1 para los ensayos 1,2,3,4.

Ahora quiero crear un nuevo conjunto de datos en el que los tiempos de reacción para estas pruebas formen columnas individuales. De esta forma puedo calcular el tiempo de reacción promedio para cada prueba .

   trial 1 trial 2 trial 3 trial 4 
participant 1: 2000  1450  1800  2200 

He probado el "colsplit" de la -package de "reshape2", pero eso no parece dividir mis datos en nuevas columnas (tal vez porque mis datos están todos en 1 célula).

¿Alguna sugerencia?

Respuesta

17

Creo que está buscando la función strsplit();

a = "2000,1450,1800,2200" 
strsplit(a, ",") 
[[1]]                                      
[1] "2000" "1450" "1800" "2200" 

Observe que strsplit devuelve una lista, en este caso con un solo elemento. Esto es porque strsplit toma vectores como entrada. Por lo tanto, también puede poner un vector largo de sus caracteres individuales en la función y obtener una lista dividida de ese vector. En un ejemplo más relevante este aspecto:

# Create some example data 
dat = data.frame(reaction_time = 
     apply(matrix(round(runif(100, 1, 2000)), 
        25, 4), 1, paste, collapse = ","), 
        stringsAsFactors=FALSE) 
splitdat = do.call("rbind", strsplit(dat$reaction_time, ",")) 
splitdat = data.frame(apply(splitdat, 2, as.numeric)) 
names(splitdat) = paste("trial", 1:4, sep = "") 
head(splitdat) 
    trial1 trial2 trial3 trial4 
1 597 1071 1430 997 
2 614 322 1242 1140 
3 1522 1679  51 1120 
4 225 1988 1938 1068 
5 621 623 1174  55 
6 1918 1828 136 1816 

y, por último, para calcular la media por persona:

apply(splitdat, 1, mean) 
[1] 1187.50 361.25 963.75 1017.00 916.25 1409.50 730.00 1310.75 1133.75 
[10] 851.25 914.75 881.25 889.00 1014.75 676.75 850.50 805.00 1460.00 
[19] 901.00 1443.50 507.25 691.50 1090.00 833.25 669.25 
+0

Guau, excelente y rápida respuesta Paul, dankjewel!Funciona como un encanto :) Si no me equivoco, también puede usar "colMeans" y "rowMeans" en lugar de "apply (splitdat, 1, mean)"? PS. lo siento, no puedo votarte, aparentemente necesito 15 reputación primero ?! – user1092247

+0

Tienes razón acerca de los colmes por supuesto :). Sin embargo, creo que usar apply también es bueno porque es mucho más flexible. ps ¿También eres de los Países Bajos? –

+0

Gracias! Sí, también soy de Nueva Zelanda :) – user1092247

8

Un ingenioso, si en lugar de mano dura, forma es utilizar read.csv en conjunción con textConnection. Suponiendo que los datos están en una trama de datos, df:

x <- read.csv(textConnection(df[["reaction times"]])) 
+2

No parece pesado para mí en absoluto. Parece que esgrimiendo R con un hábil toque. –

+0

¡Solución elegante! Sería interesante ver si nuestras soluciones se comparan en términos de velocidad para conjuntos de datos realmente grandes. –

+0

También funciona a la perfección (¿puedo aprobar ambos como soluciones?) – user1092247

6

vieja pregunta, pero me encontré con que a partir another recent question (que parece no estar relacionado).

Ambas respuestas existentes son apropiadas, pero quería compartir una respuesta relacionada con un paquete que he creado llamado "splitstackshape" que es rápido y tiene una sintaxis sencilla.

He aquí algunos datos de ejemplo:

Esta es la división:

library(splitstackshape) 
cSplit(dat, "reaction_time", ",") 
# reaction_time_1 reaction_time_2 reaction_time_3 reaction_time_4 
# 1:    532   1889   1374    761 
# 2:    745   1322    769   1555 
# 3:   1146   1259   1540   1869 
# 4:   1817    125    996    425 
# 5:    404    413   1436   1304 
# 6:   1797    354   1984    252 

y, opcionalmente, si es necesario tomar la rowMeans:

rowMeans(cSplit(dat, "reaction_time", ",")) 
# [1] 1139.00 1097.75 1453.50 840.75 889.25 1096.75 
+0

Excelente paquete - ¡gracias por compartir, lo hace mucho más sencillo! – user1092247

2

Otra opción usando dplyr y tidyr con los datos de ejemplo de Paul Hiemstra es:

# create example data 
data = data.frame(reaction_time = 
        apply(matrix(round(runif(100, 1, 2000)), 
            25, 4), 1, paste, collapse = ","), 
      stringsAsFactors=FALSE) 
head(data) 

# clean data 
data2 <- data %>% mutate(split_reaction_time = str_split(as.character(reaction_time), ",")) %>% unnest(split_reaction_time) 
data2$col_names <- c("trial1", "trial2", "trial3", "trial4") 
data2 <- data2 %>% spread(key = col_names, value = split_reaction_time) %>% select(-reaction_time) 
head(data2) 
Cuestiones relacionadas