Proplot调用contourf绘图报错DiscreteNorm无'_vmin'属性
ProPlot调用contourf绘图触发
DiscreteNorm缺少_vmin属性报错 问题现象
- 使用ProPlot(Matplotlib高级封装绘图库)调用
contourf绘制填充等高线时触发属性错误,即便是运行官方文档提供的2dplots章节对应示例代码,也会复现完全相同的报错。 - 正常依赖配置的环境下上述官方示例可正常输出图像,初步排查ProPlot源码未定位到根因。
测试数据构造代码
import xarray as xr import numpy as np import pandas as pd import proplot as pp # 构造DataArray格式测试数据 state = np.random.RandomState(51423) linspace = np.linspace(0, np.pi, 20) data = 50 * state.normal(1, 0.2, size=(20, 20)) * ( np.sin(linspace * 2) ** 2 * np.cos(linspace + np.pi / 2)[:, None] ** 2 ) lat = xr.DataArray( np.linspace(-90, 90, 20), dims=('lat',), attrs={'units': '\N{DEGREE SIGN}N'} ) plev = xr.DataArray( np.linspace(1000, 0, 20), dims=('plev',), attrs={'long_name': 'pressure', 'units': 'hPa'} ) da = xr.DataArray( data, name='u', dims=('plev', 'lat'), coords={'plev': plev, 'lat': lat}, attrs={'long_name': 'zonal wind', 'units': 'm/s'} ) # 构造DataFrame格式测试数据 data = state.rand(12, 20) df = pd.DataFrame( (data - 0.4).cumsum(axis=0).cumsum(axis=1)[::1, ::-1], index=pd.date_range('2000-01', '2000-12', freq='MS') ) df.name = 'temperature (\N{DEGREE SIGN}C)' df.index.name = 'date' df.columns.name = 'variable (units)'
绘图复现代码
fig = pp.figure(refwidth=2.5, share=False, suptitle='Automatic subplot formatting') # 绘制DataArray填充等高线 cmap = pp.Colormap('PuBu', left=0.05) ax = fig.subplot(121, yreverse=True) ax.contourf(da, cmap=cmap, colorbar='t', lw=0.7, ec='k') # 绘制DataFrame填充等高线 ax = fig.subplot(122, yreverse=True) ax.contourf(df, cmap='YlOrRd', colorbar='t', lw=0.7, ec='k') ax.format(xtickminor=False, yformatter='%b', ytickminor=False)
完整报错信息
AttributeError Traceback (most recent call last) Input In [780], in <module> 4 cmap = pp.Colormap('PuBu', left=0.05) 5 ax = fig.subplot(121, yreverse=True) ----> 6 ax.contourf(da, cmap=cmap, colorbar='t', lw=0.7, ec='k') 8 # Plot DataFrame 9 ax = fig.subplot(122, yreverse=True) File /opt/anaconda3/envs/argopy-tests/lib/python3.8/site-packages/proplot/internals/process.py:284, in _preprocess_args.<locals>.decorator.<locals>._redirect_or_standardize(self, *args, **kwargs) 281 ureg.setup_matplotlib(True) 283 # Call main function --> 284 return func(self, *args, **kwargs) File /opt/anaconda3/envs/argopy-tests/lib/python3.8/site-packages/proplot/axes/plot.py:3861, in PlotAxes.contourf(self, x, y, z, **kwargs) 3859 x, y, z, kw = self._parse_plot2d(x, y, z, **kwargs) 3860 kw.update(_pop_props(kw, 'collection')) -> 3861 kw = self._parse_cmap(x, y, z, plot_contours=True, **kw) 3862 contour_kw = _pop_kwargs(kw, 'edgecolors', 'linewidths', 'linestyles') 3863 edgefix_kw = _pop_params(kw, self._apply_edgefix) File /opt/anaconda3/envs/argopy-tests/lib/python3.8/site-packages/proplot/internals/warnings.py:96, in _rename_kwargs.<locals>.decorator.<locals>._deprecate_kwargs(*args, **kwargs) 91 key_new = key_new.format(value) 92 _warn_proplot( 93 f'Keyword {key_old!r} was deprecated in version {version} and will ' 94 f'be removed in a future release. Please use {key_new!r} instead.' 95 ) ---> 96 return func_orig(*args, **kwargs) File /opt/anaconda3/envs/argopy-tests/lib/python3.8/site-packages/proplot/axes/plot.py:2703, in PlotAxes._parse_cmap(self, cmap, cmap_kw, c, color, colors, default_cmap, norm, norm_kw, extend, vmin, vmax, discrete, default_discrete, skip_autolev, plot_lines, plot_contours, min_levels, *args, **kwargs) 2700 # Create the discrete normalizer 2701 # Then finally warn and remove unused args 2702 if levels is not None: -> 2703 norm, cmap, kwargs = self._parse_discrete( 2704 levels, norm, cmap, extend=extend, min_levels=min_levels, **kwargs 2705 ) 2706 methods = (self._parse_levels, self._parse_autolev, self._parse_vlim) 2707 params = _pop_params(kwargs, *methods, ignore_internal=True) File /opt/anaconda3/envs/argopy-tests/lib/python3.8/site-packages/proplot/axes/plot.py:2529, in PlotAxes._parse_discrete(self, levels, norm, cmap, extend, min_levels, **kwargs) 2526 # Generate DiscreteNorm and update "child" norm with vmin and vmax from 2527 # levels. This lets the colorbar set tick locations properly! 2528 if not isinstance(norm, mcolors.BoundaryNorm) and len(levels) > 1: -> 2529 norm = pcolors.DiscreteNorm(levels, norm=norm, unique=unique, step=step) 2531 return norm, cmap, kwargs File /opt/anaconda3/envs/argopy-tests/lib/python3.8/site-packages/proplot/internals/warnings.py:96, in _rename_kwargs.<locals>.decorator.<locals>._deprecate_kwargs(*args, **kwargs) 91 key_new = key_new.format(value) 92 _warn_proplot( 93 f'Keyword {key_old!r} was deprecated in version {version} and will ' 94 f'be removed in a future release. Please use {key_new!r} instead.' 95 ) ---> 96 return func_orig(*args, **kwargs) File /opt/anaconda3/envs/argopy-tests/lib/python3.8/site-packages/proplot/colors.py:2459, in DiscreteNorm.__init__(self, levels, norm, unique, step, clip) 2457 self._dest = dest 2458 self._norm = norm -> 2459 self.vmin = vmin 2460 self.vmax = vmax 2461 self.boundaries = levels File /opt/anaconda3/envs/argopy-tests/lib/python3.8/site-packages/matplotlib/colors.py:1148, in Normalize.vmin(self, value) 1145 @vmin.setter 1146 def vmin(self, value): 1147 value = _sanitize_extrema(value) -> 1148 if value != self._vmin: 1149 self._vmin = value 1150 self._changed() AttributeError: 'DiscreteNorm' object has no attribute '_vmin'
问题根因
该报错由ProPlot与Matplotlib版本不兼容导致:
- 当前环境安装的Matplotlib版本≥3.6.0,新版本调整了
Normalize基类的初始化逻辑,_vmin、_vmax这类私有属性必须先通过父类构造方法初始化,才能通过setter给vmin、vmax属性赋值。 - 环境中安装的ProPlot为≤0.9.7的正式稳定版,该版本中
DiscreteNorm类的__init__方法没有先调用父类构造方法完成基础属性初始化,就直接执行self.vmin = vmin的赋值操作,触发属性不存在的错误。 - 官方示例代码本身没有逻辑问题,是本地环境依赖版本不匹配导致运行失败。
解决方案
可根据自身需求选择以下任意一种方案修复:
- 方案1:降级Matplotlib到兼容版本(最稳定)
将Matplotlib版本固定到3.5.x系列,该版本与0.9.7版ProPlot适配性最好,不会出现兼容问题。执行对应包管理命令即可:# pip环境 pip install matplotlib==3.5.3 # conda环境 # conda install matplotlib=3.5.3 - 方案2:安装修复了兼容问题的ProPlot开发版
ProPlot官方开发分支已经适配了Matplotlib 3.6+版本的接口变更,可直接安装最新开发版替换现有稳定版。 - 方案3:临时手动修改ProPlot源码修复
如果不想调整现有依赖版本,可以找到环境中ProPlot安装路径下的proplot/colors.py文件,定位到DiscreteNorm类的__init__方法,在所有self.xxx属性赋值前,添加一行父类初始化代码:
修改保存后重启Python内核,即可正常运行绘图代码。super().__init__(vmin=None, vmax=None, clip=clip)
内容的提问来源于stack exchange,提问作者Only god knows
相关产品推荐
相关产品推荐

