如何在二维密度图中设置百分比概率等高线?
实现KDE概率百分比等高线的方法
要把等高线设置为90%、50%这类概率百分比,核心是先计算对应概率的密度阈值,再用这些阈值绘制等高线。具体步骤如下:
- 计算网格面积:因为用离散网格计算KDE,每个网格单元的面积是
dx*dy,用来计算累积概率。 - 获取密度阈值:把KDE的密度值展平排序,通过累积求和找到对应累积概率的密度值(比如90%概率区域对应累积概率从0到0.9的部分,即密度从高到低累加至覆盖90%概率,对应的最低密度就是阈值)。
- 绘制带百分比的等高线:用计算出的阈值作为
contour的levels参数,同时自定义标注文本。
修改后的完整代码如下:
import pandas as pd import numpy as np import matplotlib.pyplot as plt from scipy import stats xls = pd.ExcelFile('CSL-results.xlsx') df = xls.parse("TAL"); TAL = df.dropna() TALx = TAL.values[:,0] TALy = TAL.values[:,1] xmin = 0 xmax = 80 ymin = 0 ymax = 1 # 生成网格 X, Y = np.mgrid[xmin:xmax:100j, ymin:ymax:100j] dx = (xmax - xmin)/100 dy = (ymax - ymin)/100 grid_area = dx * dy positions = np.vstack([X.ravel(), Y.ravel()]) TALvalues = np.vstack([TALx, TALy]) TALkernel = stats.gaussian_kde(TALvalues) fTAL = np.reshape(TALkernel(positions).T, X.shape) # 计算概率阈值 density_flat = fTAL.ravel() # 按密度从高到低排序 sorted_density = np.sort(density_flat)[::-1] # 计算累积概率(每个密度乘以网格面积后累加) cumulative_prob = np.cumsum(sorted_density * grid_area) # 定义需要的概率百分比 target_probs = [0.9, 0.5] # 找到对应阈值:累积概率首次超过目标值的位置对应的密度 levels = [] for prob in target_probs: idx = np.where(cumulative_prob >= prob)[0][0] levels.append(sorted_density[idx]) # 为了让等高线从高到低,把levels排序 levels.sort(reverse=True) fig = plt.figure(figsize = (10, 6), dpi = 200) ax = fig.gca() # 绘制等高线,指定levels cfsetTAL = ax.contour(X, Y, fTAL, levels=levels, colors='#6c2d6c') # 自定义标注文本,替换默认的密度值为百分比 ax.clabel(cfsetTAL, inline=1, fontsize=6, fmt={level: f"{int(prob*100)}%" for level, prob in zip(levels, target_probs)}) Hex_TAL = plt.hexbin(TALx,TALy, gridsize=50, mincnt=1, cmap='Blues') plt.show()
说明:
- 网格面积
grid_area的计算要和mgrid的步长对应,这里用100j生成100个间隔,所以步长是(max-min)/100。 - 累积概率的计算是把密度从高到低累加,因为我们要找的是包含指定百分比概率的高密度区域,比如90%概率区域就是密度最高的那些网格,它们的概率总和达到90%。
- 最后用字典把密度阈值映射成对应的百分比文本,让标注更直观。
内容的提问来源于stack exchange,提问作者Scott
相关产品推荐
相关产品推荐

