如何为带地理地图的绘图设置正方形纵横比
解决6×6英寸正方形画布的地图散点图绘制问题
我尝试在世界地图上绘制散点图,希望将绘图设置为6英寸×6英寸的正方形。这需要调整地图的纵横比,但x轴最大值与最小值的差和y轴的差值不相等,增加了实现难度。以下是我目前的代码及生成的图。

import matplotlib.pyplot as plt from mpl_toolkits.axes_grid1 import make_axes_locatable from matplotlib.colors import Normalize import numpy as np import geopandas as gpd #==================================================================== y_pred = np.random.random((389, 28, 14)) world = gpd.read_file("ne_110m_land/ne_110m_land.shp") min_lat = 19.25 max_lat = -5.75 min_lon = 18.5 max_lon = 31.5 lat = np.tile(np.arange(max_lat, min_lat-0.5, -0.5).reshape(-1, 1), (1, int(max_lon - min_lon+1))) lon = np.tile(np.arange(min_lon, max_lon+1, 1).reshape(1, -1), (int((max_lat - min_lat)*2)+1, 1)) #==================================================================== ''' Plot map ''' norm = Normalize(vmin=0, vmax=max(y_pred.ravel())) fig_map, ax_map = plt.subplots(1,1,figsize=(6,6), dpi=100, tight_layout=True) fig_map.set_size_inches(6, 6) map = ax_map.scatter(x=lon, y=lat, c=y_pred[date_idx], s=4, cmap='bwr', norm=norm) world.plot(ax=ax_map, facecolor='none', edgecolor='black', linewidth=.5, alpha=1) divider = make_axes_locatable(ax_map) cax = divider.append_axes("right", size="5%", pad=0.05) plt.colorbar(map, cax=cax) ax_map.set_xlim(-20, 60) ax_map.set_ylim(-20, 20) ax_map.set_aspect('equal') plt.show() fig_map.savefig('test.png', bbox_inches='tight', pad_inches=0)
问题根源
当前代码中ax_map.set_aspect('equal')强制坐标轴等比例,但x轴跨度为80(-20到60)、y轴跨度为40(-20到20),比例不匹配6×6的正方形画布,导致地图被挤压变形,无法填满画布。
修改方案
方案1:适配画布比例(允许地图轻微变形)
去掉强制等比例设置,让Matplotlib自动适配6×6画布的尺寸,同时完整显示目标区域:
import matplotlib.pyplot as plt from mpl_toolkits.axes_grid1 import make_axes_locatable from matplotlib.colors import Normalize import numpy as np import geopandas as gpd y_pred = np.random.random((389, 28, 14)) world = gpd.read_file("ne_110m_land/ne_110m_land.shp") min_lat = 19.25 max_lat = -5.75 min_lon = 18.5 max_lon = 31.5 lat = np.tile(np.arange(max_lat, min_lat-0.5, -0.5).reshape(-1, 1), (1, int(max_lon - min_lon+1))) lon = np.tile(np.arange(min_lon, max_lon+1, 1).reshape(1, -1), (int((max_lat - min_lat)*2)+1, 1)) # 绘图部分 norm = Normalize(vmin=0, vmax=max(y_pred.ravel())) # 仅设置一次画布尺寸即可 fig_map, ax_map = plt.subplots(1,1,figsize=(6,6), dpi=100, tight_layout=True) # 替换未定义的date_idx为具体索引,示例用0 map = ax_map.scatter(x=lon, y=lat, c=y_pred[0], s=4, cmap='bwr', norm=norm) world.plot(ax=ax_map, facecolor='none', edgecolor='black', linewidth=.5, alpha=1) divider = make_axes_locatable(ax_map) cax = divider.append_axes("right", size="5%", pad=0.05) plt.colorbar(map, cax=cax) ax_map.set_xlim(-20, 60) ax_map.set_ylim(-20, 20) # 取消强制等比例,自动适配画布 ax_map.set_aspect('auto') plt.show() fig_map.savefig('test.png', bbox_inches='tight', pad_inches=0)
方案2:保持地理比例(无变形)
调整x轴范围,让x/y轴跨度比等于画布宽高比(1:1),同时确保目标区域完整显示:
# ... 其他代码不变 ax_map.set_xlim(0, 40) # 跨度40,和y轴跨度一致 ax_map.set_ylim(-20, 20) ax_map.set_aspect('equal') # ... 其他代码不变
内容的提问来源于stack exchange,提问作者Innocuous Rift
相关产品推荐
相关产品推荐

