Question

I would like to reverse the order of the coordinates in this JSON response from (lat,lon) to (lon,lat):

url='https://www.sciencebase.gov/catalogMaps/mapping/ows/5342c5fce4b0aa151574a8ed?\
service=wfs&version=1.1.0&request=GetFeature&typeNames=sb:Conservation_Zone_WGS84&outputFormat=application/json'
response = requests.get(url).json()   
print response

{u'crs': {u'properties': {u'code': u'4326'}, u'type': u'EPSG'},
 u'features': [{u'geometry': {u'coordinates': [[[[39.81487959537135,
        -74.09688169446223],
       [39.81488113835475, -74.09587338924456],
       [39.8143317590967, -74.09614209870023],
       [39.8137616151959, -74.09633047532941],
       [39.812950626580545, -74.09670529470912],
       [39.8120075697193, -74.09698124228382],
       [39.814255381955064, -74.0973277412355],
       [39.81487959537135, -74.09688169446223]]]],
    u'type': u'MultiPolygon'},
   u'geometry_name': u'the_geom',
   u'id': u'Conservation_Zone_WGS84.1',
   u'properties': {u'ID': 1,
    u'NAME': u'Sedge Island Marine Conservation Zone',
    u'OBJECTID': 1,
    u'SHAPE_AREA': 70259289.0821,
    u'SHAPE_LEN': 40592.8006466,
    u'WEB_LINK': u'http://www.state.nj.us/dep/fgw/sedge.htm'},
   u'type': u'Feature'}],
 u'type': u'FeatureCollection'}

I could pull this apart, brute force it, and stick it back together, but I'm wondering: what would be a good pythonic way to change the order while leaving the structure intact?

Was it helpful?

Solution

Solution using numpy that should work for any geojson. It will flip all 'coordinates'.

import json
import requests
import numpy as np


def flip_geojson_coordinates(geo):
    if isinstance(geo, dict):
        for k, v in geo.iteritems():
            if k == "coordinates":
                z = np.asarray(geo[k])
                f = z.flatten()
                geo[k] = np.dstack((f[1::2], f[::2])).reshape(z.shape).tolist()
            else:
                flip_geojson_coordinates(v)
    elif isinstance(geo, list):
        for k in geo:
            flip_geojson_coordinates(k)

url = "https://www.sciencebase.gov/catalogMaps/mapping/ows/5342c5fce4b0aa151574a8ed?\
service=wfs&version=1.1.0&request=GetFeature&typeNames=sb:Conservation_Zone_WGS84&outputFormat=application/json"
resp = requests.get(url)
gj = json.loads(resp.text)

print gj
flip_geojson_coordinates(gj)
print gj

OTHER TIPS

Well ... digging down to your coordinates list takes this:

d['features'][0]['geometry']['coordinates'][0][0]

So to reverse those you'd have to do this:

d['features'][0]['geometry']['coordinates'][0][0] = [i[::-1] for i in d['features'][0]['geometry']['coordinates'][0][0]]

Or, a bit cleaner IMO:

for l in d['features'][0]['geometry']['coordinates'][0][0]:
    l.reverse()

Use a list comprehension and re-assign the result to the structure.

There are several lists involved here, so a few loops are needed:

for feature in response['features']:
    feature['geometry']['coordinates'] = [[
        [[long, lat] for lat, long in coords] for coords in poly]
        for poly in feature['geometry']['coordinates']]

This does presume that the structure of 'coordinates' is stable; I see that there is a 'type' key too, you may have to vary how you alter the structure if types other than u'MultiPolygon are used.

This moves the data from:

>>> pprint.pprint(response)
{u'crs': {u'properties': {u'code': u'4326'}, u'type': u'EPSG'},
 u'features': [{u'geometry': {u'coordinates': [[[[39.81487959537135,
                                                  -74.09688169446223],
                                                 [39.81488113835475,
                                                  -74.09587338924456],
                                                 [39.8143317590967,
                                                  -74.09614209870023],
                                                 [39.8137616151959,
                                                  -74.09633047532941],
                                                 ....
                                                 [39.814255381955064,
                                                  -74.0973277412355],
                                                 [39.81487959537135,
                                                  -74.09688169446223]]]],
                              u'type': u'MultiPolygon'},
                u'geometry_name': u'the_geom',
                u'id': u'Conservation_Zone_WGS84.1',
                u'properties': {u'ID': 1,
                                u'NAME': u'Sedge Island Marine Conservation Zone',
                                u'OBJECTID': 1,
                                u'SHAPE_AREA': 70259289.0821,
                                u'SHAPE_LEN': 40592.8006466,
                                u'WEB_LINK': u'http://www.state.nj.us/dep/fgw/sedge.htm'},
                u'type': u'Feature'}],
 u'type': u'FeatureCollection'}

to:

>>> pprint.pprint(response)
{u'crs': {u'properties': {u'code': u'4326'}, u'type': u'EPSG'},
 u'features': [{u'geometry': {u'coordinates': [[[[-74.09688169446223,
                                                  39.81487959537135],
                                                 [-74.09587338924456,
                                                  39.81488113835475],
                                                 [-74.09614209870023,
                                                  39.8143317590967],
                                                 [-74.09633047532941,
                                                  39.8137616151959],
                                                 ....
                                                 [-74.0973277412355,
                                                  39.814255381955064],
                                                 [-74.09688169446223,
                                                  39.81487959537135]]]],
                              u'type': u'MultiPolygon'},
                u'geometry_name': u'the_geom',
                u'id': u'Conservation_Zone_WGS84.1',
                u'properties': {u'ID': 1,
                                u'NAME': u'Sedge Island Marine Conservation Zone',
                                u'OBJECTID': 1,
                                u'SHAPE_AREA': 70259289.0821,
                                u'SHAPE_LEN': 40592.8006466,
                                u'WEB_LINK': u'http://www.state.nj.us/dep/fgw/sedge.htm'},
                u'type': u'Feature'}],
 u'type': u'FeatureCollection'}

Your "pythonic" code is unreadable and don't work. Keep it simple, stupid!

def swapCoords(x):
    out = []
    for iter in x:
        if isinstance(iter, list):
            out.append(swapCoords(iter))
        else:
            return [x[1], x[0]]
    return out



for feature in response['features']:
    feature['geometry']['coordinates'] = swapCoords(feature['geometry']['coordinates'])
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top