在这个降水图上显示两个水平颜色条,导致大的空白

问题描述

我正在使用 Metpy 制作精美的降水图。我认为这更像是一个 matplotlib 问题,但我对如何在该图中添加两个水平颜色条感到困惑。总体思路是在这张地图上显示雪和雨率,这是我通过在一个图形上使用两个轮廓填充来实现的。我想显示两个颜色条,因为我有两个单独的降雪率和降雨率。理想情况下,我希望两个颜色条水平并排。我得到的最接近的是让它们堆叠在一起,它们之间有很大的空间。这是我的草率代码

import metpy
from siphon.catalog import TDSCatalog
from datetime import datetime,timedelta
%matplotlib inline
import cartopy.crs as ccrs
import cartopy.feature as cfeature
from metpy.units import units
import metpy.calc as mpcalc
import matplotlib.pyplot as plt
import matplotlib.colors as cls
from xarray.backends import NetCDF4DataStore
import xarray as xr
from scipy.ndimage import gaussian_filter
import numpy as np

# Set up access via NCSS
gfs_catalog = ('http://thredds.ucar.edu/thredds/catalog/grib/NCEP/GFS/'
              'Global_0p5deg/catalog.xml?dataset=grib/NCEP/GFS/Global_0p5deg/Best')
cat = TDSCatalog(gfs_catalog)
ncss = cat.datasets[0].subset()
query3 = ncss.query()
query3.accept('netcdf')
query3.variables('Pressure_reduced_to_MSL_msl','Precipitation_rate_surface','SNow_depth_surface','Categorical_SNow_surface')
Now = datetime.utcNow()
query3.time_range(Now,Now + timedelta(days=4))
query3.lonlat_Box(west=-140,east=-60,north=60,south=20)
data3 = ncss.get_data(query3)
ds3 = xr.open_dataset(NetCDF4DataStore(data3))

#parsing data
isSNow_var = ds3.metpy.parse_cf('Categorical_SNow_surface')
precip_var = ds3.metpy.parse_cf('Precipitation_rate_surface')
longitude = precip_var.metpy.x
latitude = precip_var.metpy.y
time_index = 11

#All the Precip Stuff
precip_inch_hour = precip_var[time_index].squeeze() *  141.73228346457 
precip2 = mpcalc.smooth_n_point(precip_inch_hour,5,1)

#Converting to 10:1 sNow ratio
sNow_precip = (precip_inch_hour * isSNow_var[time_index].squeeze()) * 10

# Plot using cartopy and Matplotlib
mapproj = ccrs.LAmbertConformal(central_latitude=45.,central_longitude=-100.)

# Set projection of data
data_projection = ccrs.PlateCarree()

# Grab data for plotting state boundaries
states_provinces = cfeature.NaturalEarthFeature(
       category='cultural',name='admin_1_states_provinces_lakes',scale='50m',facecolor='none')

# Set extent and plot map lines
fig = plt.figure(1,figsize=(25.,25.))
ax = plt.subplot(111,projection=mapproj)
ax.set_extent([-125.,-70,25.,50.],ccrs.PlateCarree())
ax.coastlines('50m',edgecolor='black',linewidth=0.75)
ax.add_feature(states_provinces,linewidth=0.5)

#colormap data
precip_colors = [
   "#bde9bf",# 0.01 - 0.02 inches 1
   "#adddb0",# 0.02 - 0.03 inches 2
   "#9ed0a0",# 0.03 - 0.04 inches 3
   "#8ec491",# 0.04 - 0.05 inches 4
   "#7fb882",# 0.05 - 0.06 inches 5
   "#70ac74",# 0.06 - 0.07 inches 6
   "#60a065",# 0.07 - 0.08 inches 7
   "#519457",# 0.08 - 0.09 inches 8
   "#418849",# 0.09 - 0.10 inches 9
   "#307c3c",# 0.10 - 0.12 inches 10
   "#1c712e",# 0.12 - 0.14 inches 11
   "#f7f370",# 0.14 - 0.16 inches 12
   "#fbdf65",# 0.16 - 0.18 inches 13
   "#fecb5a",# 0.18 - 0.2 inches 14
   "#ffb650",# 0.2 - 0.3 inches 15
   "#ffa146",# 0.3 - 0.4 inches 16
   "#ff8b3c",# 0.4 - 0.5 inches 17
   "#ff8b3c"   # 0.5 - 0.6 inches 18
]

precip_colormap = cls.ListedColormap(precip_colors)

#Precip Rate
clev_precip =  np.concatenate((np.arange(0.01,0.1,.01),np.arange(.1,.2,.02),np.arange(.2,.61,.1)))
norm = cls.Boundarynorm(clev_precip,18)
cf = ax.contourf(longitude,latitude,precip2,clev_precip,cmap=precip_colormap,norm=norm,transform=ccrs.PlateCarree())
cb = plt.colorbar(cf,ticks=clev_precip,aspect=65,orientation = 'horizontal',shrink=0.6,pad=0.01)

sNow_colors = [
   "#63c9d5",# 0.1 - 0.2 inches 1
   "#5fb4ca",# 0.2 - 0.3 inches 2
   "#5a9fc0",# 0.3 - 0.4 inches 3
   "#558ab5",# 0.4 - 0.5 inches 4
   "#4e76aa",# 0.5 - 0.6 inches 5
   "#4763a0",# 0.6 - 0.7 inches 6
   "#3e4f95",# 0.7 - 0.8 inches 7
   "#353c8b",# 0.8 - 0.9 inches 8
   "#292980",# 0.9 - 1.0 inches 9
   "#493387",# 1.0 - 1.2 inches 10
   "#643e8e",# 1.2 - 1.4 inches 11
   "#7c4995",# 1.4 - 1.6 inches 12
   "#94559c",# 1.6 - 0.18 inches 13
   "#ab61a3",# 1.8 - 2 inches 14
   "#c36eaa",# 2 - 3 inches 15
   "#da7bb0",# 3 - 4 inches 16
   "#f288b7"   # 4 - 5 inches 17
]

sNow_colormap = cls.ListedColormap(sNow_colors)

#SNow Rate
clev_sNow =  np.concatenate((np.arange(.1,1,.1),np.arange(1,2,.2),np.arange(2,6,1)))
norm2 = cls.Boundarynorm(clev_sNow,17)
cf2 = ax.contourf(longitude,sNow_precip,clev_sNow,cmap=sNow_colormap,norm=norm2,transform=ccrs.PlateCarree())
cb2 = plt.colorbar(cf2,ticks=clev_sNow,pad=0.01,aspect=65)

#Valid Time
vtime = isSNow_var.metpy.time[time_index].values

#Title Info
plt.title('MSLP (hPa) with Highs and Lows,1000-500 hPa Thickness (m),Rain (in/hr),SNow 10:1 (in/hr)',loc='left')
plt.title(f'VALID: {vtime}',loc='right')

Example of Plot

我尝试过 subplots 和 gridSpec,但我一直遇到不同的障碍,当我尝试这些不同的方法时会遇到不同的错误。主要是我认为这与我对 Metpy、cartopy 和 Matplotlib 的入门级知识有关。欣赏对此问题的任何见解和可能的解决方案。谢谢!

解决方法

首先,感谢您以可重现的方式发布所有代码!

这看起来像是 subaxes 的解决方案。使用 fig.add_axes,您可以精确地创建子轴。

代替您的 cb 语句,我使用了以下两个块:

cax1 = fig.add_axes([0.15,0.25,0.3,0.02])
cb = fig.colorbar(cf,cax=cax1,orientation = 'horizontal')

cax2 = fig.add_axes([0.55,0.02])
cb2 = fig.colorbar(cf2,cax=cax2,orientation = 'horizontal')

这将创建两个并排的水平颜色条。这四个数字分别是左下角在x然后y中的位置和在x然后y中的大小,都是图形大小的比例。我没有在这台机器上工作,所以不得不使用随机数据,但这不应该影响你的结果:

side by side colorbars1

n.b.当您创建新轴时,对 plt.<function> 的任何调用都将默认使用最后创建的轴,在本例中为 cb2。出于这个原因,您应该使用 mantplotlib 的首选面向对象编程风格,因此使用 ax.set_title 而不是 plt.title

创建您的标题

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...