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

基于Haversine公式计算房屋与餐厅全量坐标配对距离的实现方案

错误原因梳理

  • 循环写法错误:ll.append(rows(float(dist))) 中rows是DataFrame遍历得到的Series对象,加括号会被识别为函数调用,触发Series object is not callable报错,直接追加距离值或关联信息即可。
  • apply写法错误:lambda内传入的是完整的df1['Latitude']等Series对象而非当前行的单个经纬度值,同时axis=1被错误放在haversine的参数括号内,导致返回的是Series无法转float。
  • zip写法错误:zip仅会按索引位置一一配对两个DataFrame的行,无法生成所有两两组合的笛卡尔积,所以结果数量远小于预期。

小规模数据正确实现

适合小数据量验证逻辑,直接生成笛卡尔积后调用距离函数:

import pandas as pd
import math

# 你的haversine函数,返回单位为km,要米的话把radius改成6371*1000即可
def haversine(lat1, lon1, lat2, lon2):
    radius = 6371 
    dlat = math.radians(lat2-lat1)
    dlon = math.radians(lon2-lon1)
    a = math.sin(dlat/2) * math.sin(dlat/2) + math.cos(math.radians(lat1)) \
        * math.cos(math.radians(lat2)) * math.sin(dlon/2) * math.sin(dlon/2)
    c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a))
    d = radius * c
    return d

# 方法1:修正后的双重循环
ll = []
for _, rest_row in df2.iterrows():
    rest_lat, rest_lon = rest_row['Latitude'], rest_row['Longitude']
    for _, house_row in df1.iterrows():
        house_lat, house_lon = house_row['Latitude'], house_row['Longitude']
        dist = haversine(house_lat, house_lon, rest_lat, rest_lon)
        # 可按需存储房屋ID、餐厅ID、距离,方便后续分析
        ll.append({
            'house_id': house_row.get('id', _), # 有实际ID字段替换成对应列名即可
            'restaurant_id': rest_row.get('id', _),
            'distance_km': dist
        })
result_df = pd.DataFrame(ll)

# 方法2:笛卡尔积+行处理,比双重循环效率更高
# 生成所有两两组合
df1['tmp_key'] = 0
df2['tmp_key'] = 0
cross_df = pd.merge(df1, df2, on='tmp_key').drop('tmp_key', axis=1)
# 逐行计算距离
cross_df['distance_km'] = cross_df.apply(lambda x: haversine(x['Latitude_x'], x['Longitude_x'], x['Latitude_y'], x['Longitude_y']), axis=1)

大规模数据(10万房屋+2480餐厅)高性能实现

10万*2480的计算量约2.48亿次,普通Python循环/逐行apply性能极低,推荐用numpy向量化计算,速度可提升百倍以上:

import numpy as np

# 向量化版haversine,支持数组批量输入
def haversine_vectorized(lat1, lon1, lat2, lon2):
    R = 6371.0
    lat1, lon1, lat2, lon2 = map(np.radians, [lat1, lon1, lat2, lon2])
    dlat = lat2[:, None] - lat1
    dlon = lon2[:, None] - lon1
    a = np.sin(dlat/2)**2 + np.cos(lat1) * np.cos(lat2[:, None]) * np.sin(dlon/2)**2
    c = 2 * np.arctan2(np.sqrt(a), np.sqrt(1-a))
    return R * c # 返回shape为(餐厅数量, 房屋数量)的数组,单位为km

# 提取经纬度数组
house_lats = df1['Latitude'].values
house_lons = df1['Longitude'].values
rest_lats = df2['Latitude'].values
rest_lons = df2['Longitude'].values

# 一次性计算所有两两距离
dist_matrix = haversine_vectorized(house_lats, house_lons, rest_lats, rest_lons)
# dist_matrix[i][j] 即为第i个餐厅到第j个房屋的距离

如果需要转成结构化的长表,直接reshape即可:

result_df = pd.DataFrame({
    'restaurant_idx': np.repeat(np.arange(len(df2)), len(df1)),
    'house_idx': np.tile(np.arange(len(df1)), len(df2)),
    'distance_km': dist_matrix.flatten()
})

内容的提问来源于stack exchange,提问作者amanda

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 22:00:02