使用GeoPandas填充DataFrame中缺失经纬度值的技术求助
用GeoPandas填充经纬度缺失值的完整实现
步骤1:导入依赖库
import pandas as pd import geopandas as gpd from geopandas.tools import geocode
步骤2:数据预处理(对应需求1、2)
先清理无效行,再筛选出需要填充的记录:
# 假设你的原始DataFrame名为df # 1. 删除地址列全为空的行 df = df.dropna(subset=['BOROUGH', 'ON STREET NAME', 'CROSS STREET NAME', 'OFF STREET NAME'], how='all') # 2. 筛选出经纬度为空或为0.0的行 to_fill = df.loc[(df['LATITUDE'].isna()) | (df['LATITUDE'] == 0.0) | (df['LONGITUDE'].isna()) | (df['LONGITUDE'] == 0.0)].copy()
步骤3:按优先级生成地址字符串(对应需求3)
按照BOROUGH > ON STREET NAME > CROSS STREET NAME > OFF STREET NAME的优先级拼接可使用的地址,确保地理编码的准确性:
def build_address(row): # 优先级1:行政区+主街道+交叉街道 if pd.notna(row['BOROUGH']) and pd.notna(row['ON STREET NAME']) and pd.notna(row['CROSS STREET NAME']): return f"{row['ON STREET NAME']} & {row['CROSS STREET NAME']}, {row['BOROUGH']}, New York" # 优先级2:行政区+主街道 elif pd.notna(row['BOROUGH']) and pd.notna(row['ON STREET NAME']): return f"{row['ON STREET NAME']}, {row['BOROUGH']}, New York" # 优先级3:行政区+非主街道 elif pd.notna(row['BOROUGH']) and pd.notna(row['OFF STREET NAME']): return f"{row['OFF STREET NAME']}, {row['BOROUGH']}, New York" # 优先级4:仅行政区 elif pd.notna(row['BOROUGH']): return f"{row['BOROUGH']}, New York" else: return None # 生成待编码的地址列 to_fill['address'] = to_fill.apply(build_address, axis=1) # 过滤掉仍无地址的行(理论上已被步骤1删除,做双重保险) to_fill = to_fill.dropna(subset=['address'])
步骤4:地理编码并填充经纬度(对应需求4)
使用GeoPandas调用Nominatim服务获取经纬度,再将结果回填到原始DataFrame:
# 地理编码,指定用户代理(避免被限制) geocoded = geocode(to_fill['address'], provider='nominatim', user_agent='nyc_collision_filler', timeout=10) # 将编码结果与待填充行合并 to_fill = to_fill.join(geocoded[['geometry']]) # 从geometry中提取经纬度 to_fill['LATITUDE'] = to_fill['geometry'].y to_fill['LONGITUDE'] = to_fill['geometry'].x # 将填充后的值更新回原始DataFrame df.update(to_fill[['LATITUDE', 'LONGITUDE']])
注意事项
- Nominatim服务有请求频率限制,若数据量较大,建议添加延迟或使用批量处理方式
- 部分地址可能无法被编码成功,可根据情况补充其他地理编码服务(如Google Maps Geocoding API,需API密钥)
- 处理前建议先对地址列做清洗(如去除多余空格、统一大小写),提升编码成功率
内容的提问来源于stack exchange,提问作者death_templar
相关产品推荐
相关产品推荐

