MonikaP
MonikaP

Reputation: 147

A general way to read single features from geojson FeatureCollection in R

I am trying to read a geojson file containing FeatureCollection. I am looking for a general way to convert a single feature into a Spatial object.

Specifically, the file is a bus route generated by Overpass query: http://overpass-turbo.eu/s/BdB . I tried various combinations of commands from geojsonio library, such as

x<-geojson_atomize(file_to_geojson(name))

but they give various errors (in this case "'x' not valid JSON" even though file_to_geojson conversion claims to be a success).

The answer to this question How to load *part* of a multifeature geojson file in R? gives a way to do it, but it is valid for one specific case and requires knowledge of the structure of specific geojson. Besides, the answer is 3 years old and I am assuming that packages developed since.

Upvotes: 1

Views: 852

Answers (1)

HAVB
HAVB

Reputation: 1888

It's quite easy if you use the sf package:

#install.packages("sf)
library(sf)
# I have downloaded the Overpass query as a GeoJSON file
route <- st_read("export.geojson")

The result is a dataframe with each feature represented as a row, so you can subset it (i.e. route[1:3,]) to extract only the features you are interested in. Feature attributes are stored as columns, so you can easily select a subset of those too.

And that's it!

Let's take a look at your particular case.

There are 89 features:

nrow(route)

[1] 89 

with 12 attributes (the last column, number 13, appears in all sf objects and holds the geometry data)

names(route)

[1] "id"                       "X.id"                     "from"                    
 [4] "name"                     "network"                  "public_transport.version"
 [7] "ref"                      "route"                    "source"                  
[10] "to"                       "type"                     "X.relations"             
[13] "geometry"  

That look like this:

plot(route)

(only the first ten attributes are shown with plot() unless you use max.plot = 10)

enter image description here

Inspecting the dataframe, you can see that there are two polyline features, and 87 point features -transport routes and transport stations, I assume.

summary(route$geometry)
MULTILINESTRING           POINT       epsg:4326   +proj=long... 
              2              87               0               0 

The first two rows contain the lines, and the rest represent the points.

head(route)

Simple feature collection with 6 features and 12 fields
geometry type:  GEOMETRY
dimension:      XY
bbox:           xmin: 20.89744 ymin: 52.21596 xmax: 21.10796 ymax: 52.25929
epsg (SRID):    4326
proj4string:    +proj=longlat +datum=WGS84 +no_defs
                id             X.id                    from
1 relation/4254149 relation/4254149 PKP Olszynka Grochowska
2 relation/4254150 relation/4254150            Stare Bemowo
3    node/32920674    node/32920674                    <NA>
4   node/209094035   node/209094035                    <NA>
5   node/251880529   node/251880529                    <NA>
6   node/302874515   node/302874515                    <NA>
                                              name      network public_transport.version  ref route
1 Bus 523: PKP Olszynka Grochowska => Stare Bemowo ZTM Warszawa                        2  523   bus
2 Bus 523: Stare Bemowo => PKP Olszynka Grochowska ZTM Warszawa                        2  523   bus
3                                             <NA>         <NA>                     <NA> <NA>  <NA>
4                                             <NA>         <NA>                     <NA> <NA>  <NA>
5                                             <NA>         <NA>                     <NA> <NA>  <NA>
6                                             <NA>         <NA>                     <NA> <NA>  <NA>
                                                    source                      to  type
1 Rozkład jazdy ZTM Warszawa, trasa wygenerowana przez bot            Stare Bemowo route
2 Rozkład jazdy ZTM Warszawa, trasa wygenerowana przez bot PKP Olszynka Grochowska route
3                                                     <NA>                    <NA>  <NA>
4                                                     <NA>                    <NA>  <NA>
5                                                     <NA>                    <NA>  <NA>
6                                                     <NA>                    <NA>  <NA>
                                                                                                                                                                                                                                                                                                                                                  X.relations
1                                                                                                                                                                                                                                                                                                                                                        <NA>
2                                                                                                                                                                                                                                                                                                                                                        <NA>
3 [ { "role": "stop", "rel": 4254149, "reltags": { "from": "PKP Olszynka Grochowska", "name": "Bus 523: PKP Olszynka Grochowska => Stare Bemowo", "network": "ZTM Warszawa", "public_transport:version": "2", "ref": "523", "route": "bus", "source": "Rozkład jazdy ZTM Warszawa, trasa wygenerowana przez bot", "to": "Stare Bemowo", "type": "route" } } ]
4 [ { "role": "stop", "rel": 4254150, "reltags": { "from": "Stare Bemowo", "name": "Bus 523: Stare Bemowo => PKP Olszynka Grochowska", "network": "ZTM Warszawa", "public_transport:version": "2", "ref": "523", "route": "bus", "source": "Rozkład jazdy ZTM Warszawa, trasa wygenerowana przez bot", "to": "PKP Olszynka Grochowska", "type": "route" } } ]
5 [ { "role": "stop", "rel": 4254150, "reltags": { "from": "Stare Bemowo", "name": "Bus 523: Stare Bemowo => PKP Olszynka Grochowska", "network": "ZTM Warszawa", "public_transport:version": "2", "ref": "523", "route": "bus", "source": "Rozkład jazdy ZTM Warszawa, trasa wygenerowana przez bot", "to": "PKP Olszynka Grochowska", "type": "route" } } ]
6 [ { "role": "stop", "rel": 4254150, "reltags": { "from": "Stare Bemowo", "name": "Bus 523: Stare Bemowo => PKP Olszynka Grochowska", "network": "ZTM Warszawa", "public_transport:version": "2", "ref": "523", "route": "bus", "source": "Rozkład jazdy ZTM Warszawa, trasa wygenerowana przez bot", "to": "PKP Olszynka Grochowska", "type": "route" } } ]
                        geometry
1 MULTILINESTRING ((21.10695 ...
2 MULTILINESTRING ((20.89804 ...
3      POINT (21.07858 52.23575)
4      POINT (21.08457 52.24583)
5      POINT (21.07847 52.23509)
6      POINT (21.08454 52.24331)

If you only want, say, the first feature, you simple subset the dataframe accordingly:

myfeature <- route[1,]

You could also want a set of features, like all the lines. Here it's easy to select them, because we know they are in the first two rows:

route_lines <- route[1:2,]

plot(route_lines)

enter image description here

Or the points:

route_stations <- route[3:89,]

plot(route_stations)

enter image description here

Finally, if you want to save your extracted features, just do something like:

st_write(route_stations, "route_stations.geojson")

See https://cran.r-project.org/web/packages/sf/vignettes/sf1.html for additonal information on the really cool features available with sf.

Upvotes: 2

Related Questions