Matplotlib绘制mpmath数据调用pcolormesh时报TypeError如何解决?
错误原因
你通过mpmath计算得到的z数组的元素是mpmath自定义的高精度mpf类型,不属于numpy原生支持的数值类型。matplotlib在绘图过程中会调用np.isnan()检查输入数组中的异常值,numpy的ufunc函数无法处理mpf类型的输入,也无法按照安全规则自动完成类型转换,因此触发该报错。
额外补充:即使没有类型错误,你的z数值量级达到e-500,已经远低于numpy float64类型的最小正数值阈值(约2.2e-308),直接转换会发生下溢变成0,也无法正常绘制出数值的分布差异。
解决方案
核心思路是对极小值做对数变换,将数值范围拉到普通浮点数可表示的区间,再转换为numpy原生类型绘图:
- 对mpmath计算得到的
z逐元素取自然对数,把极小值的量级差转换为线性的对数差 - 将取对数后的结果转换为numpy float64类型数组
- 用转换后的数组绘图,只需在色条上标注为对数取值即可保证可视化信息完整
示例修改代码:
import mpmath as mp import matplotlib.pyplot as plt import numpy as np from mpmath import e as e from mpmath import mpf, mpc,mp mp.dps = 1000 y, x = np.meshgrid(np.linspace(-5, 5, 1000), np.linspace(-5, 5, 1000)) z = e ** (-x**2 + y) z = z[:-1, :-1] # 新增转换代码:取对数后转numpy数组 z_log = np.array([[float(mp.log(val)) for val in row] for row in z]) z_min, z_max = z_log.min(), z_log.max() # 绘图时使用转换后的z_log fig, ax = plt.subplots() c = ax.pcolormesh(x, y, z_log, cmap='RdBu', vmin=z_min, vmax=z_max) ax.set_title('Titles are overall a positive feature') ax.axis([x.min(), x.max(), y.min(), y.max()]) # 色条标注对数属性 fig.colorbar(c, ax=ax, label='ln(z)') plt.show()
不使用mpmath的实现方法
完全可以不使用mpmath完成绘图。可视化本质需要的是数值的相对大小关系,对z = e^(-x² + y)这类指数形式的极小值,其对数变换结果ln(z) = -x² + y可以直接用numpy计算,没有精度问题,也不会出现极小值下溢的情况:
示例代码:
import matplotlib.pyplot as plt import numpy as np y, x = np.meshgrid(np.linspace(-5, 5, 1000), np.linspace(-5, 5, 1000)) # 直接计算对数后的结果,不需要处理极小值 z_log = -x**2 + y z_log = z_log[:-1, :-1] z_min, z_max = z_log.min(), z_log.max() fig, ax = plt.subplots() c = ax.pcolormesh(x, y, z_log, cmap='RdBu', vmin=z_min, vmax=z_max) ax.set_title('Titles are overall a positive feature') ax.axis([x.min(), x.max(), y.min(), y.max()]) fig.colorbar(c, ax=ax, label='ln(z)') plt.show()
如果你的实际z值是无法直接解析求对数的复杂极小值,也可以先通过mpmath计算得到数值后,逐元素取对数转float,再用numpy处理绘图,不需要全程使用mpmath类型。
内容的提问来源于stack exchange,提问作者Denis Marcinkov
相关产品推荐
相关产品推荐

