将一系列的sf对象转换为一个sf对象

20

我有一个sf对象列表,我想行绑定它们以创建一个单独的sf对象。我正在寻找类似于data.table :: rbindlist 的函数,可以高效地堆叠各个对象。

可再现示例的数据:

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))

请注意,data.tablesf库目前还不完全兼容。因此,rbindlist函数返回的对象无法被识别为一个`sf对象。

single_sf <- rbindlist(my_list)
class(single_sf)

3
如果 CRS 相等,你可以轻松地将其转换为 sf 对象:sf::st_as_sf(data.table::rbindlist(my_list)) - TimSalabim
1
为了完整性,@timelyportfolio 还编写了 mapedit:::combine_list_of_sf 来实现此功能。值得注意的是,https://github.com/r-spatial/mapedit/issues/46 也值得关注,因为在某个阶段,sf 可能会实现专用的 bind_rows_sf - TimSalabim
3个回答

23
df <- do.call(rbind, my_list)

> class(df)
[1] "sf"         "data.frame"

值得注意的是,dplyr::bind_rowspurrr::map_dfr不能用于sf对象,因此在这种情况下使用rbind更好。


6
需要注意的是列表元素的CRS需要匹配... - TimSalabim

10

这是一个老问题,但值得注意的是,最新版本的dplyr(> 0.9)可以绑定sf对象的行(无论是在列表中还是不在列表中):

single_sf <- dplyr::bind_rows(my_list)
class(single_sf)
[1] "sf"         "data.frame"

其他软件包也提供可以用于绑定 sf 对象的选项(例如 mapedit:::combine_list_of_sf()sf:::rbind.sfdata.table::rbindlist),除了上面提到的 do.call() 选项(请参见 https://github.com/r-spatial/sf/issues/798# 进行讨论和一些基准测试)。但是,dplyr 选项也适用于包含不同列数数据框的 sf 对象,而这是 do.call()sf:::rbind.sf()data.table::rbindlist() 无法做到的,并且对我处理包含不同列数的 sf 对象列表非常重要。


2

我发现最快的方法是使用data.table::rbindlist,然后将其转换回sf,具体如下:

library(sf)
library(data.table)

# fast row bind
sf <- rbindlist(my_list)

# back to st
sf <- st_sf(sf)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接