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