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

如何调整添加Basemap的xarray分面图列间距

xarray分面图叠加Basemap底图列间距过大解决方案

问题根源

列间距无法通过subplots_adjust、tight_layout调整的核心原因有两个:

  • Basemap初始化绑定子图时,会强制将坐标轴设置为固定等宽高比(aspect='equal'),和xarray FacetGrid默认的自适应布局逻辑冲突,matplotlib会自动为等比轴补充留白,覆盖手动设置的wspace参数
  • 手动添加的独立colorbar轴会干扰tight_layout的自动排版计算,导致系统为了给colorbar腾位置主动拉开子图列间距

修复步骤

  • 提前计算研究区的经纬度宽高比,在创建xarray分面图时就通过aspect、subplot_kws参数锁定子图宽高比,避免Basemap初始化时修改轴属性撑乱布局
  • 在创建分面网格的阶段就通过gridspec_kw传入间距参数,这个参数的优先级高于事后调用subplots_adjust,不会被固定aspect的轴覆盖
  • 调用tight_layout时传入rect参数,提前给右侧colorbar预留固定位置,告诉排版系统不要调整该区域内的子图布局
  • 清空子图默认的经纬度刻度,避免刻度标签占用额外空间产生不必要的留白

修正后代码

import pickle
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import colors
from mpl_toolkits.basemap import Basemap
import xarray as xr

# 读取本地测试数据
with open('/data/direcotory/test_data.pkl', "rb") as f:
    ds_sub = pickle.load(f)

plt.close("all")

# 提前提取研究区边界,计算地图实际宽高比
lon_min, lon_max = ds_sub['lon'].min().item(), ds_sub['lon'].max().item()
lat_min, lat_max = ds_sub['lat'].min().item(), ds_sub['lat'].max().item()
map_aspect = (lon_max - lon_min) / (lat_max - lat_min)
lon_0 = ds_sub['lon'].mean().item()
lat_0 = ds_sub['lat'].mean().item()

# 计算色标分级
levels = np.arange(0, ds_sub['sum'].quantile(0.99),
                   (ds_sub['sum'].quantile(0.99) / 10)).tolist()
norm = colors.BoundaryNorm(levels, len(levels))

# 创建分面图时直接锁定布局参数
p = ds_sub['sum'].loc[[0, 3, 6, 9], :, :].plot(
    add_colorbar=False,
    row='time',
    cmap='OrRd',
    col_wrap=2,
    norm=norm,
    aspect=map_aspect,
    figsize=(8, 10),
    subplot_kws={"aspect": map_aspect},
    gridspec_kw={"hspace": 0.05, "wspace": 0.02}  # 网格初始化时直接设间距
)

# 添加独立色标
mappable = p.axes.flat[0].collections[0]
cax = p.fig.add_axes([0.88, 0.2, 0.03, 0.6])
cbar = plt.colorbar(
    mappable,
    ticks=levels,
    values=levels,
    cax=cax,
    orientation='vertical'
)
cbar.ax.tick_params(labelsize=14)

# 逐子图叠加Basemap底图
for ax in p.axes.flatten():
    # 清空默认轴标签和刻度,避免额外留白
    ax.set_xlabel('')
    ax.set_ylabel('')
    ax.set_xticks([])
    ax.set_yticks([])
    ax.margins(0, 0)

    m = Basemap(
        resolution='f',
        lat_ts=20,
        lat_0=lat_0,
        lon_0=lon_0,
        llcrnrlon=lon_min,
        llcrnrlat=lat_min,
        urcrnrlon=lon_max,
        urcrnrlat=lat_max,
        ax=ax,
        fix_aspect=True  # 锁定宽高比不自动调整
    )
    m.drawmapboundary(linewidth=0.5)
    m.drawrivers(linewidth=0.3)
    m.drawcoastlines(linewidth=0.5)
    m.drawcountries(linewidth=0.5)
    m.drawstates(linewidth=0.3)
    point_lon, point_lat = m(51.534817, 25.286106)

# 最后微调布局,rect参数指定子图排版区域为画布左0到右85%的位置,给色标留空间
plt.tight_layout(rect=[0, 0, 0.85, 1], pad=0.1)
plt.show()

效果说明

调整后子图列间距可以稳定控制在wspace设定的数值,不会被Basemap或者colorbar挤开,行间距也可以通过hspace参数按需调整。如果需要更紧凑的效果,直接把gridspec_kw里的wspace设为0即可。


内容的提问来源于stack exchange,提问作者Seyed Omid Nabavi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 23:51:35