Saltar al contenido

Diferencia entre rbind () y bind_rows () en R

Si encuentras algo que no comprendes puedes dejarlo en los comentarios y te ayudaremos lo mas rápido que podamos.

Solución:

Aparte de algunas diferencias más, una de las principales razones para usar bind_rows sobre rbind consiste en combinar dos marcos de datos con diferente número de columnas. rbind arroja un error en tal caso mientras que bind_rows asigna “NA“a aquellas filas de columnas que faltan en uno de los marcos de datos donde el valor no es proporcionado por los marcos de datos.

Pruebe el siguiente código para ver la diferencia:

a <- data.frame(a = 1:2, b = 3:4, c = 5:6)
b <- data.frame(a = 7:8, b = 2:3, c = 3:4, d = 8:9)

Los resultados de las dos convocatorias son los siguientes:

rbind(a, b)
> rbind(a, b)
Error in rbind(deparse.level, ...) : 
  numbers of columns of arguments do not match
library(dplyr)
bind_rows(a, b)
> bind_rows(a, b)
  a b c  d
1 1 3 5 NA
2 2 4 6 NA
3 7 2 3  8
4 8 3 4  9

Dado que ninguna de las respuestas aquí ofrece una revisión sistemática de las diferencias entre base::rbind y dplyr::bind_rows, y la respuesta de @bob con respecto al rendimiento es incorrecta, decidí agregar lo siguiente.

Tengamos un marco de datos de prueba:

df_1 = data.frame(
  v1_dbl = 1:1000,
  v2_lst = I(as.list(1:1000)),
  v3_fct = factor(sample(letters[1:10], 1000, replace = TRUE)),
  v4_raw = raw(1000),
  v5_dtm = as.POSIXct(paste0("2019-12-0", sample(1:9, 1000, replace = TRUE)))
)

df_1$v2_lst = unclass(df_1$v2_lst) #remove the AsIs class introduced by `I()`

1. base::rbind maneja las entradas de la lista de manera diferente

rbind(list(df_1, df_1))
     [,1]   [,2]  
[1,] List,5 List,5

# You have to combine it with `do.call()` to achieve the same result:
head(do.call(rbind, list(df_1, df_1)), 3)
  v1_dbl v2_lst v3_fct v4_raw     v5_dtm
1      1      1      b     00 2019-12-02
2      2      2      h     00 2019-12-08
3      3      3      c     00 2019-12-09

head(dplyr::bind_rows(list(df_1, df_1)), 3)
  v1_dbl v2_lst v3_fct v4_raw     v5_dtm
1      1      1      b     00 2019-12-02
2      2      2      h     00 2019-12-08
3      3      3      c     00 2019-12-09

2. base::rbind puede hacer frente a (algunos) mixed tipos

Mientras tanto base::rbind y dplyr::bind_rows fallar al intentar enlazar, por ejemplo. columna sin formato o de fecha y hora a una columna de algún otro tipo, base::rbind puede hacer frente a cierto grado de discrepancia.

La combinación de una lista y una columna que no es una lista produce una columna de lista. La combinación de un factor y algo más produce una advertencia pero no un error:

df_2 = data.frame(
  v1_dbl = 1,
  v2_lst = 1,
  v3_fct = 1,
  v4_raw = raw(1),
  v5_dtm = as.POSIXct("2019-12-01")
)

head(rbind(df_1, df_2), 3)
  v1_dbl v2_lst v3_fct v4_raw     v5_dtm
1      1      1      b     00 2019-12-02
2      2      2      h     00 2019-12-08
3      3      3      c     00 2019-12-09
Warning message:
In `[<-.factor`(`*tmp*`, ri, value = 1) : invalid factor level, NA generated

# Fails on the lst, num combination:
head(dplyr::bind_rows(df_1, df_2), 3)
Error: Column `v2_lst` can't be converted from list to numeric

# Fails on the fct, num combination:
head(dplyr::bind_rows(df_1[-2], df_2), 3)
Error: Column `v3_fct` can't be converted from factor to numeric

3. base::rbind mantiene los nombres de fila

Tidyverse aboga por convertir los nombres de fila en una columna dedicada, por lo que sus funciones los eliminan.

rbind(mtcars[1:2, 1:4], mtcars[3:4, 1:4])
                mpg cyl disp  hp
Mazda RX4      21.0   6  160 110
Mazda RX4 Wag  21.0   6  160 110
Datsun 710     22.8   4  108  93
Hornet 4 Drive 21.4   6  258 110

dplyr::bind_rows(mtcars[1:2, 1:4], mtcars[3:4, 1:4])
   mpg cyl disp  hp
1 21.0   6  160 110
2 21.0   6  160 110
3 22.8   4  108  93
4 21.4   6  258 110

4. base::rbind no puedo hacer frente a las columnas que faltan

Solo para completar, ya que Abhilash Kandwal ya lo dijo en su respuesta.

5. base::rbind maneja los argumentos nombrados de manera diferente

Tiempo base::rbind antepone los nombres de los argumentos a los nombres de las filas, dplyr::bind_rows tiene la opción de agregar una columna de identificación dedicada:

rbind(hi = mtcars[1:2, 1:4], bye = mtcars[3:4, 1:4])
                    mpg cyl disp  hp
hi.Mazda RX4       21.0   6  160 110
hi.Mazda RX4 Wag   21.0   6  160 110
bye.Datsun 710     22.8   4  108  93
bye.Hornet 4 Drive 21.4   6  258 110

dplyr::bind_rows(hi = mtcars[1:2, 1:4], bye = mtcars[3:4, 1:4], .id = "my_id")
  my_id  mpg cyl disp  hp
1    hi 21.0   6  160 110
2    hi 21.0   6  160 110
3   bye 22.8   4  108  93
4   bye 21.4   6  258 110

6. base::rbind convierte argumentos vectoriales en filas (y los recicla)

A diferencia de, dplyr::bind_rows agrega columnas (y por lo tanto requiere que se nombren los elementos de x):

rbind(mtcars[1:2, 1:4], x = 1:2))
              mpg cyl disp  hp
Mazda RX4      21   6  160 110
Mazda RX4 Wag  21   6  160 110
x               1   2    1   2

dplyr::bind_rows(mtcars[1:2, 1:4], x = c(a = 1, b = 2))
  mpg cyl disp  hp  a  b
1  21   6  160 110 NA NA
2  21   6  160 110 NA NA
3  NA  NA   NA  NA  1  2

7. base::rbind es más lento y requiere más RAM

Para enlazar cien marcos de datos de tamaño mediano (1k filas), base::rbind requiere cincuenta veces más RAM y es más de 15 veces más lento:

dfs = rep(list(df_1), 100)
bench::mark(
  "base::rbind" = do.call(rbind, dfs),
  "dplyr::bind_rows" = dplyr::bind_rows(dfs)
)[, 1:5]

# A tibble: 2 x 5
  expression            min   median `itr/sec` mem_alloc
                
1 base::rbind       47.23ms  48.05ms      20.0  104.48MB
2 dplyr::bind_rows   3.69ms   3.75ms     261.     2.39MB

Como necesitaba unir muchos marcos de datos pequeños, aquí también hay un punto de referencia para eso. Tanto la velocidad como la diferencia de RAM son bastante llamativas:

dfs = rep(list(df_1[1:2, ]), 10^4)
bench::mark(
  "base::rbind" = do.call(rbind, dfs),
  "dplyr::bind_rows" = dplyr::bind_rows(dfs)
)[, 1:5]

# A tibble: 2 x 5
  expression            min   median `itr/sec` mem_alloc
                
1 base::rbind         1.65s    1.65s     0.605    1.56GB
2 dplyr::bind_rows  19.31ms  20.21ms    43.7    566.69KB

Finalmente, help("rbind") y help("bind_rows") también son interesantes de leer.

Comentarios y calificaciones del post

Ten en cuenta mostrar este artículo si te ayudó.

¡Haz clic para puntuar esta entrada!
(Votos: 2 Promedio: 4.5)


Tags : / /

Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *