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

Python中数据子集与全集高斯分布密度不一致问题求助

问题描述

我尝试为数据绘制密度分布图,现有数据框:

df = pd.read_csv('des_y3.csv')

通过以下代码计算全集密度:

from scipy.stats import gaussian_kde
# Extract x and y
x = df['column_1'].to_numpy()
y = df['column_2'].to_numpy()
xx, yy = np.mgrid[min(x):max(x):100j, min(y):max(y):100j]

positions = np.vstack([xx.ravel(), yy.ravel()])
values = np.vstack([x, y])
kernel = gaussian_kde(values)
f_1 = np.reshape(kernel(positions).T, xx.shape)

这部分运行正常,但筛选column_3等于'E'的子集计算密度时:

x = df['column_1'][df['column_3'] == 'E'].to_numpy()
y = df['column_2'][df['column_3'] == 'E'].to_numpy()
xx, yy = np.mgrid[min(x):max(x):100j, min(y):max(y):100j]

positions = np.vstack([xx.ravel(), yy.ravel()])
values = np.vstack([x, y])
kernel = gaussian_kde(values)
f_2 = np.reshape(kernel(positions).T, xx.shape)

发现子集数据量更少,但f_2的数值反而比f_1大。我需要让子集的密度与原始数据保持一致,同时绘图时子集与全集使用相同的配色方案和等高线水平,当前绘图代码如下:

# Create subplots for the first two components
fig, ax = plt.subplots(1, 2)

cfset = ax[0].contourf(xx, yy, f, cmap='coolwarm')
ax[0].imshow(np.rot90(f), cmap='coolwarm', extent=[xmin, xmax, ymin, ymax])
cset0 = ax[0].contour(xx, yy, f, colors='k')
ax[0].set_xlabel('X')
ax[0].set_ylabel('Y')
ax[0].set_title('All data')

cfset = ax[1].contourf(xx, yy, f0, cmap='coolwarm')
ax[1].imshow(np.rot90(f0), cmap='coolwarm', extent=[xmin, xmax, ymin, ymax])
cset = ax[1].contour(xx, yy, f0, cset0.levels, colors='k')
ax[1].set_xlim(xmin, xmax)
ax[1].set_ylim(ymin, ymax)
ax[1].set_xlabel('X')
ax[1].set_ylabel('Y')
ax[1].set_title('Subset')

plt.show()

请问该如何解决?


解决方案

1. 修正密度数值不一致的问题

gaussian_kde默认会将密度归一化到当前数据集的分布,即子集和全集的密度积分都为1。子集数据更集中,归一化后峰值自然更高。要让子集密度与全集保持同一量级,需按子集在全集中的占比缩放:

  • 计算子集样本量占比:subset_ratio = len(df[df['column_3'] == 'E']) / len(df)
  • 用该比例缩放子集密度:f_2_scaled = f_2 * subset_ratio

另外,计算网格xx, yy时必须使用全集的x、y范围,否则坐标区间不一致会影响视觉对比:

# 改用全集的x、y范围生成网格
x_full = df['column_1'].to_numpy()
y_full = df['column_2'].to_numpy()
xx, yy = np.mgrid[min(x_full):max(x_full):100j, min(y_full):max(y_full):100j]

2. 统一配色与等高线水平

  • 等高线部分已通过cset0.levels复用全集水平,只需确保缩放后的子集密度能匹配这些层级。
  • contourf默认会根据当前数据极值自动调整色标范围,需手动指定vmin和vmax为全集密度的极值,实现配色统一:
# 获取全集密度的极值
f_min = f_1.min()
f_max = f_1.max()

# 绘图时指定统一的色标范围
cfset = ax[0].contourf(xx, yy, f_1, cmap='coolwarm', vmin=f_min, vmax=f_max)
cfset = ax[1].contourf(xx, yy, f_2_scaled, cmap='coolwarm', vmin=f_min, vmax=f_max)

注意:contourf和imshow都是绘制填充密度图,重复使用会导致图层重叠,建议只保留其中一个。

完整修正代码示例

import pandas as pd
import numpy as np
from scipy.stats import gaussian_kde
import matplotlib.pyplot as plt

# 加载数据
df = pd.read_csv('des_y3.csv')

# 计算全集密度
x_full = df['column_1'].to_numpy()
y_full = df['column_2'].to_numpy()
xx, yy = np.mgrid[min(x_full):max(x_full):100j, min(y_full):max(y_full):100j]

positions = np.vstack([xx.ravel(), yy.ravel()])
values_full = np.vstack([x_full, y_full])
kernel_full = gaussian_kde(values_full)
f_1 = np.reshape(kernel_full(positions).T, xx.shape)

# 计算子集密度并缩放
subset_df = df[df['column_3'] == 'E']
x_sub = subset_df['column_1'].to_numpy()
y_sub = subset_df['column_2'].to_numpy()
values_sub = np.vstack([x_sub, y_sub])
kernel_sub = gaussian_kde(values_sub)
f_2 = np.reshape(kernel_sub(positions).T, xx.shape)

# 按子集占比缩放密度
subset_ratio = len(subset_df) / len(df)
f_2_scaled = f_2 * subset_ratio

# 绘图
fig, ax = plt.subplots(1, 2, figsize=(12, 5))

# 全集绘图
f_min = f_1.min()
f_max = f_1.max()
cfset0 = ax[0].contourf(xx, yy, f_1, cmap='coolwarm', vmin=f_min, vmax=f_max)
cset0 = ax[0].contour(xx, yy, f_1, colors='k')
ax[0].set_xlabel('X')
ax[0].set_ylabel('Y')
ax[0].set_title('All data')

# 子集绘图
cfset1 = ax[1].contourf(xx, yy, f_2_scaled, cmap='coolwarm', vmin=f_min, vmax=f_max)
cset1 = ax[1].contour(xx, yy, f_2_scaled, cset0.levels, colors='k')
ax[1].set_xlim(min(x_full), max(x_full))
ax[1].set_ylim(min(y_full), max(y_full))
ax[1].set_xlabel('X')
ax[1].set_ylabel('Y')
ax[1].set_title('Subset (scaled)')

# 添加统一色条
fig.colorbar(cfset0, ax=ax)

plt.tight_layout()
plt.show()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 13:55:58