MatPlotLib,日期时间和TypeError:输入类型不支持ufunc'isfinite'… [英] MatPlotLib, datetimes, and TypeError: ufunc 'isfinite' not supported for the input types…

查看:228
本文介绍了MatPlotLib,日期时间和TypeError:输入类型不支持ufunc'isfinite'…的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆