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

使用Basemap时迭代Pandas数据框及经纬度旋转保陆地位置问题

搞定经纬度旋转变换的两个问题:遍历Pandas数据框 + 修复while循环

一、用Basemap遍历Pandas数据框检查陆地属性

要逐个验证数据框里的经纬度点是否在陆地,结合Basemap的工具和Pandas的遍历方法很容易实现,给你两种常用方案:

方案1:用df.apply()批量处理(推荐,效率更高)

这种方式贴合Pandas的向量化思维,代码干净利落:

from mpl_toolkits.basemap import Basemap
import pandas as pd

# 先初始化Basemap实例,这里用圆柱投影(cyl),你可以根据需求换其他投影
m = Basemap(projection='cyl', llcrnrlat=-90, urcrnrlat=90, llcrnrlon=-180, urcrnrlon=180, resolution='l')

# 模拟你的数据框
df = pd.DataFrame({
    '原始经度': [116.4, 120.1, 100.5],
    '原始纬度': [39.9, 30.2, 25.0]
})

# 定义检查陆地的函数
def check_land(row):
    # 把经纬度转成Basemap的投影坐标(cyl投影下和原坐标一致,但养成好习惯总是对的)
    x, y = m(row['原始经度'], row['原始纬度'])
    # 用Basemap的is_land方法判断
    return m.is_land(x, y)

# 给数据框新增一列存检查结果
df['是否为陆地'] = df.apply(check_land, axis=1)

print(df)

方案2:用iterrows()逐行遍历(适合需要自定义操作的场景)

如果需要在遍历过程中同时做旋转变换这类操作,逐行循环更灵活:

for idx, row in df.iterrows():
    original_lon, original_lat = row['原始经度'], row['原始纬度']
    x, y = m(original_lon, original_lat)
    is_land = m.is_land(x, y)
    # 这里可以直接加旋转变换的代码,或者更新数据框
    df.at[idx, '是否为陆地'] = is_land

小贴士:数据量大的话,apply()比iterrows()快不少,优先选前者。


二、修复旋转变换的while循环问题

你说加了while循环后脚本出问题,十有八九是循环没设退出边界导致死循环,或者旋转后的坐标始终碰不到陆地。给你一个更稳的循环思路:

核心要点

  1. 一定要设最大迭代次数,避免无限跑
  2. 每次旋转后用Basemap检查是否在陆地
  3. 满足条件就退出,到次数还不行就返回原坐标(或者给提示)

示例代码

import numpy as np

# 先写个旋转变换函数,这里用平面旋转示例,你可以换成自己的球面旋转逻辑(建议用pyproj处理球面更准确)
def rotate_coords(original_lon, original_lat, angle):
    # 简化版:把经纬度转平面笛卡尔坐标
    x = original_lon * np.cos(np.radians(original_lat))
    y = original_lat
    # 旋转矩阵
    rot_matrix = np.array([[np.cos(np.radians(angle)), -np.sin(np.radians(angle))],
                           [np.sin(np.radians(angle)), np.cos(np.radians(angle))]])
    x_rot, y_rot = rot_matrix @ np.array([x, y])
    # 转回经纬度(简化版,实际球面旋转要复杂些)
    lon_rot = x_rot / np.cos(np.radians(y_rot))
    lat_rot = y_rot
    return lon_rot, lat_rot

# 循环旋转直到找到陆地坐标的函数
def rotate_until_land(original_lon, original_lat, max_iter=100, step_angle=5):
    current_lon, current_lat = original_lon, original_lat
    for i in range(max_iter):
        # 每次旋转角度递增(你也可以固定角度,或者随机角度,看需求)
        current_lon, current_lat = rotate_coords(original_lon, original_lat, step_angle * i)
        # 检查是否在陆地
        x, y = m(current_lon, current_lat)
        if m.is_land(x, y):
            return current_lon, current_lat
    # 到次数还没找到,给提示并返回原坐标
    print(f"警告:旋转{max_iter}次后仍没找到陆地坐标,返回原坐标")
    return original_lon, original_lat

# 把这个函数应用到整个数据框
df['旋转后经度'], df['旋转后纬度'] = zip(*df.apply(lambda row: rotate_until_land(row['原始经度'], row['原始纬度']), axis=1))

常见坑排查

  • 死循环:没设max_iter的话,要是原坐标在大洋中心,旋转一万次也碰不到陆地,脚本直接卡死,一定要加这个限制
  • 旋转逻辑不准:平面旋转适合小范围坐标,要是跨半球旋转,必须用球面旋转(比如用pyproj的Transformer做坐标转换),否则结果会离谱
  • 陆地判断不准:Basemap的is_land()分辨率由初始化时的resolution参数决定('l'是低分辨率,'h'是高分辨率),需要精确判断就调高点分辨率

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:13:49