如何调整 xarray 图中的 Matplotlib colorbar 范围?
How to adjust Matplotlib colorbar range in xarray plot?
我有一个看起来像这样的情节
我无法理解如何手动更改或设置颜色条的数据值范围。我想根据图中显示的数据值试验范围,并将颜色条更改为 (-4,4)。我看到 plt.clim
、vmin
和 vmax
是可能使用的函数。
这是我的代码:
import cdsapi
import xarray as xr
import matplotlib.pyplot as plt
import numpy as np
import cartopy.crs as ccrs
# Also requires cfgrib library.
c = cdsapi.Client()
url = c.retrieve(
'reanalysis-era5-single-levels-monthly-means',
{
'product_type': 'monthly_averaged_reanalysis',
'format': 'grib',
'variable': ['100m_u_component_of_wind','100m_v_component_of_wind'],
'year': ['2006','2007','2008','2009','2010','2011','2012','2013','2014','2015','2016','2017','2018','2019','2020','2021'],
'month': ['01','02','03','04','05','06','07','08','09','10','11','12'],
'time': '00:00',
'grid': [0.25, 0.25],
'area': [70.00, -180.00, -40.00, 180.00],
},
"C:\Users\U321103\.spyder-py3\ERA5_MAPPING\100m_wind_U_V.grib")
path = "C:\Users\U321103\.spyder-py3\ERA5_MAPPING\100m_wind_U_V.grib"
ds = xr.load_dataset(path, engine='cfgrib')
wind_abs = np.sqrt(ds.u100**2 + ds.v100**2)
monthly_means = wind_abs.mean(dim='time')
wind_abs_clim = wind_abs.sel(time=slice('2006-01','2020-12')).groupby('time.month').mean(dim='time') # select averaging period
wind_abs_anom = ((wind_abs.groupby('time.month') / wind_abs_clim))-1 #deviation from climo
fg = wind_abs_anom.sel(time=slice('2021-01',None)).groupby('time.month').mean(dim='time').plot(col='month',
col_wrap=3,transform=ccrs.PlateCarree(),
cbar_kwargs={'orientation':'horizontal','shrink':0.6, 'aspect':40,'label':'Percent Deviation'},robust=False,subplot_kws={'projection': ccrs.Mercator()})
fg.map(lambda: plt.gca().coastlines())
我能够重现您的图形,发现我可以添加 vmin
和 vmax
,如下所示。出于某种原因,这意味着我还必须指定颜色图,否则我会得到 viridis
。但是下面的代码对我有用(在我让它工作时进行了一些重构——这里唯一的 material 变化是在底部的绘图部分)。
首先,加载数据:
import cdsapi
c = cdsapi.Client()
params = {
'product_type': 'monthly_averaged_reanalysis',
'format': 'grib',
'variable': ['100m_u_component_of_wind', '100m_v_component_of_wind'],
'year': [f'{n}' for n in range(2006, 2022)],
'month': [f'{n:02d}' for n in range(1, 13)],
'time': '00:00',
'grid': [0.25, 0.25],
'area': [70.00, -180.00, -40.00, 180.00],
}
path = '100m_wind_U_V.grib'
url = c.retrieve('reanalysis-era5-single-levels-monthly-means',
params,
path,
)
然后是数据管道:
import xarray as xr
import numpy as np
# Also need cfgrib library.
ds = xr.load_dataset(path, engine='cfgrib')
wind_abs = np.sqrt(ds.u100**2 + ds.v100**2)
monthly_means = wind_abs.mean(dim='time')
wind_abs_clim = (wind_abs.sel(time=slice('2006-01','2020-12'))
.groupby('time.month')
.mean(dim='time'))
wind_abs_anom = ((wind_abs.groupby('time.month') / wind_abs_clim)) - 1
终于开始策划了:
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
cbar_kwargs = {'orientation':'horizontal', 'shrink':0.6, 'aspect':40, 'label':'Percent Deviation'}
subplot_kws = {'projection': ccrs.Mercator()}
fg = (wind_abs_anom.sel(time=slice('2021-01', None))
.groupby('time.month')
.mean(dim='time')
.plot(col='month',
col_wrap=3,
transform=ccrs.PlateCarree(),
cmap='RdBu_r', vmin=-3, vmax=3, # <-- New bit.
cbar_kwargs=cbar_kwargs,
robust=False,
subplot_kws=subplot_kws
))
fg.map(lambda: plt.gca().coastlines())
有时我会使用百分位数来自动控制 vmin
和 vmax
的值,例如 max_ = np.percentile(data, 99)
,然后是 vmin=-max_, vmax=max_
。这很好地处理了拉伸颜色图的异常值,但它要求您能够在绘制绘图之前计算这些值。
如果你想开始对绘图有更多的控制,停止使用 xarray
绘图界面并直接使用 matplotlib
和 cartopy
可能是个好主意。这可能看起来像(替换上面的所有绘图代码):
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
sel = wind_abs_anom.sel(time=slice('2021-01', None))
left, *_, right = wind_abs_anom.longitude
top, *_, bottom = wind_abs_anom.latitude # Min and max latitude.
extent = [left, right, bottom, top]
fig, axs = plt.subplots(nrows=2, ncols=3,
figsize=(15, 6),
subplot_kw={'projection': ccrs.PlateCarree()},
)
for ax, (month, group) in zip(axs.flat, sel.groupby('time.month')):
mean = group.mean(dim='time')
im = ax.imshow(mean,
transform=ccrs.PlateCarree(),
extent=extent,
cmap='RdBu_r', vmin=-3, vmax=3)
ax.set_title(f'month = {month}')
ax.coastlines()
cbar_ax = fig.add_axes([0.2, 0.0, 0.6, 0.05]) # Left, bottom, width, height.
cbar = fig.colorbar(im, cax=cbar_ax, extend='both', orientation='horizontal')
cbar.set_label('Percent deviation')
plt.show()
出于某种原因,当我尝试对地图使用 ccra.Mercator()
时,数据会失真;也许你能弄明白这一点。
我有一个看起来像这样的情节
我无法理解如何手动更改或设置颜色条的数据值范围。我想根据图中显示的数据值试验范围,并将颜色条更改为 (-4,4)。我看到 plt.clim
、vmin
和 vmax
是可能使用的函数。
这是我的代码:
import cdsapi
import xarray as xr
import matplotlib.pyplot as plt
import numpy as np
import cartopy.crs as ccrs
# Also requires cfgrib library.
c = cdsapi.Client()
url = c.retrieve(
'reanalysis-era5-single-levels-monthly-means',
{
'product_type': 'monthly_averaged_reanalysis',
'format': 'grib',
'variable': ['100m_u_component_of_wind','100m_v_component_of_wind'],
'year': ['2006','2007','2008','2009','2010','2011','2012','2013','2014','2015','2016','2017','2018','2019','2020','2021'],
'month': ['01','02','03','04','05','06','07','08','09','10','11','12'],
'time': '00:00',
'grid': [0.25, 0.25],
'area': [70.00, -180.00, -40.00, 180.00],
},
"C:\Users\U321103\.spyder-py3\ERA5_MAPPING\100m_wind_U_V.grib")
path = "C:\Users\U321103\.spyder-py3\ERA5_MAPPING\100m_wind_U_V.grib"
ds = xr.load_dataset(path, engine='cfgrib')
wind_abs = np.sqrt(ds.u100**2 + ds.v100**2)
monthly_means = wind_abs.mean(dim='time')
wind_abs_clim = wind_abs.sel(time=slice('2006-01','2020-12')).groupby('time.month').mean(dim='time') # select averaging period
wind_abs_anom = ((wind_abs.groupby('time.month') / wind_abs_clim))-1 #deviation from climo
fg = wind_abs_anom.sel(time=slice('2021-01',None)).groupby('time.month').mean(dim='time').plot(col='month',
col_wrap=3,transform=ccrs.PlateCarree(),
cbar_kwargs={'orientation':'horizontal','shrink':0.6, 'aspect':40,'label':'Percent Deviation'},robust=False,subplot_kws={'projection': ccrs.Mercator()})
fg.map(lambda: plt.gca().coastlines())
我能够重现您的图形,发现我可以添加 vmin
和 vmax
,如下所示。出于某种原因,这意味着我还必须指定颜色图,否则我会得到 viridis
。但是下面的代码对我有用(在我让它工作时进行了一些重构——这里唯一的 material 变化是在底部的绘图部分)。
首先,加载数据:
import cdsapi
c = cdsapi.Client()
params = {
'product_type': 'monthly_averaged_reanalysis',
'format': 'grib',
'variable': ['100m_u_component_of_wind', '100m_v_component_of_wind'],
'year': [f'{n}' for n in range(2006, 2022)],
'month': [f'{n:02d}' for n in range(1, 13)],
'time': '00:00',
'grid': [0.25, 0.25],
'area': [70.00, -180.00, -40.00, 180.00],
}
path = '100m_wind_U_V.grib'
url = c.retrieve('reanalysis-era5-single-levels-monthly-means',
params,
path,
)
然后是数据管道:
import xarray as xr
import numpy as np
# Also need cfgrib library.
ds = xr.load_dataset(path, engine='cfgrib')
wind_abs = np.sqrt(ds.u100**2 + ds.v100**2)
monthly_means = wind_abs.mean(dim='time')
wind_abs_clim = (wind_abs.sel(time=slice('2006-01','2020-12'))
.groupby('time.month')
.mean(dim='time'))
wind_abs_anom = ((wind_abs.groupby('time.month') / wind_abs_clim)) - 1
终于开始策划了:
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
cbar_kwargs = {'orientation':'horizontal', 'shrink':0.6, 'aspect':40, 'label':'Percent Deviation'}
subplot_kws = {'projection': ccrs.Mercator()}
fg = (wind_abs_anom.sel(time=slice('2021-01', None))
.groupby('time.month')
.mean(dim='time')
.plot(col='month',
col_wrap=3,
transform=ccrs.PlateCarree(),
cmap='RdBu_r', vmin=-3, vmax=3, # <-- New bit.
cbar_kwargs=cbar_kwargs,
robust=False,
subplot_kws=subplot_kws
))
fg.map(lambda: plt.gca().coastlines())
有时我会使用百分位数来自动控制 vmin
和 vmax
的值,例如 max_ = np.percentile(data, 99)
,然后是 vmin=-max_, vmax=max_
。这很好地处理了拉伸颜色图的异常值,但它要求您能够在绘制绘图之前计算这些值。
如果你想开始对绘图有更多的控制,停止使用 xarray
绘图界面并直接使用 matplotlib
和 cartopy
可能是个好主意。这可能看起来像(替换上面的所有绘图代码):
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
sel = wind_abs_anom.sel(time=slice('2021-01', None))
left, *_, right = wind_abs_anom.longitude
top, *_, bottom = wind_abs_anom.latitude # Min and max latitude.
extent = [left, right, bottom, top]
fig, axs = plt.subplots(nrows=2, ncols=3,
figsize=(15, 6),
subplot_kw={'projection': ccrs.PlateCarree()},
)
for ax, (month, group) in zip(axs.flat, sel.groupby('time.month')):
mean = group.mean(dim='time')
im = ax.imshow(mean,
transform=ccrs.PlateCarree(),
extent=extent,
cmap='RdBu_r', vmin=-3, vmax=3)
ax.set_title(f'month = {month}')
ax.coastlines()
cbar_ax = fig.add_axes([0.2, 0.0, 0.6, 0.05]) # Left, bottom, width, height.
cbar = fig.colorbar(im, cax=cbar_ax, extend='both', orientation='horizontal')
cbar.set_label('Percent deviation')
plt.show()
出于某种原因,当我尝试对地图使用 ccra.Mercator()
时,数据会失真;也许你能弄明白这一点。