0

I have this dataframe:

      Lat       Lon
 29.39291 -98.50925
 29.39923 -98.51256
 29.40147 -98.51123
 29.38752 -98.52372
 29.39291 -98.50925
 29.39537 -98.50402
 29.39343 -98.49707
 29.39291 -98.50925
 29.39556 -98.53148

I want to convert these lat/lon rows to ZIP codes (for each row), using Python.

  • Not sure what your exact error/problem is, but pygeocoder hasn't seen an update in a while, maybe checkout geocoder. Note, that you need to set env variables with an API key you've created from a Google Account. I haven't tried the Bing provider, but that is also an option with geocoder. – Ryan Mar 4 at 19:35
5

You can use geopy and its Nominatim geocoder.

Here is an example using the DataFrame you provided:

import geopy
import pandas as pd


def get_zipcode(df, geolocator, lat_field, lon_field):
    location = geolocator.reverse((df[lat_field], df[lon_field]))
    return location.raw['address']['postcode']


geolocator = geopy.Nominatim(user_agent='my-application')

df = pd.DataFrame({
    'Lat': [29.39291, 29.39923, 29.40147, 29.38752, 29.39291, 29.39537, 29.39343, 29.39291, 29.39556],
    'Lon': [-98.50925, -98.51256, -98.51123, -98.52372, -98.50925, -98.50402, -98.49707, -98.50925, -98.53148]
})
zipcodes = df.apply(get_zipcode, axis=1, geolocator=geolocator, lat_field='Lat', lon_field='Lon')
>>> zipcodes
0    78204
1    78204
2    78204
3    78225
4    78204
5    78204
6    78204
7    78204
8    78225
dtype: object
| improve this answer | |
2

For geocoding with ArcGIS, credentials have to be provided gis = GIS("http://www.arcgis.com", "username", "password").


In terms of pandas, this code should do the work (adapted from @Marcelo Villa's answer)

from arcgis.geocoding import reverse_geocode
from arcgis.geometry import Geometry
from arcgis.gis import GIS
import pandas as pd

gis = GIS("http://www.arcgis.com", "***", "***")

def get_zip(df, lon_field, lat_field):
    location = reverse_geocode((Geometry({"x":float(df[lon_field]), "y":float(df[lat_field]), "spatialReference":{"wkid": 4326}})))
    return location['address']['Postal']

df = pd.DataFrame({
    'Lat': [29.39291, 29.39923, 29.40147, 29.38752, 29.39291, 29.39537, 29.39343, 29.39291, 29.39556],
    'Lon': [-98.50925, -98.51256, -98.51123, -98.52372, -98.50925, -98.50402, -98.49707, -98.50925, -98.53148]
})

zipcodes = df.apply(get_zip, axis=1, lat_field='Lat', lon_field='Lon')

result


Probably not as smart as pandas but using Python's internal module csv and ArcGIS's API for Python Reverse Geocoding.

from arcgis.geocoding import reverse_geocode
from arcgis.geometry import Geometry
from arcgis.gis import GIS
import csv

gis = GIS("http://www.arcgis.com", "***", "***")

coords = [
(29.39291, -98.50925),
(29.39923, -98.51256),
(29.40147, -98.51123),
(29.38752, -98.52372),
(29.39291, -98.50925),
(29.39537, -98.50402),
(29.39343, -98.49707),
(29.39291, -98.50925),
(29.39556, -98.53148)
]

result = []

for lat, lon in coords:
    pt = Geometry({
        "x": float(lon),
        "y": float(lat),
        "spatialReference": {
            "wkid": 4326
        }
    })
    try:
        result.append({'lat': lat, 'lon': lon, 'geocoded': reverse_geocode(pt)})
    except:
        pass

result_zip = []

for item in result:
    result_item = {
        'lat': item['lat'],
        'lon': item['lon'],
        'zip': item['geocoded']['address']['Postal']
    }
    result_zip.append(result_item)

keys = result_zip[0].keys()

with open('output.csv', 'w', encoding='utf8', newline='') as output_file:
    dict_writer = csv.DictWriter(output_file, keys, delimiter=';', quoting=csv.QUOTE_NONE, lineterminator='\r')
    dict_writer.writeheader()
    dict_writer.writerows(result_zip)

Output csv-file looks as following

output

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.