我碰巧在这个 page上看到了一个漂亮的图表,如下所示: 是否有可能在matplotlib中获得这样的颜色渐变? 对类似问题有一些先前的答案(例如 https://stackoverflow.com/a/22081678/325565),但他们建议
是否有可能在matplotlib中获得这样的颜色渐变?
对类似问题有一些先前的答案(例如 https://stackoverflow.com/a/22081678/325565),但他们建议采用次优方法.大多数先前的答案建议在pcolormesh填充上绘制白色多边形.由于两个原因,这不太理想:
>轴的背景不能是透明的,因为它上面有一个填充的多边形
> pcolormesh绘制速度相当慢,并且不能平滑插值.
这是一个更多的工作,但有一种方法可以更快地绘制并提供更好的视觉效果:设置用imshow绘制的图像的剪辑路径.
举个例子:
import numpy as np import matplotlib.pyplot as plt import matplotlib.colors as mcolors from matplotlib.patches import Polygon np.random.seed(1977) def main(): for _ in range(5): gradient_fill(*generate_data(100)) plt.show() def generate_data(num): x = np.linspace(0, 100, num) y = np.random.normal(0, 1, num).cumsum() return x, y def gradient_fill(x, y, fill_color=None, ax=None, **kwargs): """ Plot a line with a linear alpha gradient filled beneath it. Parameters ---------- x, y : array-like The data values of the line. fill_color : a matplotlib color specifier (string, tuple) or None The color for the fill. If None, the color of the line will be used. ax : a matplotlib Axes instance The axes to plot on. If None, the current pyplot axes will be used. Additional arguments are passed on to matplotlib's ``plot`` function. Returns ------- line : a Line2D instance The line plotted. im : an AxesImage instance The transparent gradient clipped to just the area beneath the curve. """ if ax is None: ax = plt.gca() line, = ax.plot(x, y, **kwargs) if fill_color is None: fill_color = line.get_color() zorder = line.get_zorder() alpha = line.get_alpha() alpha = 1.0 if alpha is None else alpha z = np.empty((100, 1, 4), dtype=float) rgb = mcolors.colorConverter.to_rgb(fill_color) z[:,:,:3] = rgb z[:,:,-1] = np.linspace(0, alpha, 100)[:,None] xmin, xmax, ymin, ymax = x.min(), x.max(), y.min(), y.max() 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) im.set_clip_path(clip_path) ax.autoscale(True) return line, im main()