matplotlib.widgets.Slider 和 fill_between

matplotlib.widgets.Slider with fill_between

我正在尝试在类似于 slider demo example 的图中添加滑块。

我正在绘制 fill_between,它给出 PolyCollection 对象。

尽管我也尝试使用 plot 给出了 Line2D 对象,如下图所示,但绘图没有像预期的那样更新demo.

代码

import numpy as np
import scipy.stats as ss
import matplotlib.pyplot as plt
import matplotlib.widgets as widgets

def get_pdf(mu, sigma=1, offset=4):
    o = sigma * offset
    x = np.linspace(mu - o, mu + o, 100)
    rv = ss.norm(mu, sigma)
    return x, rv.pdf(x)

fig, ax = plt.subplots()
plt.subplots_adjust(bottom=0.25)
ax.fill_between(*get_pdf(0, 1), alpha=0.7)
# t = plt.fill_between(*get_pdf(2, 1), alpha=0.7) # this gives ployCollection
t = ax.plot(*get_pdf(2, 1), label='treatment', alpha=0.7)

a = plt.axes([0.25, 0.1, 0.5, 0.03])

slider = widgets.Slider(a, "shift", 0, 10, valinit=2, valstep=1)
def update(val):
    x, y = get_pdf(val)
    t[0].set_ydata(y)
    fig.canvas.draw_idle()

slider.on_changed(update)
plt.show()

要更新线图,需要设置t[0].set_xdata(x),因为每次调用都不同。在这种特殊情况下,get_pdf 每次 returns 相同 y

似乎无法更新 fill_between 生成的 polyCollection 的坐标。但是,您可以在每次更新时删除并重新创建它。请注意,这比仅更新坐标要慢。

import numpy as np
import scipy.stats as ss
import matplotlib.pyplot as plt
import matplotlib.widgets as widgets

def get_pdf(mu, sigma=1, offset=4):
    o = sigma * offset
    x = np.linspace(mu - o, mu + o, 100)
    rv = ss.norm(mu, sigma)
    return x, rv.pdf(x)

fig, ax = plt.subplots()
plt.subplots_adjust(bottom=0.25)
ax.fill_between(*get_pdf(0, 1), alpha=0.7)
t = ax.fill_between(*get_pdf(2), color='crimson', alpha=0.7)
a = plt.axes([0.25, 0.1, 0.5, 0.03])

slider = widgets.Slider(a, "shift", 0, 10, valinit=2, valstep=1)
def update(val):
    global t
    t.remove()
    t = ax.fill_between(*get_pdf(val), color='crimson', alpha=0.7)
    fig.canvas.draw_idle()

slider.on_changed(update)
plt.show()