如何计算2D KDE图最低密度外层的面积?
如何获取Seaborn KDE Plot的密度水平并计算最外层面积
问题原因:get_array()返回None的原因
你调用kde_plot.collections[0].get_array()返回None,是因为未设置fill=True时,Seaborn生成的是LineCollection对象,它的get_array()方法并不存储密度水平值。密度水平和对应的轮廓路径需要从ContourSet对象中提取。
解决方案1:从已生成的绘图对象中提取并计算面积
修改代码,找到ContourSet对象来获取levels和路径,再计算面积:
import numpy as np import seaborn as sns import matplotlib.pyplot as plt from matplotlib.contour import ContourSet # 生成数据 x = np.linspace(0, 10, 100) y = x**2 data = {"X": x, "Y": y} # 绘制KDE图 kde_plot = sns.kdeplot(data=data, x="X", y="Y", common_norm=False, color='blue') # 找到ContourSet对象 contour_set = None for child in kde_plot.get_children(): if isinstance(child, ContourSet): contour_set = child break if contour_set: # 获取密度水平,levels按密度从小到大排序,第一个就是最外层的水平 levels = contour_set.levels print(f"密度水平:{levels}") # 获取最外层的所有路径 outer_paths = contour_set.collections[0].get_paths() # 计算总面积 total_area = 0 for path in outer_paths: # 仅处理有效闭合路径 if path.vertices.shape[0] > 2: total_area += abs(path.area) print(f"最外层面积:{total_area}") plt.title('2D KDE Plot with Custom Data') plt.xlabel('X') plt.ylabel('Y') plt.show()
解决方案2:直接计算KDE并生成等高线(更可靠可控)
跳过绘图对象提取,直接用scipy计算KDE,生成网格密度值后创建等高线,再计算面积。这种方法避免了绘图对象的依赖,更灵活:
import numpy as np import matplotlib.pyplot as plt from scipy.stats import gaussian_kde # 生成数据 x = np.linspace(0, 10, 100) y = x**2 # 计算KDE xy = np.vstack([x, y]) # 使用Seaborn默认的Scott带宽方法 kde = gaussian_kde(xy, bw_method='scott') # 生成高密度网格,提升面积计算精度 xmin, xmax = x.min() - 1, x.max() + 1 ymin, ymax = y.min() - 1, y.max() + 1 xx, yy = np.meshgrid(np.linspace(xmin, xmax, 2000), np.linspace(ymin, ymax, 2000)) zz = kde(np.vstack([xx.ravel(), yy.ravel()])).reshape(xx.shape) # 生成等高线,获取ContourSet cs = plt.contour(xx, yy, zz) # 最外层对应第一个密度水平 outer_paths = cs.collections[0].get_paths() # 计算总面积 total_area = 0 for path in outer_paths: if path.vertices.shape[0] > 2: total_area += abs(path.area) print(f"最外层面积:{total_area}") # 可选:绘制KDE图验证 plt.contourf(xx, yy, zz, alpha=0.7, levels=cs.levels) plt.scatter(x, y, s=10, c='red') plt.title('2D KDE with Area Calculation') plt.xlabel('X') plt.ylabel('Y') plt.show()
关键说明
- 密度水平
levels默认按从小到大排序,第一个值对应最外层(最低密度、面积最大)的轮廓。 - 计算面积时需过滤无效路径(顶点数少于3的非闭合路径),并取面积绝对值确保结果为正。
- 提升网格分辨率(如从1000改为2000)可以提高面积计算的精度,但会增加计算时间。
内容的提问来源于stack exchange,提问作者ilan
相关产品推荐
相关产品推荐

