Tengo un marco de datos, así:
data.frame(director = c("Aaron Blaise,Bob Walker", "Akira Kurosawa",
"Alan J. Pakula", "Alan Parker", "Alejandro Amenabar", "Alejandro Gonzalez Inarritu",
"Alejandro Gonzalez Inarritu,Benicio Del Toro", "Alejandro González Iñárritu",
"Alex Proyas", "Alexander Hall", "Alfonso Cuaron", "Alfred Hitchcock",
"Anatole Litvak", "Andrew Adamson,Marilyn Fox", "Andrew Dominik",
"Andrew Stanton", "Andrew Stanton,Lee Unkrich", "Angelina Jolie,John Stevenson",
"Anne Fontaine", "Anthony Harvey"), AB = c('A', 'B', 'A', 'A', 'B', 'B', 'B', 'A', 'B', 'A', 'B', 'A', 'A', 'B', 'B', 'B', 'B', 'B', 'B', 'A'))
Como puede ver, algunas entradas en la directorcolumna son varios nombres separados por comas. Me gustaría dividir estas entradas en filas separadas mientras mantengo los valores de la otra columna. Como ejemplo, la primera fila en el marco de datos anterior debe dividirse en dos filas, con un solo nombre en la directorcolumna y una 'A' en la ABcolumna.

Respuestas:
Esta vieja pregunta se utiliza con frecuencia como objetivo engañoso (etiquetado con
r-faq). Hasta el día de hoy, se ha respondido tres veces ofreciendo 6 enfoques diferentes, pero carece de un punto de referencia como guía sobre cuál de los enfoques es el más rápido 1 .Las soluciones comparadas incluyen
data.tablemétodos y dosdplyr/tidyrenfoques,splitstackshapesolución de Ananda ,data.tablemétodos de Jaap .En general, se compararon 8 métodos diferentes en 6 tamaños diferentes de marcos de datos utilizando el
microbenchmarkpaquete (consulte el código a continuación).Los datos de muestra proporcionados por el OP constan solo de 20 filas. Para crear marcos de datos más grandes, estas 20 filas simplemente se repiten 1, 10, 100, 1000, 10000 y 100000 veces, lo que genera problemas de hasta 2 millones de filas.
Resultados comparativos
Los resultados de la evaluación comparativa muestran que para marcos de datos suficientemente grandes, todos los
data.tablemétodos son más rápidos que cualquier otro método. Para marcos de datos con más de aproximadamente 5000 filas, eldata.tablemétodo 2 de Jaap y la varianteDT3son los más rápidos, magnitudes más rápidas que los métodos más lentos.Sorprendentemente, los tiempos de los dos
tidyversemétodos y lasplistackshapesolución son tan similares que es difícil distinguir las curvas en el gráfico. Son los métodos comparativos más lentos de todos los tamaños de marcos de datos.Para marcos de datos más pequeños, la solución R base de Matt y
data.tablemétodo 4 parecen tener menos gastos generales que los otros métodos.Código
Definir función para ejecuciones de referencia de tamaño de problema
nEjecute un banco de pruebas para diferentes tamaños de problemas
Preparar datos para graficar
Crear gráfico
Información de la sesión y versiones del paquete (extracto)
1 Este comentario exuberante despertó mi curiosidad . ¡Brillante! Órdenes de magnitud más rápido! a una respuesta de una pregunta que se cerró como un duplicado de esta pregunta.
tidyversefuente
data.table,dplyr, etc.strsplitfixed=TRUE. Como el otro lo tiene y esto tendrá un impacto en los tiempos. Desde R 4.0.0 , el valor predeterminado, al crear undata.frame, esstringsAsFactors = FALSE, por lo queas.characterpodría eliminarse.Varias alternativas:
1) dos formas con tabla de datos:
2) una dplyr / tidyr combinación:
3) con tidyrsolo: Con
tidyr 0.5.0(y posterior), también puede usarseparate_rows:Puede utilizar el
convert = TRUEparámetro para convertir automáticamente números en columnas numéricas.4) con base R:
fuente
data.table(id= "X21", a = "chr1;chr1;chr1", b="123;133;134",c="234;254;268")convirtiéndosedata.table(id = c("X21","X21",X21"), a=c("chr1","chr1","chr1"), b=c("123","133","134"), c=c("234","254","268"))?setDT(dt)[,lapply(.SD, function(x) unlist(tstrsplit(x, ";",fixed=TRUE))), by = ID]es lo que funcionó para mí.Nombrando su data.frame original
v, tenemos esto:Tenga en cuenta el uso de
reppara construir la nueva columna AB. Aquí,sapplydevuelve el número de nombres en cada una de las filas originales.fuente
vapply. ¿Hay algo que lo hagavapplymás apropiado aquí?sapply(s, length)podría reemplazarse porlengths(s).Tarde para la fiesta, pero otra alternativa generalizada es usar
cSplitmi paquete "splitstackshape" que tiene undirectionargumento. Establezca esto en"long"para obtener el resultado que especifique:fuente
fuente
Actualmente, se podría recomendar otro Benchmark resultante del uso
strsplitde base para dividir cadenas separadas por comas en una columna en filas separadas , ya que era la más rápida en una amplia gama de tamaños:Tenga en cuenta que el uso
fixed=TRUEtiene un impacto significativo en los tiempos.Métodos comparados:
Bibliotecas:
Datos:
Resultados de cálculo y cronometraje:
Nota, métodos como
devolver un
strsplitparauniquedirector y podría ser comparable conpero a mi entender, esto no se preguntó.
fuente