我從these two posts on SO獲取了大量關於在matplotlib中將曲線填充到曲線下方的信息。我嘗試了在一個座標軸上繪製多個繪圖的同樣的事情,並且處理它們的順序和它們的alpha以確保它們可見。我得到PIL的錯誤,輸出這個圖的代碼:Matplotlib圖形中的漸變填充
是否有可能使plot下面的'fill'進一步下降,並修復右下角的錯誤?我通過將原始數據放在bpaste上包含了我在這個例子中使用的數據,所以即使很長時間,這個例子也是完全獨立的。
它可能與後端使用有關嗎?
感謝,賈裏德
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
from matplotlib.patches import Polygon
from matplotlib.ticker import Formatter, FuncFormatter
import matplotlib
import numpy as np
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFilter
df = pd.read_csv('https://bpaste.net/raw/87cbf69259ae')
df = df.set_index('Date', drop=True)
df.index = pd.to_datetime(df.index)
df1 = pd.read_csv('https://bpaste.net/raw/bc06b26b0b8b')
df1 = df1.set_index('Date', drop=True)
df1.index = pd.to_datetime(df1.index)
def zfunc(x, y, fill_color='k', alpha=1.0, xmin=None, xmax=None, ymin=None, ymax=None):
if xmax is not None:
xmax = int(xmax)
if xmin is not None:
xmin = int(xmin)
if ymax is not None:
ymax = int(ymax)
if ymin is not None:
ymin = int(ymin)
w, h = xmax-xmin, ymax-ymin
z = np.empty((h, w, 4), dtype=float)
rgb = mcolors.colorConverter.to_rgb(fill_color)
z[:,:,:3] = rgb
# Build a z-alpha array which is 1 near the line and 0 at the bottom.
img = Image.new('L', (w, h), 0)
draw = ImageDraw.Draw(img)
xy = (np.column_stack([x, y]))
xy -= xmin, ymin
# Draw a blurred line using PIL
draw.line(map(tuple, xy.tolist()), fill=255, width=15)
img = img.filter(ImageFilter.GaussianBlur(radius=25))
# Convert the PIL image to an array
zalpha = np.asarray(img).astype(float)
zalpha *= alpha/zalpha.max()
# make the alphas melt to zero at the bottom
n = int(zalpha.shape[0]/4)
zalpha[:n] *= np.linspace(0, 10, n)[:, None]
z[:,:,-1] = zalpha
return z
def gradient_fill(x, y, fill_color=None, ax=None, ylabel=None, zfunc=None, **kwargs):
if ax is None:
ax = plt.gca()
if ylabel is not None:
ax.set_ylabel(ylabel, weight='bold', color='white')
class DateFormatter(Formatter):
def __init__(self, dates, fmt='%b \'%y'):
self.dates = dates
self.fmt = fmt
def __call__(self, x, pos=0):
'Return the label for time x at position pos'
ind = int(round(x))
if ind>=len(self.dates) or ind<0: return ''
return self.dates[ind].strftime(self.fmt)
def millions(x, pos):
return '$%d' % x
dollar_formatter = FuncFormatter(millions)
formatter = DateFormatter(df.index)
ax.yaxis.grid(linestyle='-', alpha=0.5, color='white', zorder=-1)
line, = ax.plot(x, y, linewidth=2.0, c=fill_color, **kwargs)
if fill_color is None:
fill_color = line.get_color()
zorder = line.get_zorder()
if 'alpha' in kwargs:
alpha = kwargs['alpha']
else:
alpha = line.get_alpha()
alpha = 1.0 if alpha is None else alpha
xmin, xmax, ymin, ymax = x.min(), x.max(), y.min(), y.max()
diff = ymax - ymin
ymin = ymin - diff*0.15
ymax = diff*0.05 + ymax
if zfunc is None:
## Grab an array of length (cols,rows,spacing) but don't initialize values
z = np.empty((110, 1, 4), dtype=float)
## get color to fill for current axix line
rgb = mcolors.colorConverter.to_rgb(fill_color)
z[:,:,:3] = rgb
z[:,:,-1] = np.linspace(0, alpha, 110)[:,None]
else:
z = zfunc(x, y, fill_color=fill_color, alpha=alpha, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax)
im = ax.imshow(z, aspect='auto', extent=[xmin, xmax, ymin, ymax], origin='lower', zorder=zorder)
xy = np.column_stack([x, y])
xy = np.vstack([[xmin, ymin], xy, [xmax, ymin], [xmin, ymin]])
clip_path = Polygon(xy, facecolor='none', edgecolor='none', closed=True)
ax.add_patch(clip_path)
ax.patch.set_facecolor('black')
im.set_clip_path(clip_path)
ax.xaxis.set_major_formatter(formatter)
ax.yaxis.set_major_formatter(dollar_formatter)
for tick in ax.get_yticklabels():
tick.set_color('white')
for tick in ax.get_xticklabels():
tick.set_color('white')
w = 17.5 * 1.5 # approximate size in inches of 1280
h = 7.5 * 1.5 # approximate size in inches of 720
fig = plt.gcf()
fig.set_size_inches(w, h)
# fig.autofmt_xdate()
plt.rcParams['xtick.major.pad']='20'
matplotlib.rcParams['ytick.major.pad']='20'
matplotlib.rcParams.update({'font.size': 22})
ax.set_ylim((ymin, ymax))
#ax.autoscale(True)
return line, im, ax
line, im, ax = gradient_fill(np.arange(len(df1.index)), df1['/CL_Close'], fill_color='#fdbf6f', ylabel='Crude Oil', alpha=1.0, zfunc=zfunc)
ax2 = ax.twinx()
gradient_fill(np.arange(len(df.index)), df['/ES_Close'], ax=ax2, fill_color='#cab2d6', ylabel='S&P', alpha=0.75, zfunc=zfunc)
ax2.yaxis.grid(False)
是第一數據鏈路的工作? – gauteh
它爲我工作,但可能是因爲我是一個人。我會用更長的TTL重新加載另一個。 – Jared
@gauteh我編輯過的數據永遠不會在bpaste上過期。 – Jared