Pandas DataFrame基于经纬度计算两点距离调用自定义函数报错如何解决
问题描述
我有一个如下图所示的Python dataframe:
其中包含实际邮政编码及对应的经纬度信息,我想要计算postcode_x到postcode_y之间的距离
我编写了如下Python函数:
def distance(lat_1,lon_1,lat_2,lon_2): R = 6373.0 # 地球半径 lat1 = math.radians(lat_1) lon1 = math.radians(lon_1) lat2 = math.radians(lat_1) lon2 = math.radians(lon_2) dlon = lon2 - lon1 dlat = lat2 - lat1 a = math.sin(dlat / 2)**2 + math.cos(lat1) * math.cos(lat2) * math.sin(dlon / 2)**2 # 哈弗辛公式 c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a)) distance = R * c
单独调用该函数时运行正常:
lat_1 =52.2296756 lon_1 =21.0122287 lat_2 = 52.406374 lon_2 = 16.9251681 distance(lat_1,lon_1,lat_2,lon_2) # 输出结果为 278.40645089544114
但是当我尝试调用该函数为DataFrame生成新列时:
result['distance']=distance(result['LATITUDE_x'],result['LONGITUDE_x'],result['LATITUDE_y'],result['LONGITUDE_y'])
返回如下报错:
TypeError: cannot convert the series to <class 'float'> TypeError: cannot convert the series to <class 'float'> --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-56-44558335aa06> in <module> ----> 1 result['distance']=distance(result['LATITUDE_x'].astype(np.float),result['LONGITUDE_x'].astype(np.float),result['LATITUDE_y'].astype(np.float),result['LONGITUDE_y'].astype(np.float)) 2 result <ipython-input-53-4dddb160b896> in distance(lat_1, lon_1, lat_2, lon_2) 4 5 ----> 6 lat1 = math.radians(lat_1) 7 # coordinates 8 c:\python\python 3.95\lib\site-packages\pandas\core\series.py in wrapper(self) 139 if len(self) == 1: 140 return converter(self.iloc[0]) --> 141 raise TypeError(f"cannot convert the series to {converter}") 142 143 wrapper.__name__ = f"__{converter.__name__}__" TypeError: cannot convert the series to <class 'float'>
我已经尝试了以下解决方案:
result['distance']=distance(result['LATITUDE_x'].astype(np.float32),result['LONGITUDE_x'].astype(np.float32),result['LATITUDE_y'].astype(np.float32),result['LONGITUDE_y'].astype(np.float32))- 将
np.float32替换为astype(float),两种方法都返回相同报错。
解决方案
报错原因有两个:
- 内置
math库的函数仅支持处理单个浮点数值,你直接传入整列pandas Series数组自然无法识别 - 你编写的函数存在笔误:
lat2 = math.radians(lat_1)错误调用了第一个纬度参数,需要修改为lat2 = math.radians(lat_2),否则计算结果全部错误
两种常用修复方案如下:
方案1:逐行调用(代码改动最小,适合小数据量)
不需要修改原有函数,调用时用apply逐行传参即可:
result['distance'] = result.apply(lambda row: distance(row['LATITUDE_x'], row['LONGITUDE_x'], row['LATITUDE_y'], row['LONGITUDE_y']), axis=1)
方案2:向量运算版本(性能更高,适合大数据量)
把所有math库函数替换为numpy的对应函数,即可直接传入整列计算,速度远高于逐行调用:
import numpy as np def distance_vec(lat_1, lon_1, lat_2, lon_2): R = 6373.0 lat1 = np.radians(lat_1) lon1 = np.radians(lon_1) lat2 = np.radians(lat_2) lon2 = np.radians(lon_2) dlon = lon2 - lon1 dlat = lat2 - lat1 a = np.sin(dlat / 2)**2 + np.cos(lat1) * np.cos(lat2) * np.sin(dlon / 2)**2 c = 2 * np.arctan2(np.sqrt(a), np.sqrt(1 - a)) return R * c # 直接调用即可生成新列 result['distance'] = distance_vec(result['LATITUDE_x'],result['LONGITUDE_x'],result['LATITUDE_y'],result['LONGITUDE_y'])
内容的提问来源于stack exchange,提问作者deepankar srigyan
相关产品推荐
相关产品推荐

