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

如何用Python实现随minute_play列变化的动态2D直方图热力图

实现随minute_play动态变化的2D直方图(热力图)

我已编写如下可生成静态2D直方图(热力图)的Python代码,但需要创建随minute_play列动态变化的热力图,请问该如何实现?附上数据样例图、静态输出图及现有代码:

multicolor = ["#ffffff","#e2eeff", "#c3d8f9","#80bdff", "#42b0f5",
              "#a0e242", "#d1cb1c", "#a06a20", "#872a10", "#630d02", "#000000"]
bins = 100

densities,_,_ = np.histogram2d(heatmap_df.params_pos_x, heatmap_df.params_pos_y, bins=bins)
percentiles = [0,1,10,20,30,40,50,60,70,80,99,100]

bounds = []
for i in percentiles:
 bounds.append(np.percentile(np.unique(densities),i))

cmaplist = multicolor
cmap = mpl.colors.LinearSegmentedColormap.from_list(
           'Custom cmap',
            cmaplist,
            len(percentiles))
norm = mpl.colors.BoundaryNorm(bounds, cmap.N)
plt.hist2d(heatmap_df.params_pos_x,
           heatmap_df.params_pos_y,
      bins = bins,
      norm = norm,
       cmap = cmap)
cbar = plt.colorbar(ticks = bounds)
plt.show()

我曾尝试参考Plotly的热力图动画教程,但不清楚如何将现有代码迁移适配,恳请指导。


解决方案:用Plotly实现按minute_play分帧的动态热力图

核心思路

  1. 按minute_play字段分组,为每个时间切片计算独立的2D直方图数据
  2. 复用你定义的自定义色阶和分位数边界,确保所有帧的颜色标尺统一,避免视觉混乱
  3. 基于Plotly的Figure和Frame对象构建可交互的动画组件

完整适配代码

import numpy as np
import plotly.graph_objects as go
from matplotlib import colors as mpl_colors

# 复用原配置:自定义色阶、分位数参数
multicolor = ["#ffffff","#e2eeff", "#c3d8f9","#80bdff", "#42b0f5",
              "#a0e242", "#d1cb1c", "#a06a20", "#872a10", "#630d02", "#000000"]
bins = 100
percentiles = [0,1,10,20,30,40,50,60,70,80,99,100]

# 预先计算全局分位数边界(用全量数据保证所有帧颜色标尺一致)
full_densities, x_edges, y_edges = np.histogram2d(
    heatmap_df.params_pos_x, 
    heatmap_df.params_pos_y, 
    bins=bins
)
bounds = [np.percentile(np.unique(full_densities), p) for p in percentiles]

# 按minute_play分组生成动画帧
frames = []
unique_minutes = sorted(heatmap_df['minute_play'].unique())  # 排序保证时间顺序

for minute in unique_minutes:
    # 筛选当前分钟的数据子集
    subset = heatmap_df[heatmap_df['minute_play'] == minute]
    # 计算当前分钟的2D直方图(复用全局bins边缘,保证坐标对齐)
    densities, _, _ = np.histogram2d(
        subset.params_pos_x, 
        subset.params_pos_y, 
        bins=[x_edges, y_edges]
    )
    # 添加动画帧
    frames.append(go.Frame(
        data=[go.Heatmap(
            z=densities.T,  # Plotly的z轴需转置以匹配numpy输出格式
            x=x_edges,
            y=y_edges,
            colorscale=multicolor,
            zmin=bounds[0],
            zmax=bounds[-1],
            colorbar=dict(tickvals=bounds)
        )],
        name=str(minute)
    ))

# 创建初始图(用第一个分钟的数据)
first_minute = unique_minutes[0]
first_subset = heatmap_df[heatmap_df['minute_play'] == first_minute]
first_densities, _, _ = np.histogram2d(
    first_subset.params_pos_x, 
    first_subset.params_pos_y, 
    bins=[x_edges, y_edges]
)

fig = go.Figure(
    data=[go.Heatmap(
        z=first_densities.T,
        x=x_edges,
        y=y_edges,
        colorscale=multicolor,
        zmin=bounds[0],
        zmax=bounds[-1],
        colorbar=dict(tickvals=bounds, ticktext=[str(p) for p in percentiles])
    )],
    frames=frames,
    layout=go.Layout(
        title='随比赛分钟变化的位置热力图',
        xaxis_title='X坐标',
        yaxis_title='Y坐标',
        # 添加播放/暂停控制按钮
        updatemenus=[dict(
            type='buttons',
            showactive=True,
            buttons=[dict(
                label='播放',
                method='animate',
                args=[None, dict(frame=dict(duration=500, redraw=True), fromcurrent=True)]
            ), dict(
                label='暂停',
                method='animate',
                args=[[None], dict(frame=dict(duration=0, redraw=False), mode='immediate')]
            )]
        )],
        # 添加分钟选择滑块
        sliders=[dict(
            steps=[dict(
                method='animate',
                args=[[str(minute)], dict(mode='immediate', frame=dict(duration=300))]
            ) for minute in unique_minutes],
            currentvalue=dict(prefix='当前分钟: ')
        )]
    )
)

fig.show()

关键适配说明

  • 统一颜色标尺:用全量数据计算分位数边界,避免不同时间片的颜色标尺波动,确保跨帧对比的一致性
  • 坐标对齐:复用全局计算的x_edges和y_edges,保证所有帧的热力图网格完全重合
  • 色阶无缝迁移:直接将原自定义色阶列表传入Plotly的colorscale参数,完美保留原配色风格
  • 交互控制:内置播放/暂停按钮和分钟滑块,支持自动播放和手动切换时间片

内容的提问来源于stack exchange,提问作者Quang Dang Hong

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 16:15:02