Skip to content
Switch branches/tags
Go to file
Cannot retrieve contributors at this time
title: "Reading and writing GeoJSON files in R"
author: "Robin Lovelace"
date: "11/26/2014"
output: html_document
## Introduction
[GeoJSON]( is an open data format that
extends [JSON](, the JavaScript Object Notation
to encode spatial information.
GeoJSON has the following advantages:
- All the geographical information is self contained (unlike shapefiles, which have multiple files for one spatial object)
- It is an open standard which is becoming increasingly popular
- GeoJSON files display as maps on GitHub by default!
The disadvantages are:
- GeoJSON files are [quite large]( compared with non text formats such as shapefiles and
spatial databases.
- GeoJSON files can be slow to read/write and are not supported by
all GIS software (yet!).
## Reading GeoJSONs with readOGR
As illustrated by this [post](, it is easy to read and write GeoJSON files
in R, using the [**rgdal**]( package, which calls
[gdal]( commands. Here's an example using
publicly available GeoJSON file:
```{r, echo=FALSE}
system("rm /tmp/gas*")
library(rgdal) # the library we'll be using
u <- ""
downloader::download(url = u, destfile = "/tmp/gas.GeoJSON")
gas <- readOGR(dsn = "/tmp/gas.GeoJSON", layer = "OGRGeoJSON")
Note that to test whether the GeoJSON driver works on your system,
you can use the following [command](
"GeoJSON" %in% ogrDrivers()$name
As shown in the above example,
GeoJSON files can have coordinate reference system (CRS)
allocated to them through the `"crs"` 'member':
```{r, engine='node', eval=FALSE}
"crs": {
"type": "name",
"properties": {
"name": "urn:ogc:def:crs:OGC:1.3:CRS84"
Note that we can see this definition in the `gas.GeoJSON` file:
This 'member' is defined in plain text in the GeoJSON file
before the spatial `"features"` are defined. Please see this
small example of [gas stations]( to see how the CRS
is defined in the context of a complete GeoJSON file.
## Writing GeoJSONs with writeOGR
To write GeoJSON files, the sensibly named corrollary of
`readOGR` is used, `writeOGR`:
geojsonio::geojson_write(gas, file = "/tmp/gas2.geojson")
## Multifeature geojsons
Based on [this](, geojson files can usually be loaded into R with `readOGR`, as illustrated above.
However, this fails for multifeature geojsons.
Reproducible example:
downloader::download("", "test.geojson")
try(test <- rgdal::readOGR("test.geojson", "OGRGeoJSON")) # fails with:
There are 2 solutions. One uses rgdal and the gdal argument
`require_geomType`. The other uses geojsonio.
### Multifeature geojsons with rgdal
The first solution uses new features introduced in gdal 0.9-3.
It is worth checking (and maybe updating) your gdal version.
(Thanks to [@hrbrmstr]( for this detailed information.)
rgdal::getGDALVersionInfo() # check the version of gdal
system("gdal-config --version") # asking gdal its version from bash
Before update, this was:
[1] "GDAL 1.11.1, released 2014/09/24"
After updating gdal, e.g. like this (Ubuntu), it changed:
$ sudo add-apt-repository ppa:ubuntugis/ubuntugis-unstable && sudo apt-get update
$ sudo apt-get install gdal-bin
gdal can provide us with information about the layers in the
multipart geojson.
It can also provide more general information about the object,
if we ask it correctly.
try(ogrInfo("test.geojson")) # no information on the file
system("ogrinfo test.geojson ")
try(ogrInfo("test.geojson", "OGRGeoJSON"))
The output from the previous lines indicates how we can
access just one layer. We use the argument `require_geomType`
to specify which of the geometries to load:
testp_info <-
ogrInfo("test.geojson", "OGRGeoJSON", require_geomType="wkbPoint")
testp_df <-$iteminfo)
Note we can use the same command for any of the geometries:
```{r, eval=FALSE}
ogrInfo("test.geojson", "OGRGeoJSON", require_geomType = "wkbPolygon")
NOTE: keeping only 23 wkbPolygon of 781 features
note that extent applies to all features
Source: "test.geojson", layer: "OGRGeoJSON"
Driver: GeoJSON number of rows 781
selected geometry type: wkbPolygon with 23 rows
Feature type: wkbPolygon with 2 dimensions
Extent: (12.48326 41.88355) - (12.5033 41.89629)
CRS: +proj=longlat +datum=WGS84 +no_defs
Number of fields: 78
name type length typeName
1 area 4 0 String
2 bicycle 4 0 String
3 highway 4 0 String
Armed with this information, we can read in the features:
points <- readOGR("test.geojson", "OGRGeoJSON", require_geomType="wkbPoint")
lines <- readOGR("test.geojson", "OGRGeoJSON", require_geomType="wkbLineString")
polygons <- readOGR("test.geojson", "OGRGeoJSON", require_geomType="wkbPolygon")
Let's plot the data (see )
plot(lines, col="#7f7f7f")
plot(polygons, add=TRUE)
plot(points, add=TRUE, col="red")
## Solution from geojsonio
This is an alternative solution:
test <- geojsonio::geojson_read("test.geojson")
Then we can filter out the feature types of interest:
obj = Filter(
## Solution from Spacedman
mess <- 'ogr2ogr -where "OGR_GEOMETRY=\'LINESTRING\'" -f "GeoJSON" lines.geojson test.geojson'
testl <- rgdal::readOGR("lines.geojson", layer = "OGRGeoJSON")
## gdal fails to convert certain types of CRS
Let's see what R has created from writeOGR:
gas2 <- readLines("/tmp/gas.GeoJSON")
Frustratingly, this fails to write the CRS into the file.
**rgdal**'s ability to read a crs from a GeoJSON file is no
guarantee of it's ability to then write it out again.
It seems
**rgdal** has **lost the CRS in translation**.
This can problem be caused by using an old version of
`gdal`. Not in this case though: incomplete CRS values can
lead `rgdal` to omit the `"crs"` in the file, as explained by
Roger Bivand in a lengthy [conversation](
on the [R-sig-geo](
email list. To test that the problem is the fault of gdal and
not R, we can use the `ogr2ogr` command line tool, supplied by
```{r, echo=FALSE}
system("rm /tmp/gas3.*")
# use call gdal from the operating system to convert original GeoJSON:
system("ogr2ogr -f 'ESRI Shapefile' /tmp/gas3.shp '/tmp/gas.GeoJSON' ")
gas3 <- readOGR(dsn = "/tmp", layer = "gas3")
The above code shows that gdal has successfully converted the
original GeoJSON file to a shapefile, maintaining the CRS.
(Note that the CRS is identical but its definition is slightly different.)
Let's take a look at the `.proj` file that gdal created:
gas3_proj <- readLines("/tmp/gas3.prj", skipNul = T)
There are various ways to solve the problem.
The 'outside R' solution would be to write the file
first as a shapefile, and then use `ogr2ogr` to convert
it to a GeoJSON. But as shown in the code below, this fails:
writeOGR(gas, "/tmp/", layer = "gas4", driver = "ESRI Shapefile")
system("ogr2ogr -f 'GeoJSON' /tmp/gas5.GeoJSON '/tmp/gas4.shp' ")
# CRS definitions
As Roger Bivand shows, if the CRS is defined in certain
ways, the `"crs"` member will be written to the GeoJSON file.
But it is difficult to know how to define a CRS other than
by its [EPSG name](
gas6 <- gas # duplicate the gas object
proj4string(gas6) <- CRS("+init=epsg:4283")
# the below works, but incorrect CRS
# proj4string(gas6) <- CRS("+proj=longlat +ellps=clrk66 +datum=NAD27")
geojsonio::geojson_write(gas6, file = "/tmp/gas6.geojson")
# A manual solution
To solve the problem manually, we can simply add the correct projection
to the GeoJSON file that has been created. Thankfully this is straightforward, as line 3 of the files are left empty by gdal, presumably ready
for such an eventuality:
gas7 <- readLines("/tmp/gas2.geojson")
gas7[3] <- '"crs": {"type": "EPSG", "properties": {"code": 4283}},'
writeLines(gas7, con = "/tmp/gas8.GeoJSON")
gas8 <- readOGR(dsn = "/tmp/gas8.GeoJSON", layer = "OGRGeoJSON")
This is a messy solution but it's the only one I could find to write
GeoJSON files with a CRS defined for Australian data services' default CRS.
```{r, echo=FALSE}
# library(rgdal)
# library(pryr)
# pryr::show_c_source(readOGR)
# showMethods(readOGR)
# ??readOGR