mirror of
https://github.com/wassname/geopandas.git
synced 2026-09-09 11:22:50 +08:00
Add reverse() method to geocode module
Take a bunch of points and turn them into addresses.
This commit is contained in:
+68
-9
@@ -39,7 +39,7 @@ def geocode(strings, provider='googlev3', **kwargs):
|
||||
* yahoo
|
||||
* mapquest
|
||||
* openmapquest
|
||||
|
||||
|
||||
Ensure proper use of the results by consulting the Terms of Service for
|
||||
your provider.
|
||||
|
||||
@@ -49,16 +49,71 @@ def geocode(strings, provider='googlev3', **kwargs):
|
||||
Example
|
||||
-------
|
||||
>>> df = geocode(['boston, ma', '1600 pennsylvania ave. washington, dc'])
|
||||
address geometry
|
||||
0 Boston, MA, USA POINT (-71.0597731999999951 42.3584308000000007)
|
||||
1 1600 Pennsylvania Avenue Northwest, President'... POINT (-77.0365122999999983 38.8978377999999978)
|
||||
|
||||
address \
|
||||
0 Boston, MA, USA
|
||||
1 1600 Pennsylvania Avenue Northwest, President'...
|
||||
|
||||
geometry
|
||||
0 POINT (-71.0597732 42.3584308)
|
||||
1 POINT (-77.0365305 38.8977332)
|
||||
|
||||
"""
|
||||
return _query(strings, True, provider, **kwargs)
|
||||
|
||||
|
||||
def reverse(points, provider='googlev3', **kwargs):
|
||||
"""
|
||||
Reverse geocode a set of points and get a GeoDataFrame of the resulting
|
||||
addresses.
|
||||
|
||||
The points
|
||||
|
||||
Parameters
|
||||
----------
|
||||
points : list or Series of Shapely Point objects.
|
||||
x coordinate is longitude
|
||||
y coordinate is latitude
|
||||
provider : geopy geocoder to use, default 'googlev3'
|
||||
These are the same options as the geocode() function
|
||||
Some providers require additional arguments such as access keys
|
||||
See each geocoder's specific parameters in geopy.geocoders
|
||||
* googlev3, default
|
||||
* bing
|
||||
* google
|
||||
* yahoo
|
||||
* mapquest
|
||||
* openmapquest
|
||||
|
||||
Ensure proper use of the results by consulting the Terms of Service for
|
||||
your provider.
|
||||
|
||||
Reverse geocoding requires geopy. Install it using 'pip install geopy'.
|
||||
See also https://github.com/geopy/geopy
|
||||
|
||||
Example
|
||||
-------
|
||||
>>> df = reverse([Point(-71.0594869, 42.3584697),
|
||||
Point(-77.0365305, 38.8977332)])
|
||||
|
||||
address \
|
||||
0 29 Court Square, Boston, MA 02108, USA
|
||||
1 1600 Pennsylvania Avenue Northwest, President'...
|
||||
|
||||
geometry
|
||||
0 POINT (-71.0594869 42.3584697)
|
||||
1 POINT (-77.0365305 38.8977332)
|
||||
|
||||
"""
|
||||
return _query(points, False, provider, **kwargs)
|
||||
|
||||
|
||||
def _query(data, forward, provider, **kwargs):
|
||||
import geopy
|
||||
from geopy.geocoders.base import GeocoderQueryError
|
||||
|
||||
if not isinstance(strings, pd.Series):
|
||||
strings = pd.Series(strings)
|
||||
if not isinstance(data, pd.Series):
|
||||
data = pd.Series(data)
|
||||
|
||||
# workaround changed name in 0.96
|
||||
try:
|
||||
@@ -71,16 +126,19 @@ def geocode(strings, provider='googlev3', **kwargs):
|
||||
'yahoo': Yahoo,
|
||||
'mapquest': geopy.geocoders.MapQuest,
|
||||
'openmapquest': geopy.geocoders.OpenMapQuest,
|
||||
'nominatim' : geopy.geocoders.Nominatim}
|
||||
'nominatim': geopy.geocoders.Nominatim}
|
||||
|
||||
if provider not in coders:
|
||||
raise ValueError('Unknown geocoding provider: {0}'.format(provider))
|
||||
|
||||
coder = coders[provider](**kwargs)
|
||||
results = {}
|
||||
for i, s in iteritems(strings):
|
||||
for i, s in iteritems(data):
|
||||
try:
|
||||
results[i] = coder.geocode(s)
|
||||
if forward:
|
||||
results[i] = coder.geocode(s)
|
||||
else:
|
||||
results[i] = coder.reverse((s.y, s.x), exactly_one=True)
|
||||
except (GeocoderQueryError, ValueError):
|
||||
results[i] = (None, None)
|
||||
time.sleep(_throttle_time(provider))
|
||||
@@ -88,6 +146,7 @@ def geocode(strings, provider='googlev3', **kwargs):
|
||||
df = _prepare_geocode_result(results)
|
||||
return df
|
||||
|
||||
|
||||
def _prepare_geocode_result(results):
|
||||
"""
|
||||
Helper function for the geocode function
|
||||
|
||||
+17
-4
@@ -8,7 +8,7 @@ from shapely.geometry import Point
|
||||
import geopandas as gpd
|
||||
import nose
|
||||
|
||||
from geopandas.geocode import geocode, _prepare_geocode_result
|
||||
from geopandas.geocode import geocode, reverse, _prepare_geocode_result
|
||||
from .util import unittest
|
||||
|
||||
|
||||
@@ -26,6 +26,8 @@ class TestGeocode(unittest.TestCase):
|
||||
_skip_if_no_geopy()
|
||||
self.locations = ['260 Broadway, New York, NY',
|
||||
'77 Massachusetts Ave, Cambridge, MA']
|
||||
self.points = [Point(-71.0597732, 42.3584308),
|
||||
Point(-77.0365305, 38.8977332)]
|
||||
|
||||
def test_prepare_result(self):
|
||||
# Calls _prepare_result with sample results from the geocoder call
|
||||
@@ -69,21 +71,32 @@ class TestGeocode(unittest.TestCase):
|
||||
self.assertEqual(len(row['geometry'].coords), 0)
|
||||
self.assert_(pd.np.isnan(row['address']))
|
||||
|
||||
def test_bad_provider(self):
|
||||
def test_bad_provider_forward(self):
|
||||
from geopandas.geocode import geocode
|
||||
with self.assertRaises(ValueError):
|
||||
geocode(['cambridge, ma'], 'badprovider')
|
||||
|
||||
def test_googlev3(self):
|
||||
def test_bad_provider_reverse(self):
|
||||
with self.assertRaises(ValueError):
|
||||
reverse(['cambridge, ma'], 'badprovider')
|
||||
|
||||
def test_googlev3_forward(self):
|
||||
from geopandas.geocode import geocode
|
||||
g = geocode(self.locations, provider='googlev3', timeout=2)
|
||||
self.assertIsInstance(g, gpd.GeoDataFrame)
|
||||
|
||||
def test_openmapquest(self):
|
||||
def test_googlev3_reverse(self):
|
||||
from geopandas.geocode import geocode
|
||||
g = reverse(self.points, provider='googlev3', timeout=2)
|
||||
self.assertIsInstance(g, gpd.GeoDataFrame)
|
||||
|
||||
def test_openmapquest_forward(self):
|
||||
from geopandas.geocode import geocode
|
||||
g = geocode(self.locations, provider='openmapquest', timeout=2)
|
||||
self.assertIsInstance(g, gpd.GeoDataFrame)
|
||||
|
||||
# openmapquest does not have reverse implemented in geopy
|
||||
|
||||
@unittest.skip('Nominatim server is unreliable for tests.')
|
||||
def test_nominatim(self):
|
||||
from geopandas.geocode import geocode
|
||||
|
||||
Reference in New Issue
Block a user