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

hvplot geo=True参数致UTM坐标错误映射为北半球纬度的问题

问题描述

我有一份澳大利亚北部海滩的栅格数据,采用该区域的UTM投影坐标系(56S)。使用hvplot.xarray扩展调用da.hvplot(x="x", y="y", geo=True)绘制时,geo=True参数会触发将y坐标(米)转换为经纬度坐标,但纬度被错误映射为北半球坐标,计算方式变成lat = 90 + (-y),而正确转换应该是lat = -y。请问geo=True触发的、将XY坐标推导为经纬度的是哪个函数?

用matplotlib绘制可正常显示。

目标

整体目标是将矢量数据(岸线)叠加到栅格数据(NDWI)之上。

软件版本

python==3.10.8

hvplot.__version__  # '0.8.2'
holoviews.__version__  # 1.15.3
可复现问题的最小完整代码
import cartopy.crs as ccrs
import geopandas as gpd
import geoviews as gv
import geoviews.tile_sources as gts
import holoviews as hv
import hvplot.xarray
import xarray as xr
import matplotlib.pyplot as plt

ndwi = xr.open_dataset(
    "https://s3.eu-central-1.amazonaws.com/floris.calkoen.open.data/narrabeen_ndwi_2023-01-24T00%3A02%3A21.tif",
    engine="rasterio",
)
shoreline = gpd.read_file(
    "https://s3.eu-central-1.amazonaws.com/floris.calkoen.open.data/narrabeen_shoreline_2023-01-24T00%3A02%3A21.geojson"
)

ndwi.rio.crs == shoreline.crs  ## 返回True

utm_zone = shoreline.crs.utm_zone
southern_hemisphere = True if utm_zone[-1] == "S" else False
utm_code = int(utm_zone[:-1])
utm_crs = ccrs.UTM(
    utm_code, southern_hemisphere
)  # 为什么cartopy.crs.UTM()不支持直接传入UTM带的字符串?

shoreline_plot = gv.Path([shoreline], crs=utm_crs)
ndwi_plot = ndwi["band_data"].squeeze().hvplot(x="x", y="y", geo=True, crs=utm_crs)

shoreline_plot * gts.EsriImagery  # 这个显示正常

ndwi_plot # 可以看到XY坐标从UTM 56S转换为纬度时被错误映射到北半球(计算方式为90 + (-y))

shoreline_plot * ndwi_plot  # 因此叠加无法正常显示

# matplotlib绘制代码
fig, ax = plt.subplots()
ndwi["band_data"].squeeze().plot(ax=ax)
shoreline.plot(ax=ax, color='black', linewidth=5, label="岸线")
plt.legend()
plt.show()
解答

当hvplot设置geo=True时,触发坐标转换的核心逻辑链是:

  1. hvplot调用Holoviews的GeoInterface标识地理数据类型;
  2. 最终通过Cartopy的cartopy.crs.Projection.transform_points()方法完成投影坐标到经纬度的转换。

你遇到的南半球UTM纬度偏移问题,是旧版本hvplot/Holoviews(你的0.8.2/1.15.3版本较老)的已知bug:传递南半球UTM参数时,部分逻辑遗漏了南半球标识,导致转换时默认按北半球计算,出现错误的纬度偏移。

修复方案

  • 优先升级依赖库:将hvplot升级到0.10.0+、Holoviews升级到1.17.0+,新版本已修复南半球UTM投影的转换问题。
  • 手动转换坐标(临时方案):如果无法升级,可提前用Cartopy完成坐标转换后再绘图:
# 手动将UTM坐标转为经纬度
x_coords, y_coords = ndwi.x.values, ndwi.y.values
# 从UTM 56S转换到WGS84经纬度
lon, lat, _ = utm_crs.transform_points(ccrs.PlateCarree(), x_coords, y_coords).T
# 为数据集添加经纬度坐标
ndwi_with_latlon = ndwi.assign_coords(lon=("x", lon), lat=("y", lat))

# 用经纬度坐标绘制
ndwi_plot = ndwi_with_latlon["band_data"].squeeze().hvplot(x="lon", y="lat", geo=True)
# 此时叠加岸线即可正常显示
shoreline_plot * ndwi_plot * gts.EsriImagery
  • 直接使用rasterio的CRS对象:尝试将crs参数改为ndwi.rio.crs(rasterio原生CRS对象),而非Cartopy构造的UTM对象,旧版本可能对原生CRS支持更好:
ndwi_plot = ndwi["band_data"].squeeze().hvplot(x="x", y="y", geo=True, crs=ndwi.rio.crs)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 23:30:52