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