You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas DataFrame基于经纬度计算两点距离调用自定义函数报错如何解决

问题描述

我有一个如下图所示的Python dataframe:
enter image description here
其中包含实际邮政编码及对应的经纬度信息,我想要计算postcode_x到postcode_y之间的距离
dataframe format

我编写了如下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'>

我已经尝试了以下解决方案:

  1. 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))
  2. 将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 14:36:05