rloadinggeojsonropensci

How to load *part* of a multifeature geojson file in R?


I have a geojson that is a FeatureCollection containing 2 geographic data types: a LineString and a waypoint - see the raw file here - this is how it looks on GitHub:

the-data

I want to load only only the LineString, so this is what I do:

library(RCurl)
obj <- getURL("https://raw.githubusercontent.com/Robinlovelace/stplanr/master/inst/extdata/route_data.geojson")
writeLines(obj, "/tmp/obj.geojson")
obj <- readLines("/tmp/obj.geojson")
just_lines <- obj[14:(length(obj) - 28)]
just_lines[1] <- paste0("{",  just_lines[1])
just_lines[length(just_lines)] <- "}"
writeLines(just_lines, "/tmp/just_lines.geojson")

Now we have removed the pesky lines at the beginning and end of the file, it's a nicely formed GeoJSON file that we can load and plot, yay:

library(rgdal)
route <- readOGR("/tmp/just_lines.geojson", layer = "OGRGeoJSON")
plot(route)

line in R

Except it should be obvious to any R user that this is a very clunky and inefficient way of doing this involving too many lines of code and unnecessary reading and writing to the hard disc. There must be another way!

Options I've looked at

Context

I'm creating a package for sustainable transport planning, stplanr. A function to find cycling routes (like in the image below) needs to load in the FeatureCollection geojson data from the CycleStreets.net api.

flow


Solution

  • Read the data using jsonlite direct from the URL:

     obj <- jsonlite::fromJSON("https://raw.githubusercontent.com/Robinlovelace/stplanr/master/inst/extdata/route_data.geojson")
    

    Convert the first object in the collection to SpatialLines:

     sl = SpatialLines(list(Lines(list(Line(obj$features[1,]$geometry$coordinates[[1]])),ID=1)))
     plot(sl)
    

    That assumes the feature is a single line string.

    To make a SpatialLinesDataFrame with the attributes:

     sldf=SpatialLinesDataFrame(sl=sl,data=obj$features[1,]$properties)
    

    Should probably also give it a CRS:

     proj4string(sldf)=CRS("+init=epsg:4326")