MatPlotLib,datetimes和TypeError:输入类型不支持ufunc'isfinite'...

Sar*_*ica 3 python datetime numpy matplotlib python-3.x

这是一小段代码,它在图形的两行之间产生一个填充区域:

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(0.0, 2, 0.01)
y1 = np.sin(2 * np.pi * x)
y2 = 1.2 * np.sin(4 * np.pi * x)

fig, ax1 = plt.subplots(1, 1, sharex=True)

# Test support for masked arrays.
ax1.fill_between(x, 0, y1)
ax1.set_ylabel('between y1 and 0')
y2 = np.ma.masked_greater(y2, 1.0)
ax1.plot(x, y1, x, y2, color='black')
ax1.fill_between(
    x, y1, y2, where=y2 >= y1,
    facecolor='green',
    interpolate=True)
ax1.fill_between(x, y1, y2, where=y2 <= y1, facecolor='red', interpolate=True)
ax1.set_title('Now regions with y2>1 are masked')

# Show the plot.
plt.show()
Run Code Online (Sandbox Code Playgroud)

它看起来像这样:

由代码生成的图

现在,更改开始,以便x现在是日期时间对象的集合,如下所示:

import datetime

x1 = np.arange(0.0, 2, 0.01)
now = np.datetime64(datetime.datetime.now())
x = np.array([now - np.timedelta64(datetime.timedelta(seconds=i)) for i in range(200)])
y1 = np.sin(2 * np.pi * x1)
y2 = 1.2 * np.sin(4 * np.pi * x1)
Run Code Online (Sandbox Code Playgroud)

收益率:

Traceback (most recent call last):                                                File "fill_between_demo.py", line 21, in <module>                             
    ax1.fill_between(x, 0, y1)                                                  
  File "/home/usr/.virtualenvs/raiju/lib/python3.6/site-packages/matplotlib/__init__.py", line 1898, in inner                                                  
    return func(ax, *args, **kwargs)                                            
  File "/home/usr/.virtualenvs/raiju/lib/python3.6/site-packages/matplotlib/axes/_axes.py", line 4778, in fill_between                                         
    x = ma.masked_invalid(self.convert_xunits(x))                               
  File "/home/usr/.virtualenvs/raiju/lib/python3.6/site-packages/numpy/ma/core.py", line 2388, in masked_invalid                                               
    condition = ~(np.isfinite(a))                                               
TypeError: ufunc 'isfinite' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''     
Run Code Online (Sandbox Code Playgroud)

为什么会发生这种情况以及如何解决?

请注意,绘制数据(也就是不使用fill*)可以正常工作.

jot*_*asi 9

问题是,isfinite没有为numpy.datetime64dtype 定义numpy ufunc.但是,我们正努力改变这种状况.numpy的github上的这个问题正在这个pull-request中进行,但是只要没有完成并合并,你将无法isfinite在该dtype 上使用.matplotlib.pyplot.fill_between当调用numpy.ma.masked_invalid掩码输入数组的所有无效条目时,这是一个隐式使用此函数的问题.

虽然有一个解决方法.正如在关于绘制类型的大熊猫的类似问题的答案中所指出的,pandas为(以及其他)具有matplotlib 的dtype numpy数组注册了一个自定义转换器.要使用它,您只需导入pandas:fill_betweenSeriesdatetime64datetime64

import numpy as np
import matplotlib.pyplot as plt
import datetime
# import pandas for its converter that is then used in pyplot!
import pandas

x1 = np.arange(0.0, 2, 0.01)
now = np.datetime64(datetime.datetime.now())
x = np.array([now - np.timedelta64(datetime.timedelta(seconds=i))
              for i in range(200)])
y1 = np.sin(2 * np.pi * x1)
y2 = 1.2 * np.sin(4 * np.pi * x1)

fig, ax1 = plt.subplots(1, 1, sharex=True)

# Test support for masked arrays.
ax1.fill_between(x, 0, y1)
ax1.set_ylabel('between y1 and 0')
y2 = np.ma.masked_greater(y2, 1.0)
ax1.plot(x, y1, x, y2, color='black')
ax1.fill_between(
    x, y1, y2, where=y2 >= y1,
    facecolor='green',
    interpolate=True)
ax1.fill_between(x, y1, y2, where=y2 <= y1, facecolor='red', interpolate=True)
ax1.set_title('Now regions with y2>1 are masked')

# Show the plot.
plt.show()
Run Code Online (Sandbox Code Playgroud)

将工作,并为您提供所需的输出:

在此输入图像描述