Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Loading JSON into a GeoDataFrame

I'm having difficulty loading the following JSON containing GIS data (https://data.cityofnewyork.us/resource/5rqd-h5ci.json) into a GeoDataFrame.

The following code fails when I try to set the geometry.

import requests
import geopandas as gpd
data = requests.get("https://data.cityofnewyork.us/resource/5rqd-h5ci.json")
gdf = gpd.GeoDataFrame(data.json())
gdf = gdf.set_geometry('the_geom')
gdf.head()
like image 414
blahblahblah Avatar asked Aug 07 '17 17:08

blahblahblah


4 Answers

For people who are using web mapping libraries...

If the GeoJSON is wrapped in a FeatureCollection, as they often are when exported to a GeoJSON string by web mapping libraries (in my case, Leaflet), then all you need to do is pass the list at features to from_features() like so:

import geopandas as gpd
study_area = json.loads("""
 {"type": "FeatureCollection", "features": [{"type": "Feature", "properties": {}, "geometry": {"type": "Polygon", "coordinates": [[[36.394272, -18.626726], [36.394272, -18.558391], [36.489716, -18.558391], [36.489716, -18.626726], [36.394272, -18.626726]]]}}]}
""")
gdf = gpd.GeoDataFrame.from_features(study_area["features"])
print(gdf.head())

Output:

                                            geometry
0  POLYGON ((36.394272 -18.626726, 36.394272 -18....

Easy peasy.

like image 69
wfgeo Avatar answered Nov 13 '22 23:11

wfgeo


Setting the geometry fails because the geopandas.GeoDataFrame constructor doesn't appear to be built to handle JSON objects as python data structures. It therefore complains about the argument not being a valid geometry object. You have to parse it into something that geopandas.GeoDataFrame can understand, like a shapely.geometry.shape. Here's what ran without error on my side, Python 3.5.4:

#!/usr/bin/env python3

import requests
import geopandas as gpd
from shapely.geometry import shape

r = requests.get("https://data.cityofnewyork.us/resource/5rqd-h5ci.json")
r.raise_for_status()

data = r.json()
for d in data:
    d['the_geom'] = shape(d['the_geom'])

gdf = gpd.GeoDataFrame(data).set_geometry('the_geom')
gdf.head()

A disclaimer: I know absolutely nothing about Geo anything. I didn't even know these libraries and this kind of data existed until I installed geopandas to tackle this bounty and read a little bit of online documentation.

like image 21
JoshuaRLi Avatar answered Nov 14 '22 00:11

JoshuaRLi


Combining the above answers, this worked for me.

import pandas as pd
import geopandas as gpd
from shapely.geometry import shape

nta = pd.read_json( r'https://data.cityofnewyork.us/resource/93vf-i5bz.json' )
nta['the_geom'] = nta['the_geom'].apply(shape)
nta_geo = gpd.GeoDataFrame(nta).set_geometry('geometry')
like image 3
Can Sucuoglu Avatar answered Nov 14 '22 00:11

Can Sucuoglu


A more idiomatic way that uses regular dataframe functions inherited from pandas, and the native GeoDataFrame.from_features:

gdf = gpd.GeoDataFrame(data.json())

# features column does not need to be stored, this is just for illustration
gdf['features'] = gdf['the_geom'].apply(lambda x: {'geometry': x, 'properties': {}})
gdf2 = gpd.GeoDataFrame.from_features(gdf['features'])

gdf = gdf.set_geometry(gdf2.geometry)
gdf.head()
like image 1
prusswan Avatar answered Nov 13 '22 23:11

prusswan