MatPlotLib,日期时间和TypeError:输入类型不支持ufunc'isfinite'… [英] MatPlotLib, datetimes, and TypeError: ufunc 'isfinite' not supported for the input types…
问题描述
这是一段很小的代码,可在图形的两行之间产生一个填充区域:
import matplotlib。 pyplot as plt
导入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)
图,ax1 = plt.subplots(1,1,sharex = True)
#测试对掩码数组的支持。
ax1.fill_between(x,0,y1)
ax1.set_ylabel('在y1和0'之间)
y2 = np.ma.masked_greater(y2,1.0)
ax1 .plot(x,y1,x,y2,color ='black')
ax1.fill_between(
x,y1,y2,其中= y2> = y1,
facecolor ='green ',
interpolate = True)
ax1.fill_between(x,y1,y2,其中= y2 <= y1,facecolor ='red',interpolate = True)
ax1.set_title( '现在遮盖了y2> 1的区域')
#显示图。
plt.show()
看起来像这样:
现在,更改开始位置,使 x
现在是像这样的日期时间对象的集合:
import datetime
x1 = np.arange(0.0,2,0.01)
now = np.datetime64(datetime.datetime.now())
x = np.array([now-np.timedelta64(datetime。 i在范围(200)中的timedelta(seconds = i))])
y1 = np.sin(2 * np.pi * x1)
y2 = 1.2 * np.sin(4 * np。 pi * x1)
收益率:
跟踪(最近一次通话最近):文件 fill_between_demo.py,第21行,在< module>中
ax1.fill_between(x,0,y1)
文件 /home/usr/.virtualenvs/raiju/lib/python3.6/site-packages/matplotlib/__init__.py,行1898,在内部
中返回func(ax,* args,** kwargs)
文件 /home/usr/.virtualenvs/raiju/lib/python3.6/site-packages/matplotlib/axes/_axes。 py,第4778行,在fill_between
x = ma.masked_invalid(self.convert_xunits(x))
文件 /home/usr/.virtualenvs/raiju/lib/python3.6/site-packages/ numpy / ma / core.py,第2388行,在masked_invalid
条件=〜(np.isfinite(a))
TypeError中:输入类型不支持ufunc'isfinite',并且输入可以不能根据铸造规则安全地强制使用任何受支持的类型le安全
为什么会发生这种情况以及如何解决? em>
请注意,绘制数据(也就是不使用 fill *
)可以正常工作。
问题是,numpy ufunc isfinite
没有为<$定义c $ c> numpy.datetime64 dtype。不过,我们正在努力改变这一点。此
Here is a tiny piece of code that produces a filled in region between two lines of a graph:
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()
It looks like so:
Now, changing the start so that x
is now a collections of date times objects like so:
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)
yields:
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''
Why is that happening and how to fix it?
Note that plotting the data (aka not using fill*
) works just fine.
The problem is, that the numpy ufunc isfinite
is not defined for the numpy.datetime64
dtype. There is an effort to change this, though. This issue on numpy's github is being worked on in this pull-request, but as long as this is not finished up and merged, you will not be able to use isfinite
on that dtype. This is a problem as matplotlib.pyplot.fill_between
is using this function implicitly, when calling numpy.ma.masked_invalid
to mask all invalid entries of your input array.
There is a work-around though. As pointed out in this answer to a similar question concerning fill_between
plotting of a pandas Series
of datetime64
type, pandas registers a custom converter for (among others) numpy arrays of datetime64
dtype with matplotlib. To make use of that, you simply have to import pandas:
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()
will work and give you your desired output:
这篇关于MatPlotLib,日期时间和TypeError:输入类型不支持ufunc'isfinite'…的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!