ipywidgets:使用交互时避免闪烁

Ant*_*ano 5 python matplotlib jupyter-notebook ipywidgets

我制作了一个图形,其中包含分别基于随机正态分布、伽玛分布、指数分布和均匀分布的直方图的四个子图。我使用 matplotlib 和 Jupyter Notebook 制作的。它是通过 ipywidgets lib 生成的交互式图形。特别是,有四个滑动条控制每个直方图上的样本大小并相应地更新它们。然而,当更新直方图时,它会令人烦恼地闪烁。有什么办法可以避免这种情况吗?谢谢。

现在要在 jupyter 笔记本上运行的代码:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib notebook
from ipywidgets import *

n = 1000
x1 = np.random.normal(-2.5, 1, n)
x2 = np.random.gamma(2, 1.5, n)
x3 = np.random.exponential(2, n)+7
x4 = np.random.uniform(14,20, n)
x = [x1, x2, x3, x4]

fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(10,7))
axs = [ax1,ax2,ax3,ax4]

titles = ['x1\nNormal', 'x2\nGamma', 'x3\nExponential', 'x4\nUniform']
subplots_axes = [[-7,2,0,250], [0,4.5,0,250], [7,25,0,250], [14,20,0,250]]

bins = [np.arange(-6, 6, 0.5),
np.arange(0, 10, 0.5),
np.arange(7, 17, 0.5),
np.arange(14, 24, 0.5)]

fig.subplots_adjust(hspace=0.5)

def plt_dist(s, sample):
    axs[s].hist(x[s][:sample], bins=bins[s], linewidth=0, color='#1F77B4')
    axs[s].axis(subplots_axes[s])
    axs[s].set_title('{}'.format(titles[s]))
    axs[s].set_ylabel('Frequency')
    axs[s].set_xlabel('Value')
    axs[s].annotate('n = {}'.format(sample), xycoords='axes fraction', xy = [0.8,0.9])
    display(fig)

for s in range(0,4):
    sld_bar = interact(plt_dist, s = fixed(s), sample = widgets.IntSlider(min=100,max=1000+45,step=1,value=100))
Run Code Online (Sandbox Code Playgroud)

sam*_*sam 5

如果其他人遇到此问题,在交互函数中使用打印语句也可能导致闪烁。

fig, ax = plt.subplots()
@widgets.interact
def run(
    a = 1.2,
):
    ax.clear()
    print(1) # Comment this line to stop flickering
    ax.plot([1,2,3])
    display(fig)
Run Code Online (Sandbox Code Playgroud)


Imp*_*est 3

不太清楚是什么display(fig)会做什么或需要什么。

axs[s].clear()对我来说,删除该行并清除函数开头的轴 ( )plt_hist效果很好,并且“闪烁”不再存在。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib notebook
from ipywidgets import *

n = 1000
x1 = np.random.normal(-2.5, 1, n)
x2 = np.random.gamma(2, 1.5, n)
x3 = np.random.exponential(2, n)+7
x4 = np.random.uniform(14,20, n)
x = [x1, x2, x3, x4]

fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(10,7))
axs = [ax1,ax2,ax3,ax4]

titles = ['x1\nNormal', 'x2\nGamma', 'x3\nExponential', 'x4\nUniform']
subplots_axes = [[-7,2,0,250], [0,4.5,0,250], [7,25,0,250], [14,20,0,250]]

bins = [np.arange(-6, 6, 0.5),
np.arange(0, 10, 0.5),
np.arange(7, 17, 0.5),
np.arange(14, 24, 0.5)]

fig.subplots_adjust(hspace=0.5)

def plt_dist(s, sample):
    axs[s].clear() # <-- clear axes
    axs[s].hist(x[s][:sample], bins=bins[s], linewidth=0, color='#1F77B4')
    axs[s].axis(subplots_axes[s])
    axs[s].set_title('{}'.format(titles[s]))
    axs[s].set_ylabel('Frequency')
    axs[s].set_xlabel('Value')
    axs[s].annotate('n = {}'.format(sample), xycoords='axes fraction', xy = [0.8,0.9])
    #display(fig)  <--- delete this

for s in range(0,4):
    sld_bar = interact(plt_dist, s = fixed(s), 
              sample = widgets.IntSlider(min=100,max=1000+45,step=1,value=100))
Run Code Online (Sandbox Code Playgroud)