【问题标题】:How parse address components returned by Nominatim reverse geocoding?如何解析 Nominatim 反向地理编码返回的地址组件?
【发布时间】:2022-01-04 17:41:53
【问题描述】:

所以,我正在开发一个用于地理标记图像的地图应用程序,我希望在我的地图上包含兴趣点的地址信息。我已经成功地使用 Geopandas、GeoPy 和 Nominatim 以及 PostGIS 表中的点数据完成了大部分任务(例如 POINT Z (8.726176366993529 50.10868874301912 96.90000000000001)。

虽然脚本完成了我想要的大部分工作,但结果返回了大量无关信息,我想在更新我的数据库之前将其解析为一两条数据。我能够使用gecodingreverse geocoding 上的两篇文章来破解我的脚本。我的问题归结为不确定脚本如何接收响应对象以及如何在属性添加到我的数据框之前或之后访问它们。

我没有导入语句的代码如下:

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 函数来获取这些内容。最坏的情况,我认为只是一些字符串操作可能会实现我的目标,但似乎应该有更简单的方法。

【问题讨论】:

  • 1) 您是否使用OSMPythonTools、GeoPy 或其他方法进行查询? 2) 你能include the input data in your question?我们无权访问你的SQL服务器吗。
  • 所以,它只是 GeoPy,我提供了表中数据的示例,但它是 WGS84 中具有 x、y、z 的有效几何。

标签: python geopandas geopy nominatim


【解决方案1】:
  • 显然我无法连接到您的数据库,因此模拟了一个由一系列点组成的 GeoDataFrame
  • 然后简化了调用 Nominatim 的代码
  • raw 返回一个 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

【讨论】:

  • 嗨,Rob,感谢您的回答,但也许我的问题并不清楚。我已成功执行反向地理编码。我得到了我期望的结果,但我的问题是如何进一步解析和细化返回的地址信息。我只想把街道+门牌号和邻里信息解析出来。
  • 啊,对不起,我之前浏览了你的答案。所以,你说返回的信息是一个字符串,但我知道我想要的信息在单个示例中作为一个对象返回。我假设在这种情况下,将信息转换为字符串并将其添加到数据框中的是代码本身。因此,我需要使用逗号分隔的字符串,或者将其重写为某种循环来提取我想要的信息。
  • 我已更新 - 调查了 raw 属性,它是一个字典。要提出一个得到您想要的问题,请提供您尝试过的 MWE,该 MWE 不依赖于 SO 响应者无法访问的基础架构
  • 所以,这就是我所意识到的:我需要将其编写为脚本来从 location.raw 对象中提取数据并循环它。我可以在一个案例中做我想做的事,这是让我绊倒的循环
  • 我已经在apply() 中完成了。您的代码段没有意义,tqdmprogress_apply() 不是 pandas / geopandas 方法......另外你在哪里批量调用反向地理编码? apply(pd.Series) 的全部意义在于它在此上下文中将 dict 扩展到列
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多