2017-08-01 1 views
2

は、グラフの2つのラインの間の領域に充填生成コードの小さな作品です:matplotlibの、日付時刻、および例外TypeError:ufunc「isfiniteのは、」入力タイプでサポートされていません...ここで

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() 

に見えますがそのような:

Plot generated by the code

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) 

収率は:

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''  

がなぜ起こっているとどのようにそれを修正しますか?

データのプロット(別名fill*は使用できません)はうまくいきます。

答えて

5

numpy ufunc isfinitenumpy.datetime64dtypeで定義されていないという問題があります。しかし、これを変更する努力があります。このissue on numpy's githubはこのpull-requestで処理されていますが、これが完了してマージされない限り、isfiniteをそのdtypeに使用することはできません。入力配列のすべての無効なエントリをマスクするためにnumpy.ma.masked_invalidを呼び出すとき、matplotlib.pyplot.fill_betweenがこの関数を暗黙的に使用しているので、これは問題です。

しかし、回避策があります。このanswerに指摘されているように、同様の質問fill_betweenについて指摘したように、パンダSeriesdatetime64タイプであり、matplotlibでdatetime64dtypeの(とりわけ)numpy配列のカスタムコンバータを登録します。それを使用するには、単にパンダをインポートする必要があります。

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() 

は、ご希望の出力を仕事とあなたを与えるだろう。

enter image description here

関連する問題