Divida una columna de datos concatenados delimitados por comas y recodifique la salida como factores

Estoy tratando de limpiar algunos datos que han sido ingresados ​​incorrectamente. La pregunta para la variable permite respuestas múltiples de cinco opciones, numeradas del 1 al 5. Los datos se han ingresado de la siguiente manera (esto es solo un ejemplo: hay muchas más variables y muchas más observaciones en los datos reales) marco):

data V1 1 1, 2, 3 2 1, 2, 4 3 2, 3, 4, 5 4 1, 3, 4 5 1, 3, 5 6 2, 3, 4, 5 

Aquí hay un código para recrear los datos de ejemplo:

 data = data.frame(V1 = c("1, 2, 3", "1, 2, 4", "2, 3, 4, 5", "1, 3, 4", "1, 3, 5", "2, 3, 4, 5")) 

Lo que realmente necesito es que los datos se traten más … binarios, como un conjunto de preguntas “sí / no”, ingresadas en un dataframe que se parece más a:

 data V1.1 V1.2 V1.3 V1.4 V1.5 1 1 1 1 NA NA 2 1 1 NA 1 NA 3 NA 1 1 1 1 4 1 NA 1 1 NA 5 1 NA 1 NA 1 6 NA 1 1 1 1 

Los nombres de las variables reales no importan en este momento; puedo arreglarlo fácilmente. Además, no importa demasiado si los elementos que faltan son “O”, “NA” o en blanco, de nuevo, eso es algo que puedo solucionar más adelante.

He intentado usar la función de transform del paquete de reshape , así como alimentar cosas diferentes con strsplit , pero tampoco puedo hacer lo que estoy buscando. También he analizado muchas otras preguntas relacionadas con Stackoverflow, pero no parecen ser el mismo problema.

Solo necesita escribir una función y usar apply . Primero algunos datos ficticios:

 ##Make sure you're not using factors dd = data.frame(V1 = c("1, 2, 3", "1, 2, 4", "2, 3, 4, 5", "1, 3, 4", "1, 3, 5", "2, 3, 4, 5"), stringsAsFactors=FALSE) 

A continuación, crea una función que toma en una fila y se transforma según sea necesario

 make_row = function(i, ncol=5) { ##Could make the default NA if needed m = numeric(ncol) v = as.numeric(strsplit(i, ",")[[1]]) m[v] = 1 return(m) } 

Luego usa apply y transponer el resultado

 t(apply(dd, 1, make_row)) 

Mucho tiempo después, finalmente logré crear un paquete ( “splitstackshape” ) que trata este tipo de datos de manera eficiente. Por lo tanto, para la comodidad de los demás (y algo de autopromoción, por supuesto), aquí hay una solución compacta.

La función relevante para este problema es cSplit_e .

Primero, la configuración predeterminada, que conserva la columna original y usa NA como relleno:

 library(splitstackshape) cSplit_e(data, "V1") # V1 V1_1 V1_2 V1_3 V1_4 V1_5 # 1 1, 2, 3 1 1 1 NA NA # 2 1, 2, 4 1 1 NA 1 NA # 3 2, 3, 4, 5 NA 1 1 1 1 # 4 1, 3, 4 1 NA 1 1 NA # 5 1, 3, 5 1 NA 1 NA 1 # 6 2, 3, 4, 5 NA 1 1 1 1 

Segundo, con soltar la columna original y usar 0 como relleno.

 cSplit_e(data, "V1", drop = TRUE, fill = 0) # V1_1 V1_2 V1_3 V1_4 V1_5 # 1 1 1 1 0 0 # 2 1 1 0 1 0 # 3 0 1 1 1 1 # 4 1 0 1 1 0 # 5 1 0 1 0 1 # 6 0 1 1 1 1