使用GeoPandas计算地址间距离时遇TypeError问题求助
排查步骤及解决方案
1. 检查经纬度数据类型
TypeError最常见的触发原因是经纬度列不是数值类型。先确认DataFrame中lat和lon列的类型:
print(df[['lat', 'lon']].dtypes)
如果输出为object(字符串类型),先转换为数值:
df['lat'] = pd.to_numeric(df['lat'], errors='coerce') df['lon'] = pd.to_numeric(df['lon'], errors='coerce')
转换后检查缺失值(无法转换的内容会被转为NaN),并处理:
# 查看缺失值数量 print(df[['lat', 'lon']].isna().sum()) # 删除含缺失值的行 df = df.dropna(subset=['lat', 'lon'])
2. 确认Shapely Point的参数顺序
Shapely的Point构造函数要求参数顺序为**(经度, 纬度)**(x轴对应经度,y轴对应纬度),如果搞反成(纬度, 经度),不仅会导致距离计算错误,若目标地址与DataFrame中Point的参数顺序不一致,也可能触发类型相关的隐性错误。
正确创建Point的方式:
from shapely.geometry import Point # 目标地址:经度在前,纬度在后 target_point = Point(target_lon, target_lat) # DataFrame中批量创建Point df['point'] = df.apply(lambda row: Point(row['lon'], row['lat']), axis=1)
3. 验证目标地址的Point对象有效性
确保target_address是有效的shapely.geometry.Point实例,而非字符串、元组等其他类型:
# 错误示例:传入非Point类型 target_address = "34.0522, -118.2437" # 字符串 target_address = (34.0522, -118.2437) # 元组 # 正确示例 target_lon = -118.2437 target_lat = 34.0522 target_address = Point(target_lon, target_lat)
4. 正确计算地理英里距离
Shapely原生的distance()方法计算的是平面笛卡尔距离,并非真实地理距离。要得到英里数,需用地理坐标系计算球面距离:
方法一:用geopy(简洁直观)
from geopy.distance import geodesic # 目标地址以(纬度, 经度)元组传入 target_coords = (target_lat, target_lon) # 批量计算英里距离 df['distance_miles'] = df.apply(lambda row: geodesic(target_coords, (row['lat'], row['lon'])).miles, axis=1)
方法二:用pyproj+shapely(自定义性更强)
from pyproj import Geod from shapely.geometry import Point # 使用WGS84椭球体 geod = Geod(ellps='WGS84') def calc_miles(target_point, row_point): # 计算米距后转换为英里 _, _, dist_meters = geod.inv(target_point.x, target_point.y, row_point.x, row_point.y) return dist_meters * 0.000621371 df['distance_miles'] = df['point'].apply(lambda p: calc_miles(target_address, p))
5. 定位具体错误行
若以上步骤仍未解决问题,添加调试代码找到触发错误的具体数据行:
def safe_create_point(row): try: return Point(row['lon'], row['lat']) except TypeError as e: print(f"错误行索引: {row.name} | 错误信息: {e}") print(f"纬度值/类型: {row['lat']} | {type(row['lat'])}") print(f"经度值/类型: {row['lon']} | {type(row['lon'])}") return None df['point'] = df.apply(safe_create_point, axis=1)
内容的提问来源于stack exchange,提问作者user3476463
相关产品推荐
相关产品推荐

