Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert data frame containing coordinates of polygons to sf

I am a beginner with sf package and I am having some difficulties converting my data frame into a sf object.

I have a data frame containing coordinates of polygons in each row. These coordinates are in a single column.

Here is an example of the structure of my data frame :

dat <- tibble::tribble(
    ~code,    ~geometry,
    "MIE",    list(c(1.24, 45), c(1.25, 45), c(1.25, 46), c(1.24, 45)),
    "MIS",    list(c(1.23, 44), c(1.23, 45), c(1.24, 45), c(1.23, 44))
    )

I want to make a sf object from this data frame but R can't recognize the geometry column.

I tried list formats and functions like st_sf(), st_geometry(), st_polygon() but without success.

Trying st_sf(dat) returns:

Error in st_sf(dat) :

Error in st_sf(dat) : no simple features geometry column present

Trying st_polygon(dat$geometry) returns :

Error in vapply(x, ncol, 0L) : values must be length 1,
  but FUN(X[[1]]) result is length 0

Is there any way to convert my data frame into a sf object ?

I'm working with R version 3.6.0.

like image 719
ldavadan Avatar asked Oct 21 '25 15:10

ldavadan


1 Answers

I always struggle with doing this sf transformation too, because it's not straight forward.

The first step (and hard part) is to build a st_object (here st_polygon) for each individual geometry represented.

To do that, convert each existing list into a matrix. Once each polygon representation is a n-row matrix (one row for each point) we convert the matrix to a one element list to feed into st_polygon(). Now dat$geometry is a list appropriately classed of POLYGONS.

library(tidyverse)

dat %>%
  mutate(geometry = map(geometry,
                        ~ do.call(rbind, .) %>% # make each list a matrix
                          list() %>% # st_polygon() requires a list
                          st_polygon()
                    )
         ) %>% 
  st_as_sf()

Then the final step is to call st_as_sf() on the entire data frame. It will auto-detect the now properly formatted geometry column and produce a nice new sf object for you. Happy mapping!

EDIT: If you want to build polygons with holes, the process is similar. st_polygon() will process a multi-element list as if the the first element is the polygon and the remaining elements are holes in the first. It does require that you use map twice, because you still need to build a matrix out of each list element, but need keep the lists of grouped matrixs together for processing the holes.

dat2 <- tibble::tribble( ~code, ~geometry, "MIE", list(list(c(1.24, 45), c(1.25, 45), c(1.25, 46), c(1.24, 45)), list(c(1.245,45.5), c(1.246,45.7), c(1.245,45.5))) )

 dat %>%
  mutate(geometry = map(dat$geometry,
                        ~ map(.,
                          ~ do.call(rbind, .) # make each list a matrix
                          ) %>% 
                        st_polygon()
                        )
  ) %>% 
  st_as_sf()
like image 186
Nate Avatar answered Oct 23 '25 05:10

Nate



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!