I have a list of sf objects that I would like to row bind to create a single sf object. I'm looking for a function similar to data.table::rbindlist, that would stack the individual objects in an efficient manner.
my_list <- structure(list(structure(list(idhex = 4L, geometry = structure(list(
structure(c(664106.970004623, 6524137.38910266), class = c("XY",
"POINT", "sfg"))), class = c("sfc_POINT", "sfc"), precision = 0, bbox = structure(c(xmin = 664106.970004623,
ymin = 6524137.38910266, xmax = 664106.970004623, ymax = 6524137.38910266
), class = "bbox"), crs = structure(list(epsg = 32633L, proj4string = "+proj=utm +zone=33 +datum=WGS84 +units=m +no_defs"), class = "crs"), n_empty = 0L)), row.names = 1L, class = c("sf",
"data.frame"), sf_column = "geometry", agr = structure(c(idhex = NA_integer_), .Label = c("constant",
"aggregate", "identity"), class = "factor")), structure(list(
idhex = 9, geometry = structure(list(structure(c(665491.220375992,
6525002.7560692), class = c("XY", "POINT", "sfg"))), class = c("sfc_POINT",
"sfc"), precision = 0, bbox = structure(c(xmin = 665491.220375992,
ymin = 6525002.7560692, xmax = 665491.220375992, ymax = 6525002.7560692
), class = "bbox"), crs = structure(list(epsg = 32633L, proj4string = "+proj=utm +zone=33 +datum=WGS84 +units=m +no_defs"), class = "crs"), n_empty = 0L)), row.names = 1L, class = c("sf",
"data.frame"), sf_column = "geometry", agr = structure(c(idhex = NA_integer_), .Label = c("constant",
"aggregate", "identity"), class = "factor"))), .Dim = 1:2, .Dimnames = list(
".", NULL))
Note that data.table and sf libraries are not entirely compatible yet. So the rbindlist function returns an object that is not recognized as an `sf object.
single_sf <- rbindlist(my_list)
class(single_sf)
df <- do.call(rbind, my_list)
> class(df)
[1] "sf" "data.frame"
It is worth noting that dplyr::bind_rows and purrr::map_dfr does not work with sf objects, and thus rbind is better in this case.
This is an old question but it is worth to note that the recent version of dplyr (> 0.9) can bind rows of sf objects (in a list or not):
single_sf <- dplyr::bind_rows(my_list)
class(single_sf)
[1] "sf" "data.frame"
Other packages also provide options that can be used for binding sf objects (e.g.
mapedit:::combine_list_of_sf(), sf:::rbind.sf and data.table::rbindlist), besides the do.call() option mentioned above (see https://github.com/r-spatial/sf/issues/798# for a discussion and some benchmarking). But the dplyr option also works for sf objects with data frames containing different number of columns, somenthing that do.call(), sf:::rbind.sf(), and data.table::rbindlist() cannot do, and was important for me working with a list of sf objects with different number of columns.
I've found the fastest approach to do this is using data.table::rbindlist and then converting back to sf, as follows:
library(sf)
library(data.table)
# fast row bind
sf <- rbindlist(my_list)
# back to st
sf <- st_sf(sf)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With