knitr::opts_chunk$set( collapse = TRUE, comment = "# ", echo = TRUE, eval = TRUE )
library(sfheaders) # library(sf) ## for nice printing (disabled on github actinos!)
The hierarchy of sf
objects goes
The sfg_
group of functions assume the input is a single geometry.
sfg_point( 1:2 ) sfg_point( 1:3 ) sfg_point( 1:4 ) sfg_linestring( 1:4 ) df <- data.frame( x = c(1,1,4,4,1) , y = c(1,4,4,1,1) ) sfg_linestring(df) sfg_polygon(df)
The sfc_
group of functions let you specify an 'id' value to identify individual geometries. (Except for sfc_point()
, in this case every row is an individual geometry).
df <- data.frame( id = c(1,1,2,2,3) , x = c(1,1,4,4,1) , y = c(1,4,4,1,1) ) sfc_point( df ) sfc_multipoint( df, multipoint_id = "id" ) sfc_linestring( df, linestring_id = "id" ) ## leaving the 'id' field blank sfc_polygon( df )
The sf_
functions also let you specify an 'id' value, but in this case the id is retained and kept on the object
df <- data.frame( id = c(1,1,2,2,3) , x = c(1,1,4,4,1) , y = c(1,4,4,1,1) ) sf_point( df ) sf_multipoint( df, multipoint_id = "id" ) sf_linestring( df, linestring_id = "id" ) ## leaving the 'id' field blank sf_polygon( df )
In all these examples I haven't needed to specify the geometry columns, because other than the id
field, all the other columns are used for the coordinates.
If your data.frame has other, non-geometry and non-id columns, you must specify at least the x
and y
paramters
df <- data.frame( id = c(1,1,2,2,3) , x = c(1,1,4,4,1) , y = c(1,4,4,1,1) ) df$val <- letters[ df$id ] sf_point( df, x = "x", y = "y" ) sf_linestring( df, x = "x", y = "y", linestring_id = "id" )
If you want to keep all the other columns, set keep = TRUE
sf_linestring( df, x = "x", y = "y", linestring_id = "id", keep = TRUE )
As of version 1.0 you can now convert from sfg
, sfc
and sf
objects to data.frames
df <- data.frame( id = c(1,1,2,2,3) , x = c(1,1,4,4,1) , y = c(1,4,4,1,1) ) df$val <- letters[ df$id ] sf <- sf_linestring( df, x = "x", y = "y", linestring_id = "id", keep = TRUE ) sf_to_df( sf )
And if you want to keep all the other columns and fill them down each row of the data.frame, set fill = TRUE
sf_to_df( sf, fill = TRUE )
Here's a quick benchmark showing how well this library performs
n <- 1e5 df <- data.frame( id = rep(1:(n/5), each = 5) , x = rnorm(n) , y = rnorm(n) ) library(data.table) library(microbenchmark) dt <- as.data.table( df ) microbenchmark( dt = { sf <- dt[ , { geometry <- sf::st_linestring( x = matrix( c( x, y ), ncol = 2, byrow = T )) geometry <- sf::st_sf( geometry = sf::st_sfc( geometry ) ) } , by = id ] sf <- sf::st_as_sf( sf ) }, sfheaders = { sfh <- sfheaders::sf_linestring( obj = df , linestring_id = "id" ) }, times = 5 ) # Unit: milliseconds # expr min lq mean median uq max neval # dt 6599.67479 6654.12357 6779.23543 6750.19807 6833.46262 7058.71809 5 # sfheaders 21.07775 21.30438 23.20592 23.21665 25.06429 25.36654 5
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.