Combine dos marcos de datos por filas (rbind) cuando tengan diferentes conjuntos de columnas

Resuelto Btibert3 asked hace 54 años • 15 respuestas

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

Btibert3 avatar Jan 01 '70 08:01 Btibert3
Aceptado

rbind.filldel paquete plyrpuede ser lo que estás buscando.

Jyotirmoy Bhattacharya avatar Aug 04 '2010 04:08 Jyotirmoy Bhattacharya

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
xiaodai avatar Jan 07 '2015 02:01 xiaodai

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.frameconvierte 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))
lmo avatar Oct 08 '2017 20:10 lmo