Search code examples
rgeospatialspatialr-sf

Converting list of dataframes into a sf object in R


I am trying to convert a list of sfc dataframes into a single sf object with geometry per row.

This is the list of sfc dataframes

Somehow I managed to convert it to a sf dataframe but I have a weird sf object. In the environment panel, it says there is two columns but when I open the variable, it has three columns: geometry and geometry.1.

This is my R code.

# list of dataframes into an 'sf' dataframe
polygons <- list()

for (i in 1:length(reachable_nodes_for_pois_list)) {
  polygon <- reachable_nodes_for_pois_list[[i]][[1]]
  polygons[[i]] <- polygon
}


iso_polygons <- sf::st_sfc(do.call(rbind, polygons))


sf_df <- sf::st_sf(geometry = iso_polygons)

amenity_isochrone <- cbind(iso_points$nodeID, sf_df)
st_crs(amenity_isochrone) <- 27700 

This is the sf object with duplicated geometry

Could anyone help? Thank you!


Solution

  • Try do.call(rbind, reachable_nodes_for_pois_list) or dplyr::bind_rows(reachable_nodes_for_pois_list)

    That input structure is somewhat peculiar, took a few tries to construct something similar:

    library(dplyr)
    library(sf)
    reachable_nodes_for_pois_list <- st_read(system.file("shape/nc.shp", package="sf"), 
                                             quiet = TRUE) %>% 
      st_cast("POLYGON") %>% 
      select(polygons = geometry) %>% 
      slice_head(n = 8) %>% 
      split(1:8) %>% 
      unname()
    
    str(reachable_nodes_for_pois_list[1])
    #> List of 1
    #>  $ :Classes 'sf' and 'data.frame':   1 obs. of  1 variable:
    #>   ..$ polygons:sfc_POLYGON of length 1; first list element: List of 1
    #>   .. ..$ : num [1:27, 1:2] -81.5 -81.5 -81.6 -81.6 -81.7 ...
    #>   .. ..- attr(*, "class")= chr [1:3] "XY" "POLYGON" "sfg"
    #>   ..- attr(*, "sf_column")= chr "polygons"
    #>   ..- attr(*, "agr")= Factor w/ 3 levels "constant","aggregate",..: 
    #>   .. ..- attr(*, "names")= chr(0)
    

    reachable_nodes_for_pois_list in Viewer

    Though bind_rows() / do.call(rbind, ...) will handle it just fine:

    bind_rows(reachable_nodes_for_pois_list)
    #> Simple feature collection with 8 features and 0 fields
    #> Geometry type: POLYGON
    #> Dimension:     XY
    #> Bounding box:  xmin: -81.74107 ymin: 36.07282 xmax: -75.77316 ymax: 36.58965
    #> Geodetic CRS:  NAD27
    #>                         polygons
    #> 1 POLYGON ((-81.47276 36.2343...
    #> 2 POLYGON ((-81.23989 36.3653...
    #> 3 POLYGON ((-80.45634 36.2425...
    #> 4 POLYGON ((-76.00897 36.3196...
    #> 5 POLYGON ((-76.02717 36.5567...
    #> 6 POLYGON ((-75.90199 36.5562...
    #> 7 POLYGON ((-77.21767 36.2409...
    #> 8 POLYGON ((-76.74506 36.2339...
    

    Created on 2023-07-07 with reprex v2.0.2