GeoJSON to Simple Feature Converter.
geojsonsf
–
geojsonsf
A simple, low-dependency and fast converter between GeoJSON and Simple Feature objects in R.
v1.3.2
Converts
- GeoJSON –>
sf
- GeoJSON –>
sfc
sf
–> GeoJSONsfc
–> GeoJSON- GeoJSON –> Well-known text
- data.frame –> GeoJSON (POINT only)
As per GeoJSON (RFC 7946 specification), foreign members are ignored, and nested objects and arrays inside the properties
object are converted to string/characters.
Also, as per the specification, CRS
The coordinate reference system for all GeoJSON coordinates is a geographic coordinate reference system, using the World Geodetic System 1984 (WGS 84) [WGS84] datum, with longitude and latitude units of decimal degrees. This is equivalent to the coordinate reference system identified by the Open Geospatial Consortium (OGC) URN <urn:ogc:def:crs:OGC>::CRS84
From v1.3.2, if your coordinates are in a different CRS you can specify the CRS & proj4string values in the geojson_sf()
and geojson_sfc()
functions.
Installation
Install the CRAN version with
install.packages("geojsonsf")
To install the development version
# install.packages("devtools")
devtools::install_github("SymbolixAU/geojsonsf")
Why did you build it?
To quickly parse between GeoJSON and sf
objects, and to handle cases not supported by sf
, e.g. arrays of geometries
What do you mean, ‘cases not supported’
For example, sf
can’t read an array of GeoJSON objects, so I wanted to make this work
js <- c(
'[
{"type":"Point","coordinates":[0,0]},
{"type":"LineString","coordinates":[[-1,-1],[1,1]]},
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {"id":1},
"geometry": {"type": "Point", "coordinates": [100.0, 0.0]}
}
]
}
]'
)
sf <- geojson_sf( js )
sf
# Simple feature collection with 3 features and 1 field
# geometry type: GEOMETRY
# dimension: XY
# bbox: xmin: -1 ymin: -1 xmax: 100 ymax: 1
# z_range: zmin: NA zmax: NA
# m_range: mmin: NA mmax: NA
# CRS: 4326
# id geometry
# 1 NA POINT (0 0)
# 2 NA LINESTRING (-1 -1, 1 1)
# 3 1 POINT (100 0)
And going the other way you can also return a vector of GeoJSON
js <- sf_geojson( sf, atomise = T )
js
# {"type":"Feature","properties":{"id":null},"geometry":{"type":"Point","coordinates":[0.0,0.0]}}
# {"type":"Feature","properties":{"id":null},"geometry":{"type":"LineString","coordinates":[[-1.0,-1.0],[1.0,1.0]]}}
# {"type":"Feature","properties":{"id":1.0},"geometry":{"type":"Point","coordinates":[100.0,0.0]}}
What’s the benefit of ‘atomising’?
It’s useful for when you work with geospatial databases and want an individual record for each individual feature.
What happens if you don’t atomise
?
You get a single GeoJSON object
sf_geojson( sf )
# {"type":"FeatureCollection","features":[{"type":"Feature","properties":{"id":null},"geometry":{"type":"Point","coordinates":[0.0,0.0]}},{"type":"Feature","properties":{"id":null},"geometry":{"type":"LineString","coordinates":[[-1.0,-1.0],[1.0,1.0]]}},{"type":"Feature","properties":{"id":1.0},"geometry":{"type":"Point","coordinates":[100.0,0.0]}}]}
Can you remove the properites and just return the geometries
Yes. Call sfc_geojson()
on the sfc
object.
sfc_geojson( sf$geometry )
# {"type":"Point","coordinates":[0.0,0.0]}
# {"type":"LineString","coordinates":[[-1.0,-1.0],[1.0,1.0]]}
# {"type":"Point","coordinates":[100.0,0.0]}
If I have an sf
object without any properties, why does it ‘atomise’ by default?
sf$id <- NULL
sf_geojson( sf )
# {"type":"Point","coordinates":[0.0,0.0]}
# {"type":"LineString","coordinates":[[-1.0,-1.0],[1.0,1.0]]}
# {"type":"Point","coordinates":[100.0,0.0]}
The simplify
argument is TRUE
by default, and it will try and ‘simplify’ the GeoJSON. If there are no properties in the sf
object, then the GeoJSON won’t have any properties.
However, if you set simplify = FALSE
you’ll get a FeatureCollection with an empty properties field.
sf_geojson(sf, simplify = F)
# {"type":"FeatureCollection","features":[{"type":"Feature","properties":{},"geometry":{"type":"Point","coordinates":[0.0,0.0]}},{"type":"Feature","properties":{},"geometry":{"type":"LineString","coordinates":[[-1.0,-1.0],[1.0,1.0]]}},{"type":"Feature","properties":{},"geometry":{"type":"Point","coordinates":[100.0,0.0]}}]}
How fast is it?
This benchmark shows a comparison with library(sf)
for converting a string of GeoJSON of 3,221 counties in the US in to an sf
object
myurl <- "http://eric.clst.org/assets/wiki/uploads/Stuff/gz_2010_us_050_00_500k.json"
geo <- readLines(myurl)
geo <- paste0(geo, collapse = "")
library(microbenchmark)
microbenchmark(
geojsonsf = {
geojson_sf(geo)
},
sf = {
sf::st_read(geo, quiet = T)
},
times = 2
)
#Unit: milliseconds
# expr min lq mean median uq max neval
# geojsonsf 709.2268 709.2268 722.0626 722.0626 734.8984 734.8984 2
# sf 1867.6840 1867.6840 1958.7968 1958.7968 2049.9097 2049.9097 2