首页 > 解决方案 > 使用 mpmath 绘图时,Matplotlib 因 `TypeError` 失败

问题描述

我有非常小(有序e-500)的 2D 数据,所以我不能使用我想绘制为 pcolormesh 的 numpy。例如,

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]
z_min, z_max = -np.abs(z).max(), np.abs(z).max()

编译得很好但是当我想做一些pcolormesh事情时:

fig, ax = plt.subplots()
c = ax.pcolormesh(x, y, z, 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)
plt.show()

给出错误TypeError: ufunc 'isnan' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''

为什么会这样?你知道如何解决这个问题吗?也许没有 mpmath 的绘图会有所帮助。

编辑:完整追溯

TypeError                                 Traceback (most recent call last)
~/.local/lib/python3.8/site-packages/IPython/core/formatters.py in __call__(self, obj)
   339                 pass
   340             else:
--> 341                 return printer(obj)
   342             # Finally look for special method names
   343             method = get_real_method(obj, self.print_method)

~/.local/lib/python3.8/site-packages/IPython/core/pylabtools.py in <lambda>(fig)
   246 
   247     if 'png' in formats:
--> 248         png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png', **kwargs))
   249     if 'retina' in formats or 'png2x' in formats:
   250         png_formatter.for_type(Figure, lambda fig: retina_figure(fig, **kwargs))

~/.local/lib/python3.8/site-packages/IPython/core/pylabtools.py in print_figure(fig, fmt, bbox_inches, **kwargs)
   130         FigureCanvasBase(fig)
   131 
--> 132     fig.canvas.print_figure(bytes_io, **kw)
   133     data = bytes_io.getvalue()
   134     if fmt == 'svg':

~/.local/lib/python3.8/site-packages/matplotlib/backend_bases.py in print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, **kwargs)
  2077                             print_method, dpi=dpi, orientation=orientation),
  2078                         draw_disabled=True)
-> 2079                     self.figure.draw(renderer)
  2080                     bbox_artists = kwargs.pop("bbox_extra_artists", None)
  2081                     bbox_inches = self.figure.get_tightbbox(renderer,

~/.local/lib/python3.8/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
    36                 renderer.start_filter()
    37 
---> 38             return draw(artist, renderer, *args, **kwargs)
    39         finally:
    40             if artist.get_agg_filter() is not None:

~/.local/lib/python3.8/site-packages/matplotlib/figure.py in draw(self, renderer)
  1733 
  1734             self.patch.draw(renderer)
-> 1735             mimage._draw_list_compositing_images(
  1736                 renderer, self, artists, self.suppressComposite)
  1737 

~/.local/lib/python3.8/site-packages/matplotlib/image.py in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
   135     if not_composite or not has_images:
   136         for a in artists:
--> 137             a.draw(renderer)
   138     else:
   139         # Composite any adjacent images together

~/.local/lib/python3.8/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
    36                 renderer.start_filter()
    37 
---> 38             return draw(artist, renderer, *args, **kwargs)
    39         finally:
    40             if artist.get_agg_filter() is not None:

~/.local/lib/python3.8/site-packages/matplotlib/axes/_base.py in draw(self, renderer, inframe)
  2628             renderer.stop_rasterizing()
  2629 
-> 2630         mimage._draw_list_compositing_images(renderer, self, artists)
  2631 
  2632         renderer.close_group('axes')

~/.local/lib/python3.8/site-packages/matplotlib/image.py in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
   135     if not_composite or not has_images:
   136         for a in artists:
--> 137             a.draw(renderer)
   138     else:
   139         # Composite any adjacent images together

~/.local/lib/python3.8/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
    36                 renderer.start_filter()
    37 
---> 38             return draw(artist, renderer, *args, **kwargs)
    39         finally:
    40             if artist.get_agg_filter() is not None:

~/.local/lib/python3.8/site-packages/matplotlib/collections.py in draw(self, renderer)
  2045                 offsets = np.column_stack([xs, ys])
  2046 
-> 2047         self.update_scalarmappable()
  2048 
  2049         if not transform.is_affine:

~/.local/lib/python3.8/site-packages/matplotlib/collections.py in update_scalarmappable(self)
   790             return
   791         if self._is_filled:
--> 792             self._facecolors = self.to_rgba(self._A, self._alpha)
   793         elif self._is_stroked:
   794             self._edgecolors = self.to_rgba(self._A, self._alpha)

~/.local/lib/python3.8/site-packages/matplotlib/cm.py in to_rgba(self, x, alpha, bytes, norm)
   243         if norm:
   244             x = self.norm(x)
--> 245         rgba = self.cmap(x, alpha=alpha, bytes=bytes)
   246         return rgba
   247 

~/.local/lib/python3.8/site-packages/matplotlib/colors.py in __call__(self, X, alpha, bytes)
   559         if np.ma.is_masked(X):
   560             mask_bad = X.mask
--> 561         elif np.any(np.isnan(X)):
   562             # mask nan's
   563             mask_bad = np.isnan(X)

TypeError: ufunc 'isnan' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''

<Figure size 432x288 with 2 Axes> ```

标签: pythonnumpymatplotlibplotmpmath

解决方案


使用您的代码,编辑以在合理的测试时间内运行:

    ...: mp.dps = 10
    ...: y, x = np.meshgrid(np.linspace(-5, 5, 10), np.linspace(-5, 5, 10))
    ...: z = e ** (-x**2 + y)
    ...: z = z[:-1, :-1]
    ...: z_min, z_max = -np.abs(z).max(), np.abs(z).max()
    ...: 
In [11]: z
Out[11]: 
array([[mpf('9.357622969874e-14'), mpf('2.842594865759e-13'),
        mpf('8.635040754285e-13'), mpf('2.623093769921e-12'),
        mpf('7.968255300282e-12'), mpf('2.420542233701e-11'),
        mpf('7.352958062098e-11'), mpf('2.233631436379e-10'),
        mpf('6.785173193566e-10')],
...., dtype=object)
In [12]: z.dtype
Out[12]: dtype('O')
In [13]: np.isnan(z)
Traceback (most recent call last):
  File "<ipython-input-13-72670087bbfa>", line 1, in <module>
    np.isnan(z)
TypeError: ufunc 'isnan' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''

通过使用mpmath,您创建了一个对象 dtype 数组。虽然这可能具有更高的精度,但它的运行速度也慢得多,在某些情况下根本不运行。

isnan需要一个数字 dtype 数组:

In [16]: np.any(np.isnan(z.astype(float)))
Out[16]: False

回溯表明在图中plot使用isnan“空白”nan值。

这有效:

plt.pcolormesh(x, y, z.astype('float128'), cmap='RdBu', vmin=z_min, vmax=z_max)

推荐阅读