如何解析 Nominatim 反向地理编码返回的地址组件?
How parse address components returned by Nominatim reverse geocoding?
所以,我正在开发一个用于地理标记图像的地图应用程序,我想在我的地图上包含兴趣点的地址信息。我已经成功地使用 Geopandas、GeoPy 和 Nominatim 以及来自 PostGIS table 的点数据完成了大部分任务(例如 POINT Z (8.726176366993529 50.10868874301912 96.90000000000001)。
虽然脚本完成了我想要的大部分工作,但结果 returns 有很多无关信息,我想在更新数据库之前将其解析为一两个数据。我能够使用 gecoding and reverse geocoding 上的两篇文章破解我的脚本。我的问题归结为不确定脚本如何接收响应对象以及我如何在将属性添加到我的 Dataframe 之前或之后访问这些属性。
我没有import语句的代码如下:
conn = psycopg2.connect(
host="localhost",
database="Nizz0k",
user="Nizz0k",
password="")
sql = "select * from public.\"Peng\""
engine = create_engine('postgresql://Nizz0k@localhost:5432/public.\"Peng\"')
df = gpd.read_postgis(sql, conn, geom_col="geom")
df['lon'] = df.geometry.apply(lambda p: p.x)
df['lat'] = df.geometry.apply(lambda p: p.y)
df['geocode'] = df['lat'].map(str) + ', ' + df['lon'].map(str)
locator = Nominatim(user_agent="pengMappingAgent", timeout=10)
rgeocode = RateLimiter(locator.reverse, min_delay_seconds=0.001)
tqdm.pandas()
df['address'] = df['geocode'].progress_apply(rgeocode)
所以,我的 Python 知识非常有限,但我尝试访问新创建的 df['address']
列中的属性似乎没有任何效果。调用 df.head()
显示正确创建的列和地址信息,但现在我想简化列中的信息并将其部分提取到新列中。理想情况下,我想提取街道和门牌号信息以及社区信息,并删除城市、县、州和国家信息,因为它们是多余的。
根据我所做的研究,我应该能够从响应对象中提取此信息,但我不确定从何处或如何访问它。似乎此信息在我的专栏中被转换为字符串(我认为),如果没有,我不确定如何设置循环或 lambda 函数来获取这些内容。最坏的情况是,我假设只需一些字符串操作就可以实现我的目标,但似乎应该有更简单的方法。
- 显然我无法连接到您的数据库,因此模拟了一个 GeoDataFrame,这是一系列点
- 然后简化了调用 Nominatim
的代码
- raw returns a dict 这可以按照下面的代码提取
import geopandas as gpd
import shapely.geometry
from geopy.geocoders import Nominatim
import pandas as pd
gdf = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres"))
# a geodata frame with a few points...
df = gpd.GeoDataFrame(
geometry=gdf.loc[gdf["iso_a3"].eq("BEL"), "geometry"]
.apply(lambda p: p.exterior.coords)
.explode()
.apply(shapely.geometry.Point),
crs="EPSG:4326",
).reset_index(drop=True)
locator = Nominatim(user_agent="pengMappingAgent", timeout=10)
df = df.join(df["geometry"].apply(lambda p: locator.reverse(f"{p.y}, {p.x}").raw["address"]).apply(pd.Series))
print(df.head(3).to_markdown(index=False))
df
输出
geometry
road
suburb
city
county
state
postcode
country
country_code
house_number
village
hamlet
town
region
locality
municipality
isolated_dwelling
neighbourhood
tourism
POINT (6.15665815595878 50.80372101501058)
A 4
Verlautenheide
Aachen
Städteregion Aachen
Nordrhein-Westfalen
52080
Deutschland
de
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
POINT (6.043073357781111 50.12805166279423)
Beieknapp
nan
nan
Canton Clervaux
nan
9962
Lëtzebuerg
lu
14
Holler
nan
nan
nan
nan
nan
nan
nan
nan
POINT (5.782417433300907 50.09032786722122)
nan
nan
nan
Bastogne
Luxembourg
6600
België / Belgique / Belgien
be
nan
Noville
Neufmoulin
Bastogne
Wallonie
nan
nan
nan
nan
nan
所以,我正在开发一个用于地理标记图像的地图应用程序,我想在我的地图上包含兴趣点的地址信息。我已经成功地使用 Geopandas、GeoPy 和 Nominatim 以及来自 PostGIS table 的点数据完成了大部分任务(例如 POINT Z (8.726176366993529 50.10868874301912 96.90000000000001)。
虽然脚本完成了我想要的大部分工作,但结果 returns 有很多无关信息,我想在更新数据库之前将其解析为一两个数据。我能够使用 gecoding and reverse geocoding 上的两篇文章破解我的脚本。我的问题归结为不确定脚本如何接收响应对象以及我如何在将属性添加到我的 Dataframe 之前或之后访问这些属性。
我没有import语句的代码如下:
conn = psycopg2.connect(
host="localhost",
database="Nizz0k",
user="Nizz0k",
password="")
sql = "select * from public.\"Peng\""
engine = create_engine('postgresql://Nizz0k@localhost:5432/public.\"Peng\"')
df = gpd.read_postgis(sql, conn, geom_col="geom")
df['lon'] = df.geometry.apply(lambda p: p.x)
df['lat'] = df.geometry.apply(lambda p: p.y)
df['geocode'] = df['lat'].map(str) + ', ' + df['lon'].map(str)
locator = Nominatim(user_agent="pengMappingAgent", timeout=10)
rgeocode = RateLimiter(locator.reverse, min_delay_seconds=0.001)
tqdm.pandas()
df['address'] = df['geocode'].progress_apply(rgeocode)
所以,我的 Python 知识非常有限,但我尝试访问新创建的 df['address']
列中的属性似乎没有任何效果。调用 df.head()
显示正确创建的列和地址信息,但现在我想简化列中的信息并将其部分提取到新列中。理想情况下,我想提取街道和门牌号信息以及社区信息,并删除城市、县、州和国家信息,因为它们是多余的。
根据我所做的研究,我应该能够从响应对象中提取此信息,但我不确定从何处或如何访问它。似乎此信息在我的专栏中被转换为字符串(我认为),如果没有,我不确定如何设置循环或 lambda 函数来获取这些内容。最坏的情况是,我假设只需一些字符串操作就可以实现我的目标,但似乎应该有更简单的方法。
- 显然我无法连接到您的数据库,因此模拟了一个 GeoDataFrame,这是一系列点
- 然后简化了调用 Nominatim 的代码
- raw returns a dict 这可以按照下面的代码提取
import geopandas as gpd
import shapely.geometry
from geopy.geocoders import Nominatim
import pandas as pd
gdf = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres"))
# a geodata frame with a few points...
df = gpd.GeoDataFrame(
geometry=gdf.loc[gdf["iso_a3"].eq("BEL"), "geometry"]
.apply(lambda p: p.exterior.coords)
.explode()
.apply(shapely.geometry.Point),
crs="EPSG:4326",
).reset_index(drop=True)
locator = Nominatim(user_agent="pengMappingAgent", timeout=10)
df = df.join(df["geometry"].apply(lambda p: locator.reverse(f"{p.y}, {p.x}").raw["address"]).apply(pd.Series))
print(df.head(3).to_markdown(index=False))
df
输出
geometry | road | suburb | city | county | state | postcode | country | country_code | house_number | village | hamlet | town | region | locality | municipality | isolated_dwelling | neighbourhood | tourism |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
POINT (6.15665815595878 50.80372101501058) | A 4 | Verlautenheide | Aachen | Städteregion Aachen | Nordrhein-Westfalen | 52080 | Deutschland | de | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan |
POINT (6.043073357781111 50.12805166279423) | Beieknapp | nan | nan | Canton Clervaux | nan | 9962 | Lëtzebuerg | lu | 14 | Holler | nan | nan | nan | nan | nan | nan | nan | nan |
POINT (5.782417433300907 50.09032786722122) | nan | nan | nan | Bastogne | Luxembourg | 6600 | België / Belgique / Belgien | be | nan | Noville | Neufmoulin | Bastogne | Wallonie | nan | nan | nan | nan | nan |