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

如何提取2D热力图指定区域计数并绘制1D柱状图?

提取热力图指定区域计数并绘制1D柱状图问题解决

问题描述

我正在Python中尝试绘制热力图指定区域内计数的柱状图。已完成热力图的编写,也实现了为指定区域绘制边界的功能,但卡在提取指定区域计数并绘制柱状图的环节。该热力图是一个2D直方图,我希望将其选中区域转换为1D直方图,x轴与热力图x轴一致,y轴为计数(即热力图中颜色代表的数值)。

现有代码(含关键修正)

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import LogNorm
from matplotlib.patches import Polygon

df = pd.read_csv('adc_tdc_7_disk26.txt', sep=',', header=None)

x, y = df[0].to_numpy(), df[1].to_numpy()

fig, ax = plt.subplots()
counts, xedges, yedges = np.histogram2d(x, y, bins=1000)
counts = counts.T 
# 关键修正:添加extent参数,让轴坐标匹配原始数据范围,否则区域点判断会出错
im = ax.imshow(counts, cmap='magma_r', origin='lower', norm=LogNorm(),
               extent=[xedges[0], xedges[-1], yedges[0], yedges[-1]])
fig.colorbar(im)
click_points = []

def onselect(event):
    click_points.append((event.xdata, event.ydata))
    # 20 clicks draws a boundary
    if len(click_points) >= 20:
        polygon_verts = click_points

        polygon_patch = plt.Polygon(polygon_verts, facecolor='none', edgecolor='r')

        ax.add_patch(polygon_patch)

        fig.canvas.draw()

        hist_points(polygon_patch, counts, xedges, yedges, x, y)
        click_points.clear()

解决方案

核心问题说明

原代码未设置imshow的extent参数,导致点击的坐标(bin索引)与原始数据值不在同一坐标系,区域内点的判断完全失效。修正后即可正常提取区域内数据,以下提供两种实现方式:


方法一:基于原始选中点统计(直观易实现)

直接提取区域内的原始x数据,用与原2D直方图相同的x bins重新统计计数,无需复用已有counts数组:

def hist_points(polygon_patch, counts, xedges, yedges, x, y):
    # 获取区域内点的掩码
    selected_mask = polygon_patch.contains_points(np.column_stack((x, y)))
    # 提取选中的x数据
    selected_x = x[selected_mask]
    # 用原2D直方图的x bins统计1D计数
    hist_counts, _ = np.histogram(selected_x, bins=xedges)
    
    # 绘制1D柱状图
    fig2, ax2 = plt.subplots()
    ax2.bar(xedges[:-1], hist_counts, width=np.diff(xedges), edgecolor='black', alpha=0.7)
    ax2.set_xlabel('X (same as heatmap)')
    ax2.set_ylabel('Count')
    ax2.set_title('1D Histogram of Selected Region')
    plt.show()

方法二:基于2D直方图的bin统计(高效适合大数据)

直接复用已生成的counts数组,判断每个bin是否在选中区域内,按x bin累加计数,避免重新遍历原始数据:

def hist_points(polygon_patch, counts, xedges, yedges, x, y):
    # 生成每个bin的中心坐标(用于判断是否在多边形内)
    x_centers = (xedges[:-1] + xedges[1:]) / 2
    y_centers = (yedges[:-1] + yedges[1:]) / 2
    xx, yy = np.meshgrid(x_centers, y_centers)
    bin_centers = np.column_stack((xx.ravel(), yy.ravel()))
    
    # 判断每个bin是否在选中区域内
    bin_in_polygon = polygon_patch.contains_points(bin_centers)
    bin_in_polygon = bin_in_polygon.reshape(counts.shape)
    
    # 按x bin累加区域内的计数
    hist_counts = counts[bin_in_polygon].reshape(-1, counts.shape[1]).sum(axis=0)
    
    # 绘制1D柱状图
    fig2, ax2 = plt.subplots()
    ax2.bar(xedges[:-1], hist_counts, width=np.diff(xedges), edgecolor='black', alpha=0.7)
    ax2.set_xlabel('X (same as heatmap)')
    ax2.set_ylabel('Count')
    ax2.set_title('1D Histogram of Selected Region')
    plt.show()

使用说明

  1. 运行修正后的代码,在热力图上点击20次绘制区域边界
  2. 完成点击后会自动弹出新窗口,显示对应区域的1D柱状图

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 19:09:54