def query_address_api(df, address_api='openmapquest', address_api_key=None): logger.info("Querying address API") # Create the address data frame and cache file if it doesn't exist already if not os.path.exists(ADDRESS_CACHE): logger.info( "Converting {} geometries to EPSG 4326, this may take awhile ". format(len(df))) df_address = geopandas.GeoDataFrame(df.to_crs(epsg='4326').geometry, crs='epsg:4326') df_address['address'] = None logger.info("Creating new address cache file {}".format(ADDRESS_CACHE)) df_address.to_file(ADDRESS_CACHE, driver='ESRI Shapefile') else: logger.info( "Reading in previous address cache file {}".format(ADDRESS_CACHE)) df_address = geopandas.read_file(ADDRESS_CACHE) empty_address = df_address.loc[pd.isna(df_address['address'])] logger.info("Querying for {} addresses".format(len(empty_address))) for row in tqdm(empty_address.itertuples(), total=empty_address.shape[0]): try: address = reverse_geocode(row.geometry.centroid, user_agent='caladrius', provider=address_api, api_key=address_api_key) df_address.loc[row.Index, 'address'] = address['address'][0] df_address.to_file(ADDRESS_CACHE, driver='ESRI Shapefile') except Exception as e: logger.exception('Geocoding failed for {latlon}'.format( latlon=row.geometry.centroid)) continue
def get_point_location(points, provider='nominatim', user_agent='petk'): centroid = MultiPoint(points).centroid if importlib.util.find_spec('geopy') is not None: from geopandas.tools import reverse_geocode return reverse_geocode(centroid, provider=provider, user_agent=user_agent)['address'][0] else: return ', '.join([str(x) for x in mapping(centroid)['coordinates']])
def test_reverse(self): with mock.patch('geopy.geocoders.googlev3.GoogleV3.reverse', ReverseMock()) as m: g = reverse_geocode(self.points, provider='googlev3', timeout=2) self.assertEqual(len(self.points), m.call_count) self.assertIsInstance(g, gpd.GeoDataFrame) expected = GeoSeries(self.points, crs=from_epsg(4326)) assert_geoseries_equal(expected, g['geometry']) tm.assert_series_equal( g['address'], pd.Series('address' + str(x) for x in range(len(self.points))))
def test_reverse(self): with mock.patch('geopy.geocoders.googlev3.GoogleV3.reverse', ReverseMock()) as m: g = reverse_geocode(self.points, provider='googlev3', timeout=2) self.assertEqual(len(self.points), m.call_count) self.assertIsInstance(g, gpd.GeoDataFrame) expected = GeoSeries(self.points, crs=from_epsg(4326)) assert_geoseries_equal(expected, g['geometry']) address = pd.Series(['address' + str(x) for x in range(len(self.points))], name='address') tm.assert_series_equal(g['address'], address)
def test_reverse(self): with mock.patch('geopy.geocoders.googlev3.GoogleV3.reverse', ReverseMock()) as m: g = reverse_geocode(self.points, provider='googlev3', timeout=2) assert len(self.points) == m.call_count assert isinstance(g, GeoDataFrame) expected = GeoSeries(self.points, crs=from_epsg(4326)) assert_geoseries_equal(expected, g['geometry']) address = pd.Series( ['address' + str(x) for x in range(len(self.points))], name='address') assert_series_equal(g['address'], address)
def test_reverse(locations, points): from geopy.geocoders import GeocodeFarm for provider in ['geocodefarm', GeocodeFarm]: with mock.patch('geopy.geocoders.GeocodeFarm.reverse', ReverseMock()) as m: g = reverse_geocode(points, provider=provider, timeout=2) assert len(points) == m.call_count assert isinstance(g, GeoDataFrame) expected = GeoSeries(points, crs=from_epsg(4326)) assert_geoseries_equal(expected, g['geometry']) address = pd.Series(['address' + str(x) for x in range(len(points))], name='address') assert_series_equal(g['address'], address)
def test_reverse(locations, points): from geopy.geocoders import Photon for provider in ["photon", Photon]: with mock.patch("geopy.geocoders.Photon.reverse", ReverseMock()) as m: g = reverse_geocode(points, provider=provider, timeout=2) assert len(points) == m.call_count assert isinstance(g, GeoDataFrame) expected = GeoSeries(points, crs="EPSG:4326") assert_geoseries_equal(expected, g["geometry"]) address = pd.Series(["address" + str(x) for x in range(len(points))], name="address") assert_series_equal(g["address"], address)
def test_reverse(locations, points): from geopy.geocoders import GoogleV3 for provider in ['googlev3', GoogleV3]: with mock.patch('geopy.geocoders.googlev3.GoogleV3.reverse', ReverseMock()) as m: g = reverse_geocode(points, provider=provider, timeout=2) assert len(points) == m.call_count assert isinstance(g, GeoDataFrame) expected = GeoSeries(points, crs=from_epsg(4326)) assert_geoseries_equal(expected, g['geometry']) address = pd.Series( ['address' + str(x) for x in range(len(points))], name='address') assert_series_equal(g['address'], address)
def test_bad_provider_reverse(): from geopy.exc import GeocoderNotFound with pytest.raises(GeocoderNotFound): reverse_geocode(["cambridge, ma"], "badprovider")
def test_bad_provider_reverse(): from geopy.exc import GeocoderNotFound with pytest.raises(GeocoderNotFound): reverse_geocode(['cambridge, ma'], 'badprovider')
def test_bad_provider_reverse(self): with self.assertRaises(ValueError): reverse_geocode(['cambridge, ma'], 'badprovider')
def test_bad_provider_reverse(self): from geopy.exc import GeocoderNotFound with pytest.raises(GeocoderNotFound): reverse_geocode(['cambridge, ma'], 'badprovider')
def test_googlev3_reverse(self): g = reverse_geocode(self.points, provider='googlev3', timeout=2) self.assertIsInstance(g, gpd.GeoDataFrame)
def test_bad_provider_reverse(): from geopy.exc import GeocoderNotFound with pytest.raises(GeocoderNotFound): reverse_geocode([Point(0, 0)], "badprovider")
def apply(data, options=default_options, config=default_config, warning=print): """Perform conversion between latitude,longitude and address ARGUMENTS: data (pandas.DataFrame) The data frame must contain either an `address` field or `latitude` and `longitude` fields, according to whether `options["reverse"]` is `True` or `False`. options (dict) "reverse" (bool) specifies the direction of resolution. Forward resolves `address` from `latitude,longitude` from . Reverse resolves `latitude,longitude` `address` from. The default is `options["reverse"] = False`, which provides forward resolution. config (dict) "provider" (str) specifies the providers of the address resolution algorithm. The default is "nominatim". "user_agent" (str) specifies the user agent for the address resolution algorithm. The default is "csv_user_ht". RETURNS: pandas.DataFrame The first (and only) return value is the `data` data frame with either the `address` or `latitude,longitude` fields updated/added. """ if options["reverse"]: # convert address to lat,lon if not "address" in list(data.columns): raise Exception( "reserve address resolution requires 'address' field") data.reset_index(inplace=True) # index is not meaningful for retries in range(config["retries"]): try: pos = geocode( data["address"], provider=config["provider"], user_agent=config["user_agent"], timeout=config["timeout"], ) break except Exception as err: pos = err import time time.sleep(config["sleep"]) if type(pos) is Exception: raise pos data["longitude"] = list(map(lambda p: p.x, pos["geometry"])) data["latitude"] = list(map(lambda p: p.y, pos["geometry"])) return data else: # convert lat,lon to address try: lats = list(map(lambda x: float(x), data["latitude"])) lons = list(map(lambda x: float(x), data["longitude"])) pos = list(map(lambda xy: Point(xy), list(zip(lons, lats)))) except: pos = None if type(pos) == type(None): raise Exception( "address resolution requires 'latitude' and 'longitude' fields" ) for retries in range(config["retries"]): try: addr = reverse_geocode( pos, provider=config["provider"], user_agent=config["user_agent"], timeout=config["timeout"], ) break except Exception as err: addr = err import time time.sleep(config["sleep"]) if type(addr) is Exception: raise addr data["address"] = Series(addr["address"], dtype="string").tolist() return data