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