如何用第三个变量加权实现Matplotlib/Seaborn的加权KDE散点图?
带权重的二维核密度图优化实现
问题背景
我有一组二维分布的点,使用sns.kdeplot可正常绘制密度图。但希望引入第三个变量,使该变量值较高的点在核密度估计时拥有更高权重。为展示预期效果,生成了如下数据集:
import numpy as np import matplotlib.pyplot as plt import seaborn as sns import pandas as pd from scipy.stats import multivariate_normal data_points = multivariate_normal([0.0, 0.0], [[9, 3], [3,3]]).rvs(250) df = pd.DataFrame(data=data_points, columns=['x', 'y']) df['intensity'] = round(np.sqrt(df['x']**2 + df['y']**2))
目前通过重复intensity变量对应行数的方式模拟权重效果:
df_repeat = df.loc[df.index.repeat(df['intensity'])]
对比绘图代码:
fig, ax = plt.subplots(1,2) sns.kdeplot(ax = ax[0], data =df, x = 'x',y = 'y') sns.kdeplot(ax = ax[1], data =df_repeat, x = 'x',y = 'y')
这种方式能达到预期效果,但存在数据冗余、效率较低的问题,有没有更简洁的实现方法?
优化方案
直接使用seaborn.kdeplot内置的weights参数即可,无需通过重复行模拟权重。该参数可直接传入每个样本对应的权重值,核密度估计过程会自动根据权重分配样本的贡献度,效果和重复行完全一致,但更高效简洁。
优化后的完整代码:
import numpy as np import matplotlib.pyplot as plt import seaborn as sns import pandas as pd from scipy.stats import multivariate_normal # 生成数据集 data_points = multivariate_normal([0.0, 0.0], [[9, 3], [3,3]]).rvs(250) df = pd.DataFrame(data=data_points, columns=['x', 'y']) df['intensity'] = round(np.sqrt(df['x']**2 + df['y']**2)) # 绘制对比图 fig, ax = plt.subplots(1, 2, figsize=(12, 5)) # 无权重的原始密度图 sns.kdeplot(ax=ax[0], data=df, x='x', y='y', fill=True) ax[0].set_title('无权重核密度图') # 带权重的密度图 sns.kdeplot(ax=ax[1], data=df, x='x', y='y', weights=df['intensity'], fill=True) ax[1].set_title('带intensity权重的核密度图') plt.tight_layout() plt.show()
方案优势
- 内存高效:无需创建冗余的重复行数据集,避免权重值较大时的数据膨胀
- 代码简洁:直接通过参数声明权重逻辑,可读性更强
- 计算高效:减少了数据复制的开销,核密度估计过程更快速
内容的提问来源于stack exchange,提问作者user37292
相关产品推荐
相关产品推荐

