Combine dos marcos de datos por filas (rbind) cuando tengan diferentes conjuntos de columnas
¿Es posible enlazar por filas dos marcos de datos que no tienen el mismo conjunto de columnas? Espero conservar las columnas que no coinciden después del enlace.
rbind.fill
del paquete plyr
puede ser lo que estás buscando.
Una solución más reciente es utilizar la función dplyr
's bind_rows
, que supongo que es más eficiente que smartbind
.
df1 <- data.frame(a = c(1:5), b = c(6:10))
df2 <- data.frame(a = c(11:15), b = c(16:20), c = LETTERS[1:5])
dplyr::bind_rows(df1, df2)
a b c
1 1 6 <NA>
2 2 7 <NA>
3 3 8 <NA>
4 4 9 <NA>
5 5 10 <NA>
6 11 16 A
7 12 17 B
8 13 18 C
9 14 19 D
10 15 20 E
La mayoría de las respuestas básicas de R abordan la situación en la que solo un marco de datos tiene columnas adicionales o que el marco de datos resultante tendría la intersección de las columnas. Dado que el OP escribe Espero conservar las columnas que no coinciden después del enlace , probablemente valga la pena publicar una respuesta que utilice métodos base R para abordar este problema.
A continuación, presento dos métodos básicos de R: uno que altera los marcos de datos originales y otro que no. Además, ofrezco un método que generaliza el método no destructivo a más de dos marcos de datos.
Primero, obtengamos algunos datos de muestra.
# sample data, variable c is in df1, variable d is in df2
df1 = data.frame(a=1:5, b=6:10, d=month.name[1:5])
df2 = data.frame(a=6:10, b=16:20, c = letters[8:12])
Dos marcos de datos, modifique los originales
Para conservar todas las columnas de ambos marcos de datos en un rbind
(y permitir que la función funcione sin generar un error), agregue columnas NA a cada marco de datos con los nombres faltantes apropiados completados usando setdiff
.
# fill in non-overlapping columns with NAs
df1[setdiff(names(df2), names(df1))] <- NA
df2[setdiff(names(df1), names(df2))] <- NA
Ahora, rbind
-em
rbind(df1, df2)
a b d c
1 1 6 January <NA>
2 2 7 February <NA>
3 3 8 March <NA>
4 4 9 April <NA>
5 5 10 May <NA>
6 6 16 <NA> h
7 7 17 <NA> i
8 8 18 <NA> j
9 9 19 <NA> k
10 10 20 <NA> l
Tenga en cuenta que las dos primeras líneas alteran los data.frames originales, df1 y df2, agregando el conjunto completo de columnas a ambos.
Dos marcos.de.datos, no modifique los originales.
Para dejar intactos los marcos.datos originales, primero recorra los nombres que difieren y devuelva un vector con nombre de NA que están concatenados en una lista con el marco.datos usando c
. Luego, data.frame
convierte el resultado en un data.frame apropiado para el archivo rbind
.
rbind(
data.frame(c(df1, sapply(setdiff(names(df2), names(df1)), function(x) NA))),
data.frame(c(df2, sapply(setdiff(names(df1), names(df2)), function(x) NA)))
)
Muchos marcos de datos, no modifique los originales.
En el caso de que tenga más de dos marcos de datos, puede hacer lo siguiente.
# put data.frames into list (dfs named df1, df2, df3, etc)
mydflist <- mget(ls(pattern="df\\d+"))
# get all variable names
allNms <- unique(unlist(lapply(mydflist, names)))
# put em all together
do.call(rbind,
lapply(mydflist,
function(x) data.frame(c(x, sapply(setdiff(allNms, names(x)),
function(y) NA)))))
¿Quizás sea un poco mejor no ver los nombres de las filas de los marcos de datos originales? Entonces haz esto.
do.call(rbind,
c(lapply(mydflist,
function(x) data.frame(c(x, sapply(setdiff(allNms, names(x)),
function(y) NA)))),
make.row.names=FALSE))