You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Jupyter Notebook中实现3D数据的交互式2D直方图(悬停触发1D直方图)

解决方案

要实现Jupyter Notebook中悬停2D分箱时联动显示对应par3的1D直方图,核心是利用matplotlib的交互式事件处理,同时注意必须使用交互式后端。以下是完整实现代码:

%matplotlib widget
import numpy as np
import matplotlib.pyplot as plt

# 模拟3D参数数据
all_datas = np.random.rand(5, 10, 20) * 100
par1_bins = 5
par2_bins = 10
par3_bins = 20

# 创建双栏画布
fig, (ax0, ax1) = plt.subplots(1, 2, figsize=(10, 4))

# 绘制par1-par2的2D汇总热力图
sum_over_par3 = np.sum(all_datas, axis=2).transpose()
ax0.pcolor(sum_over_par3)
ax0.set_xlabel('par1')
ax0.set_ylabel('par2')
ax0.set_title('par1 vs par2 (sum over par3)')

# 初始化右侧1D直方图(空占位)
ax1.hist([], bins=par3_bins)
ax1.set_xlabel('par3')
ax1.set_ylabel('Count')
ax1.set_title('par3 distribution')

# 定义鼠标悬停事件处理函数
def hover_update(event):
    # 仅响应ax0内的鼠标移动事件
    if event.inaxes != ax0 or not event.xdata or not event.ydata:
        return
    
    # 将鼠标坐标转换为分箱索引
    i_par = int(np.floor(event.xdata))
    j_par = int(np.floor(event.ydata))
    
    # 索引合法性校验,避免越界
    if 0 <= i_par < par1_bins and 0 <= j_par < par2_bins:
        # 获取对应分箱的par3数据
        target_data = all_datas[i_par, j_par, :]
        
        # 更新右侧直方图
        ax1.clear()
        ax1.hist(target_data, bins=par3_bins)
        ax1.set_xlabel('par3')
        ax1.set_ylabel('Count')
        ax1.set_title(f'par1={i_par}, par2={j_par}')
        # 刷新画布生效
        fig.canvas.draw_idle()

# 绑定事件到画布
fig.canvas.mpl_connect('motion_notify_event', hover_update)

plt.tight_layout()
plt.show()

关键细节说明

  • 交互式后端:开头的%matplotlib widget是必须的——静态后端(如%matplotlib inline)无法响应鼠标事件,只有交互式后端才能触发回调函数。
  • 坐标转索引:pcolor的坐标轴范围默认对应分箱数量(比如par1有5个分箱,x轴范围是0~5),用np.floor()直接将鼠标坐标转为分箱索引即可。
  • 事件过滤:回调函数先判断鼠标是否在ax0区域内,避免无效触发;同时做索引边界检查,防止数组越界错误。
  • 画布刷新:更新直方图后调用draw_idle(),确保画布实时刷新显示新内容。

内容的提问来源于stack exchange,提问作者Stef1611

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 04:20:58