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

如何对两个KDE图做差值运算并展示差异热图?

问题

如何对两个不同的kdeplot做差值运算并展示差异?如图右上角所示,绿色气泡与红色气泡存在重叠区域,希望将两个数据集相减后展示差异——比如当某位置绿色数据集的密度数值大于红色时,该位置显示绿色。

用户原代码如下:

import matplotlib.pyplot as plt
from PIL import Image
import seaborn as sns
from functions.getMinimapExtent import getMinimapExtent
from functions.getMinimapPath import getMinimapPath

def getHeatmap(x, y, map:str, title:str, x1, y1):
    #x ~= [2054, 4225, 4234, 2134, 3552, 5632, ...]
    #y ~= [1452, 2354, 6423, 3256, 2341, 5532, ...]
    #x1 ~= [5323, 2535, 1535, 6433, 2356, 2353, ...]
    #y1 ~= [6435, 2212, 3555, 2366, 7312, 1643, ...]

    img = Image.open(getMinimapPath(map))
    minimapExtent = getMinimapExtent(map)
    plt.imshow(img, extent=minimapExtent)

    # set seaborn style
    sns.set_style("white")

    # Custom the color, add shade and bandwidth
    sns.kdeplot(x=x, y=y, cmap="Reds", shade=True, bw_adjust=.2, alpha=.6, thresh=0.25, zorder=-1)
    sns.kdeplot(x=x1, y=y1, cmap="Greens", shade=True, bw_adjust=.2, alpha=.6, thresh=0.25, zorder=-1)

    plt.title(title)
    plt.axis("off")
    plt.savefig("bot/data/img/heatmap.png", dpi=500, bbox_inches="tight")
    plt.close()

Seaborn Heatmap

解决方案

要实现两个KDE密度的差值可视化,需要手动计算两个数据集的核密度估计值,再对网格上的密度值做差值运算,最后根据差值结果绘制差异区域。步骤如下:

  1. 补充依赖工具:新增scipy.stats.gaussian_kde用于计算核密度,numpy生成对齐地图的网格点。
  2. 生成匹配底图的网格:根据地图的范围参数,生成均匀分布的x、y网格,确保坐标和底图完全对齐。
  3. 分别计算两个数据集的KDE密度:用和原代码一致的平滑度参数,计算每个网格点的密度值。
  4. 计算密度差值:用绿色数据集的密度减去红色数据集的密度,得到差值矩阵。
  5. 绘制目标差异区域:筛选出绿色密度大于红色的区域(差值>0),用绿色填充展示。

修改后的代码如下:

import matplotlib.pyplot as plt
from PIL import Image
import seaborn as sns
import numpy as np
from scipy.stats import gaussian_kde
from functions.getMinimapExtent import getMinimapExtent
from functions.getMinimapPath import getMinimapPath

def getHeatmap(x, y, map:str, title:str, x1, y1):
    # 加载底图和范围
    img = Image.open(getMinimapPath(map))
    minimapExtent = getMinimapExtent(map)
    x_min, x_max, y_min, y_max = minimapExtent

    plt.imshow(img, extent=minimapExtent)
    sns.set_style("white")

    # --------------------------
    # 计算两个数据集的KDE密度差值
    # --------------------------
    # 生成网格点(bins值越大精度越高,计算速度越慢,可按需调整)
    bins = 200
    xx, yy = np.meshgrid(np.linspace(x_min, x_max, bins),
                         np.linspace(y_min, y_max, bins))
    grid_points = np.vstack([xx.ravel(), yy.ravel()])

    # 计算红色数据集的KDE密度,bw_method对应原代码的bw_adjust
    kde_red = gaussian_kde(np.vstack([x, y]), bw_method=0.2)
    density_red = kde_red(grid_points).reshape(xx.shape)

    # 计算绿色数据集的KDE密度
    kde_green = gaussian_kde(np.vstack([x1, y1]), bw_method=0.2)
    density_green = kde_green(grid_points).reshape(xx.shape)

    # 计算密度差值:绿色 - 红色
    density_diff = density_green - density_red

    # --------------------------
    # 绘制差异区域
    # --------------------------
    # 只显示绿色密度大于红色的区域,用绿色填充
    plt.contourf(xx, yy, np.where(density_diff > 0, density_diff, np.nan),
                 cmap="Greens", alpha=0.6, zorder=-1)
    
    # 可选:若需要同时展示红色密度更高的区域,取消下面注释
    # plt.contourf(xx, yy, np.where(density_diff < 0, -density_diff, np.nan),
    #              cmap="Reds", alpha=0.6, zorder=-1)

    plt.title(title)
    plt.axis("off")
    plt.savefig("bot/data/img/heatmap.png", dpi=500, bbox_inches="tight")
    plt.close()

关键细节说明

  • bw_method=0.2和原代码的bw_adjust=.2效果一致,保证KDE的平滑程度不变。
  • bins参数控制网格精度,数值越大细节越丰富,但会增加计算耗时,可根据地图尺寸调整。
  • np.where用于筛选出绿色密度更高的区域,只保留有效差值部分,避免无意义的重叠显示。
  • zorder=-1确保差异图层在底图下方,不会遮挡地图内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 01:40:51