手把手教你用Python计算31省省会地理距离矩阵(附完整代码与数据)

张开发
2026/4/3 19:35:39 15 分钟阅读
手把手教你用Python计算31省省会地理距离矩阵(附完整代码与数据)
用Python构建中国省会城市地理距离矩阵从原理到实战当你需要研究区域经济关联、疫情传播规律或交通网络优化时地理距离矩阵是不可或缺的基础数据。但现成的数据集往往收费不菲或者格式不符合需求。本文将带你从零开始用Python实现一套完整的解决方案不仅能生成基础距离矩阵还能根据研究需求灵活调整。1. 准备工作理解地理距离计算的核心逻辑在开始编码前我们需要明确几个关键概念。地理距离计算不同于平面几何中的直线距离因为地球是一个近似的球体。最常用的方法是大圆距离公式Great-circle distance它计算的是球面上两点之间的最短路径。1.1 大圆距离公式详解大圆距离的数学表达式为distance R × arccos[sin(φ₁) × sin(φ₂) cos(φ₁) × cos(φ₂) × cos(Δλ)]其中R 是地球半径平均约6371公里φ₁, φ₂ 分别是两点的纬度弧度制Δλ 是两点经度之差弧度制这个公式考虑了地球曲率比简单的平面距离公式更精确。在实际应用中我们还需要注意经纬度需要从度转换为弧度当两点非常接近时arccos可能导致计算不稳定国际通用的地球半径是6371公里但不同标准可能略有差异1.2 Python工具链选择我们将使用以下Python库构建解决方案import pandas as pd # 数据处理 import numpy as np # 矩阵运算 from math import radians, sin, cos, sqrt, atan2 # 数学计算这些库的组合既轻量又强大能够高效处理地理计算任务。相比专业GIS软件Python方案更灵活便于集成到数据分析流程中。2. 数据收集与清洗构建城市坐标数据库可靠的数据是准确计算的基础。中国省会城市的经纬度数据可以从多个公开来源获取但需要注意数据质量和格式统一。2.1 获取城市坐标数据推荐的数据来源包括国家地理信息公共服务平台开源地理数据库如GeoNames学术论文中的补充材料一个典型的城市坐标数据结构如下city_coords { 北京: [116.40, 39.90], 上海: [121.47, 31.23], 广州: [113.26, 23.12], # 其他城市数据... }2.2 数据预处理要点处理坐标数据时需要注意单位统一确保所有经度、纬度都使用十进制度表示数据完整检查是否有缺失值或明显错误如纬度超过90度城市名称标准化使用一致的命名规范便于后续匹配我们可以用pandas将这些数据转换为更易处理的DataFrame格式df_coords pd.DataFrame.from_dict(city_coords, orientindex, columns[经度, 纬度])3. 核心算法实现高效计算距离矩阵有了干净的数据我们就可以实现距离计算的核心逻辑。为了提高效率我们将使用向量化操作而非循环。3.1 改进的距离计算函数传统的双重循环方法虽然直观但在Python中效率较低。我们可以利用numpy的广播机制进行优化def haversine_vectorized(df, earth_radius6371): 使用向量化方法计算城市间距离矩阵 参数: df - 包含经度、纬度的DataFrame earth_radius - 地球半径(km) 返回: 距离矩阵(km) # 将度转换为弧度 lat np.radians(df[纬度].values) lon np.radians(df[经度].values) # 创建所有城市对的组合 i, j np.meshgrid(np.arange(len(df)), np.arange(len(df))) # 计算经纬度差 dlat lat[j] - lat[i] dlon lon[j] - lon[i] # 应用Haversine公式 a np.sin(dlat/2)**2 np.cos(lat[i]) * np.cos(lat[j]) * np.sin(dlon/2)**2 c 2 * np.arcsin(np.sqrt(a)) return earth_radius * c这个向量化实现比双重循环快10-100倍特别适合处理大量城市数据。3.2 生成衍生矩阵在空间计量经济学中除了原始距离矩阵还常用到两种变体倒数矩阵每个元素为距离的倒数1/d平方倒数矩阵每个元素为距离平方的倒数1/d²我们可以轻松从基础距离矩阵生成这些变体distance_matrix haversine_vectorized(df_coords) inverse_matrix 1 / distance_matrix inverse_square_matrix 1 / (distance_matrix ** 2) # 将对角线设为0城市到自身的距离无意义 np.fill_diagonal(inverse_matrix, 0) np.fill_diagonal(inverse_square_matrix, 0)4. 结果输出与应用保存与可视化计算完成后我们需要将结果保存为可共享的格式并进行初步可视化检查。4.1 数据导出使用pandas可以方便地将矩阵导出为Excel或CSVdef save_matrices(distance, inverse, inverse_square, filename): 将三个矩阵保存到Excel的不同工作表 with pd.ExcelWriter(filename) as writer: pd.DataFrame(distance).to_excel(writer, sheet_name原始距离) pd.DataFrame(inverse).to_excel(writer, sheet_name距离倒数) pd.DataFrame(inverse_square).to_excel(writer, sheet_name距离平方倒数)4.2 矩阵可视化简单的热图可以帮助我们快速检查矩阵的合理性import matplotlib.pyplot as plt import seaborn as sns plt.figure(figsize(10, 8)) sns.heatmap(distance_matrix, annotFalse, cmapviridis, xticklabelsdf_coords.index, yticklabelsdf_coords.index) plt.title(城市间距离矩阵热图) plt.tight_layout() plt.show()5. 高级应用与优化技巧掌握了基础实现后我们可以进一步优化算法并扩展应用场景。5.1 性能优化策略对于大规模计算如全国所有地级市可以考虑并行计算使用multiprocessing或joblib并行处理近似算法对于不需要极高精度的场景可以使用更简单的公式稀疏矩阵当只关心近距离城市时使用稀疏矩阵存储5.2 常见问题排查实际应用中可能遇到的问题及解决方案问题1计算结果明显偏大或偏小检查确认经纬度单位是否正确应为十进制度而非度分秒问题2矩阵对角线不为零解决在计算后显式设置对角线元素np.fill_diagonal(matrix, 0)问题3部分城市距离异常排查检查这些城市的坐标数据是否录入错误5.3 扩展应用场景这套方法可以轻松扩展到其他分析需求交通网络规划结合OD流量数据优化路线区域经济研究分析经济指标的时空相关性疫情传播建模构建基于距离的传播概率矩阵6. 完整代码实现以下是整合了所有功能的完整实现import pandas as pd import numpy as np from math import radians, sin, cos, sqrt, atan2 import matplotlib.pyplot as plt import seaborn as sns def load_city_coords(filepath): 从CSV/Excel加载城市坐标数据 if filepath.endswith(.csv): return pd.read_csv(filepath, index_col0) elif filepath.endswith((.xlsx, .xls)): return pd.read_excel(filepath, index_col0) else: raise ValueError(不支持的文件格式) def haversine_vectorized(df, earth_radius6371): 向量化Haversine距离计算 lat np.radians(df[纬度].values) lon np.radians(df[经度].values) i, j np.meshgrid(np.arange(len(df)), np.arange(len(df))) dlat lat[j] - lat[i] dlon lon[j] - lon[i] a np.sin(dlat/2)**2 np.cos(lat[i]) * np.cos(lat[j]) * np.sin(dlon/2)**2 c 2 * np.arcsin(np.sqrt(a)) distances earth_radius * c np.fill_diagonal(distances, 0) return distances def generate_derived_matrices(distance_matrix): 生成倒数矩阵和平方倒数矩阵 inverse 1 / distance_matrix inverse_square 1 / (distance_matrix ** 2) np.fill_diagonal(inverse, 0) np.fill_diagonal(inverse_square, 0) return inverse, inverse_square def visualize_matrix(matrix, cities, title距离矩阵): 绘制矩阵热图 plt.figure(figsize(12, 10)) sns.heatmap(matrix, cmapviridis, xticklabelscities, yticklabelscities) plt.title(title) plt.tight_layout() plt.show() def save_matrices(distance, inverse, inverse_square, filename): 保存多个矩阵到Excel文件 with pd.ExcelWriter(filename) as writer: pd.DataFrame(distance, indexcity_names, columnscity_names).to_excel(writer, 原始距离) pd.DataFrame(inverse, indexcity_names, columnscity_names).to_excel(writer, 距离倒数) pd.DataFrame(inverse_square, indexcity_names, columnscity_names).to_excel(writer, 距离平方倒数) # 主程序 if __name__ __main__: # 加载数据 df_coords load_city_coords(china_cities_coords.xlsx) city_names df_coords.index.tolist() # 计算矩阵 distance_matrix haversine_vectorized(df_coords) inverse_matrix, inverse_square_matrix generate_derived_matrices(distance_matrix) # 可视化 visualize_matrix(distance_matrix, city_names) # 保存结果 save_matrices(distance_matrix, inverse_matrix, inverse_square_matrix, china_city_distances.xlsx)这套代码提供了从数据加载到结果输出的完整流程你可以根据自己的需求调整参数或扩展功能。比如添加城市筛选功能或者集成到更大的分析流程中。

更多文章