当前位置:首页>python>期刊图片复现|Python实现非线性极值约束分析及阈值响应特征分析

期刊图片复现|Python实现非线性极值约束分析及阈值响应特征分析

  • 2026-10-11 06:34:27
期刊图片复现|Python实现非线性极值约束分析及阈值响应特征分析

代码绘制成果展示

论文:Driving mechanisms and threshold identification of landscape ecological  risk: A nonlinear perspective from the Qilian Mountains, China
论文原图
此图系统展示了海拔、温度、降水和风速四个关键环境因子对LERI的非线性约束效应及临界阈值。图中的四行从上至下分别对应海拔、温度、降水和风速作为横坐标,纵坐标为LERI值。左列为散点及约束线图,通过密集的蓝色数据点和最优拟合的红色边界线展示了特定环境条件下生态风险所能达到的最高容忍边界;中间为数据密度热图,利用从深蓝到深红的渐变色谱直观反映了实际观测数据点在不同变量区间内的空间分布集中程度;右列则为阈值识别图,在绿色渐变背景下通过限制性三次样条曲线定位了约束关系发生显著突变的临界阈值点。
此套代码实现了环境生态变量对目标指数非线性极值响应的自动化阈值分析与可视化流程。代码首先是将连续的自变量数据等距划分为100个区间,并提取有效区间内数据的第98百分位数作为理论上的上限约束边界点;随后对这些边界点展开建模:一方面遍历拟合六种传统数学方程(线性、多项式、指数、对数、幂函数)并以最大 R2 为输出最佳基准曲线,另一方面利用限制性三次样条回归(RCS)捕捉复杂的非单调边界,并通过遍历自由度寻找最小AIC以防止过度拟合;接着,在RCS拟合出的平滑曲线上,通过连续求导计算局部最大曲率,从而锁定系统响应发生剧烈转折的临界阈值点;最后,绘制出反映数据分布的散点图、聚集热力图,以及带有渐变色与阈值线标注的约束图。
注意:代码仅靠10个样本去推算98%分位线是非常不可靠的。建议在实际应用时,应根据总数据量将此阈值提高,以确保提取出的极值边界点具有足够的统计代表性。
仿图
多种配色

代码解释

第一部分

库的导入以及字体设置
# =========================================================================================# ====================================== 1. 环境设置 =======================================# =========================================================================================import osimport numpy as npimport pandas as pdimport matplotlib.pyplot as pltfrom matplotlib.colors import LinearSegmentedColormap

第二部分

设置颜色库
# =========================================================================================# ======================================2.颜色库=======================================# =========================================================================================COLOR_SCHEMES = {    1: ['#0000CD', '#FF0000', '#2E8B57', '#9400D3'],}

第三部分

曲线拟合函数:主要目的是在多种候选数学模型中,自动为当前散点寻找最能代表数据趋势的最优模型。尝试拟合 6 种不同的曲线:线性、二次多项式、三次多项式、对数、指数和幂函数。
# =========================================================================================# ======================================3.曲线拟合函数=======================================# =========================================================================================def fit_best_curve(x, y, x_smooth):    models = {}  # 用于存储模型    n = len(x)  # 数据点数量    # 线性回归    p1 = np.polyfit(x, y, 1)    models['Linear'] = (np.poly1d(p1)(x), np.poly1d(p1)(x_smooth), 1)    # 二次多项式    p2 = np.polyfit(x, y, 2)    models['Poly2'] = (np.poly1d(p2)(x), np.poly1d(p2)(x_smooth), 2)    # 三次多项式    p3 = np.polyfit(x, y, 3)    models['Poly3'] = (np.poly1d(p3)(x), np.poly1d(p3)(x_smooth), 3)    has_non_positive = np.min(x) <= 0  # 检查是否存在小于等于0的值    best_r2 = -float('inf')  # 初始化最高R2    best_y_smooth = None  # 初始化最佳平滑y值    best_p_val = 1.0  # 初始化最佳P值    y_mean = np.mean(y)  # y的均值    ss_tot = np.sum((y - y_mean) ** 2) + 1e-8  # 计算总平方和,加极小值防分母为零        # 如果当前模型R2更好        if r2 > best_r2:            best_r2 = r2  # 更新最佳R2            best_y_smooth = y_pred_smooth  # 更新对应的预测曲线Y值            best_p_val = p_val  # 更新对应P值    return best_y_smooth, best_r2, best_p_val  # 返回平滑预测值、R2和P值

第四部分

阈值点寻找函数:用于计算平滑曲线上曲率变化最剧烈的地方也就是临界阈值点。
# =========================================================================================# ======================================4.寻找曲线拐点函数=======================================# =========================================================================================def find_inflection_threshold(x, y):    y_double_prime = np.gradient(y_prime) / (dx + 1e-8)  # 计算二阶导数    curvature = np.abs(y_double_prime) / (1 + y_prime ** 2) ** 1.5  # 计算曲率    margin = int(len(x) * 0.1)  # 忽略前后10%的数据以避免边界效应    valid_curvature = curvature[margin:-margin]  # 提取中间部分的曲率    max_idx = margin + np.argmax(valid_curvature)  # 寻找最大曲率位置对应原始数据的索引    return max_idx  # 返回拐点索引

第五部分

散点图绘制函数:制展示底层数据与边界限制拟合效果带有约束线的散点图。包括原始数据散点、由分箱数据提取出的98分位边界折线,通过 fit_best_curve 拟合出的最佳平滑约束曲线。
# =========================================================================================# ======================================6.散点图绘制函数=======================================# =========================================================================================def draw_scatter(ax, df, feature_col, xlabel_text, analysis_res, scheme_id):    scatter_pt_c, scatter_line_c, _, _ = COLOR_SCHEMES[scheme_id]  # 获取散点及拟合线颜色    # 绘制散点    r2 = analysis_res['r2']  # 获取分析结果中的R2    p_val = analysis_res['p_value']  # P值    # 设置显著性标记    if p_val < 0.001:        p_text = r'p < 0.001'    elif p_val < 0.01:        p_text = r'p < 0.01'    elif p_val < 0.05:        p_text = r'p < 0.05'    else:        p_text = f'p={p_val:.3f}'    # 添加文本标注    ax.text(0.65,  # x            0.88,  # y            f'$R^2={r2:.4f}$',  # 文本            fontsize=22,  # 字体大小            transform=ax.transAxes)  # 坐标系    ax.text(0.65,  # x            0.78,  # y            f'${p_text}$',  # 文本            fontsize=22,  # 大小            transform=ax.transAxes)  # 坐标系    apply_axis_styles(ax, df, feature_col, xlabel_text)  # 设置轴和刻度

第六部分

热图绘制函数:用于将密集的散点数据转换为二维核密度分布热图,以便更直观地观察数据在二维空间内的集中趋势。
# =========================================================================================# ======================================7.热图绘制函数=======================================# =========================================================================================def draw_heatmap(fig, ax, df, feature_col, xlabel_text, scheme_id):    scatter_pt_c, scatter_line_c, _, _ = COLOR_SCHEMES[scheme_id]  # 提取配色    # 创建渐变色    custom_cmap = LinearSegmentedColormap.from_list(f'cmap_{scheme_id}',                                                    ['#101030', scatter_pt_c, '#f5f5f5', scatter_line_c])    if len(x_data) > 10000:        idx = np.random.choice(len(x_data), 10000, replace=False)  # 无放回抽样        x_sample = x_data[idx]  # x轴抽样数据        y_sample = y_data[idx]  # y轴抽样数据    else:        x_sample = x_data  # x        y_sample = y_data  # y    # 绘制颜色条    cbar = fig.colorbar(h, cax=cax, format='%.4f')    # 颜色条顶部标题    cbar.ax.set_title('Density', fontsize=16, pad=15)    cbar.ax.tick_params(labelsize=14)  # 颜色条刻度标注    apply_axis_styles(ax, df, feature_col, xlabel_text)  # 设置轴和刻度

第七部分

RCS图绘制函数:绘制RCS的拟合曲线、渐变阴影面积以及关键拐点。
# =========================================================================================# ======================================8.RCS绘制函数======================================# =========================================================================================def draw_rcs(ax, df, feature_col, xlabel_text, analysis_res, scheme_id):    _, _, rcs_fill_c, rcs_pt_c = COLOR_SCHEMES[scheme_id]  # 提取配色    x_smooth = analysis_res['x_smooth']  # 平滑x    y_bottom = 0.0  # 曲线下面积的底部参考线    im.set_clip_path(patch)  # 把之前创建的曲线路径作为掩膜实现曲线下渐变填充    # 绘制RCS主平滑线    ax.plot(x_smooth,  # x            y_rcs,  # y            color='#2C2C2C',  # 颜色            linestyle='--',  # 虚线            linewidth=1.5)  # 粗细    x_min_data, x_max_data = df[feature_col].min(), df[feature_col].max()  # 真实数据x极值    x_pad = (x_max_data - x_min_data) * 0.05  # 两侧留白    y_pad = (1.0 - 0.0) * 0.05  # y两侧六百    # 文本    ax.text(threshold_x,  # x            threshold_y - 0.1,  # y            f'({threshold_x:.2f},'  # 文本x            f' {threshold_y:.4f})',  # 文本y            fontsize=16,  # 大小            ha='center',  # 水平            va='top')  # 垂直    apply_axis_styles(ax, df, feature_col, xlabel_text)  # 设置轴和刻度

第八部分

执行部分:包括数据的读取,绘图结果保存设置、分析、绘图等
# =========================================================================================# ======================================9.执行部分=======================================# =========================================================================================if __name__ == '__main__':    all_analysis_results = {}  # 存储各特征分析结果    # 遍历特征    for col, xlabel in feature_configs:        num_bins = 100  # 分箱数        x_data = df_real[col]  # 取该特征数据        bins = np.linspace(x_data.min(), x_data.max(), num_bins + 1)  # 生成等间距的分箱区间        bin_centers = []  # 存储分箱中点的列表        boundary_y = []  # 存储边界Y值(98分位数)的列表        # 遍历分箱        for i in range(num_bins):            mask = (x_data >= bins[i]) & (x_data < bins[i + 1])  # 生成当前分箱的数据掩码            y_in_bin = df_real['LERI'][mask]  # 提取落入当前分箱的目标值            if len(y_in_bin) > 10:                bin_centers.append(0.5 * (bins[i] + bins[i + 1]))  # 计算当前分箱中心坐标                boundary_y.append(np.percentile(y_in_bin, 98))  # 计算箱内数据的第98百分位数作为边界    # 是否批量绘图    plot_all = True    schemes_to_run = list(COLOR_SCHEMES.keys()) if plot_all else [1]  # 获取配色    # 遍历配色进行绘图    for scheme_id in schemes_to_run:        print(f'正在绘制并保存方案:[{scheme_id}]')        fig_combo.tight_layout(w_pad=0.0, h_pad=2)  # 组图布局调整        # 保存组图        fig_combo.savefig(os.path.join(BASE_DIR, f'Combined_AllFeatures_scheme_{scheme_id}.png'), dpi=300,                          bbox_inches='tight')        plt.close(fig_combo)  # 关闭

如何应用到你自己的数据

1.设置原始数据的保存路径,执行部分:

df_real = pd.read_excel(r'data.xlsx') 

2.设置绘图结果的保存路径,执行部分:

BASE_DIR = r'分析'  # 保存路径DIR_SCATTER = os.path.join(BASE_DIR, 'Scatter')  # 散点图保存路径DIR_HEATMAP = os.path.join(BASE_DIR, 'Heatmap')  # 热力图保存路径DIR_RCS = os.path.join(BASE_DIR, 'RCS')  # RCS图保存路径

3.设置特征的单位,执行部分:

feature_configs = [    ('Elevation', 'Elevation/m'),    ('Temperature', 'Temperature/°C'),    ('Precipitation', 'Precipitation/mm'),    ('WindSpeed', 'Wind speed(m/s)')]

4.设置是否要进行批量绘图,执行部分:

plot_all = True

推荐

期刊图片复现|Python绘制配对云雨图
期刊图片复现|Python绘制SHAP交互作用与依赖趋势图
Python 空间解释性机器学习实战:基于 RF 与 GeoShapley 的全流程代码解析
期刊图片复现|Python回归分析全流程深度解析-回归拟合图、SHAP特征重要性总览图、交互作用强度气泡图、单特征依赖图、双特征交互效应图

获取方式

公众号中的所有所有的免费代码都已经下架了,都并入到付费部分里了,付费合集代码和数据的购买通道已经开通,全部合集100元,后续将会持续更新,决定购买请后台私信我,注意只会分享练习数据和代码文件,不会提供答疑服务,代码文件中已经包含了每行代码的完整注释,购买前请确保真的需要!!!

最新文章

随机文章