如何在图下方居中 matplotlib 滑块并重新标记滑块标签?

Posted

技术标签:

【中文标题】如何在图下方居中 matplotlib 滑块并重新标记滑块标签?【英文标题】:How to center matplotlib slider below figure and relabel slider label? 【发布时间】:2022-01-23 19:08:00 【问题描述】:

我创建了一个使用滑块播放动画的函数。每帧由条形图上方的热图(带颜色条)组成。该函数的参数由用于热图轴标签和条形图水平轴标签的文本标签列表、矩阵列表和用于条形图的列表列表组成。此外,还有一个时间窗口值,标记为win_value,因此第 0 帧对应时间 0,第 1 帧对应win_value,第 2 帧对应 2*win_value,依此类推。

函数代码如下:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
from matplotlib.widgets import Slider

def heatmap_barplot_animation(labels,M_list,bar_list,win_value):
    num_times=len(M_list)

    fig, ax = plt.subplots(2)
    plt.subplots_adjust(left=None, bottom=.2, right=None, top=.9, wspace=.2, hspace=.2)

    ax_time=fig.add_axes([0.25, 0.1, 0.65, 0.03])
    s_time = Slider(ax_time, 'Time', 0, num_times, valinit=0,valstep=1)

    def update_graph(val):
        i= s_time.val
        ax[0].cla()
        heatmap=ax[0].imshow(M_list[i-1*1],vmin=0, vmax=1, cmap='coolwarm', aspect='auto')

        ax[0].set_xticks(range(len(labels)))
        ax[0].set_xticklabels(labels,fontsize=10,)
        a.x[0].set_yticks(range(len(labels)))
        ax[0].set_yticklabels(labels,fontsize=10)

        ax0_divider = make_axes_locatable(ax[0])
        cax0 = ax0_divider.append_axes('right', size='7%', pad='2%')
        cb = fig.colorbar(heatmap, cax=cax0, orientation='vertical')

        ax[1].cla()
        ax[1].bar(labels,bar_list[i-1])
        ax[1].set_ylim(0, 1)

        plt.show()

    s_time.on_changed(update_graph)
    s_time.set_val(0)

一个包含 7 个标签、10 个帧和 0.25 秒窗口值的示例:

import random
labels=['a','b','c','d','e','f','g','h']
M_list=[np.random.rand(7,7) for i in range(10)]
bar_list=[[random.uniform(0,1) for i in range(Nc)] for t in range(Nt)]
win_value=.25

heatmap_barplot_animation(labels,M_list,bar_list,win_value)

动画的第三帧是这样的:

我似乎无法弄清楚执行以下操作需要哪些修改:

    使条形图下方的滑块居中。 更改条形图滑块,使其不再显示索引(上面的 3),而是显示相应的时间值,在本例中为 0.75 秒。

【问题讨论】:

【参考方案1】:

    对于您的第一个问题,将滑块置于子图上的一种方法是简单地使用 plt.subplots_adjust 调整子图的位置以匹配滑块的轴。在您的代码中,滑块的轴定义为:ax_time=fig.add_axes([0.25, 0.1, 0.65, 0.03]),因此您可能希望使用plt.subplots_adjust(left=0.25, bottom=.2, right=None, top=.9, wspace=.2, hspace=.2) 调整子图。您可以使用滑块的轴和子图的轴来获得所需的结果(请参阅下面的示例,滑块以子图为中心)。

    针对您的第二个问题,要重新标记滑块中的值,您只需将标签的 valmaxvalstep 值更改为 valmax=num_times*win_valuevalstep=win_value。要索引您的 M_listbar_list 数组,您需要将 i 声明为 i=int(s_time.val/win_value)

更多细节请看您在实现上述修改后提供的代码:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
from matplotlib.widgets import Slider
import random

def heatmap_barplot_animation(labels,M_list,bar_list,win_value):
    num_times=len(M_list)
    fig, ax = plt.subplots(2)
    
    plt.subplots_adjust(left=0.25, bottom=.2, right=None, top=.9, wspace=.2, hspace=.2)
    ax_time=fig.add_axes([0.25, 0.1, 0.65, 0.03])
    s_time = Slider(ax_time, 'Time',valinit=0,valmin=0,valmax=num_times*win_value,valstep=win_value)

    def update_graph(val):
        i=int(s_time.val/win_value)
        ax[0].cla()
        heatmap=ax[0].imshow(M_list[i-1*1],vmin=0, vmax=1, cmap='coolwarm', aspect='auto')

        ax[0].set_xticks(range(len(labels)))
        ax[0].set_xticklabels(labels,fontsize=10,)
        ax[0].set_yticks(range(len(labels)))
        ax[0].set_yticklabels(labels,fontsize=10)

        ax0_divider = make_axes_locatable(ax[0])
        cax0 = ax0_divider.append_axes('right', size='7%', pad='2%')
        cb = fig.colorbar(heatmap, cax=cax0, orientation='vertical')

        ax[1].cla()
        ax[1].bar(labels,bar_list[i-1])
        ax[1].set_ylim(0, 1)

        plt.show()

    s_time.on_changed(update_graph)
    s_time.set_val(0)

labels=['a','b','c','d','e','f','g','h']
Nc=8
Nt=10
M_list=[np.random.rand(Nc,Nc) for i in range(Nt)]
bar_list=[[random.uniform(0,1) for i in range(Nc)] for t in range(Nt)]
win_value=.25
heatmap_barplot_animation(labels,M_list,bar_list,win_value)

输出给出(在第 3 帧):

【讨论】:

这太棒了!谢谢。

以上是关于如何在图下方居中 matplotlib 滑块并重新标记滑块标签?的主要内容,如果未能解决你的问题,请参考以下文章

如何锁定滑块并防止使用鼠标将值更新到 dat.GUI 菜单

vue项目监听滑块并移除。

带有两个滑块的交互式 matplotlib 图

如何在引导程序中将井居中?

如何使整个图像比较滑块居中

如何制作这样的滑块