生态学一般遵循从复杂的真实现象中得到普适性的自然规律的原则。对于土壤生态学的研究,土壤剖面是一个非常热门的研究方向。但是由于地质环境的差异性,土壤剖面也具有同样的差异性,这对我们研究土壤剖面产生了阻碍。面对不同地质环境的土壤剖面数据,怎么把这些数据进行整合,减弱因环境差异性和实验操作所导致的误差即白噪声,达到去噪的目的,这是目前所面临的问题。现在,移动平均模型可以很好的解决面临的问题。在数据预处理中,移动平均(Moving Average)是一种最基本、最常用的平滑降噪技术。它通过对原始数据序列中相邻的若干个数据点进行加权或等权平均,从而减少随机波动(即白噪声)的影响,揭示出数据背后的长期趋势或低频成分。其中,移动平均 又可以分为简单移动平均 (SMA),加权移动平均 (WMA),指数加权移动平均 (EWMA)。
下面,我们以随机的土壤有机碳剖面数据为例进行代码的讲解。数据如下所示。
这些数据处理的逻辑是,首先对Soil depth进行取中值,例如0-10记为5。然后,将所有同一剖面的数据进行取均值,得到一个全剖面的数据。最后,使用这个数据进行移动平均模型的拟合。
具体代码如下所示:
import reimport pandas as pdimport matplotlib.pyplot as plt# 读取数据file_path = r"E:\R\mata\SOC.xlsx"df = pd.read_excel(file_path)# 计算深度中值def depth_midpoint(depth_str): s = str(depth_str).replace("–", "-").replace("—", "-").strip() a, b = map(float, s.split("-")) return (a + b) / 2df["depth_mid"] = df["Soil depth"].apply(depth_midpoint)# 计算各深度层平均SOCdepth_mean = ( df.groupby("depth_mid", as_index=False) .agg(mean_SOC=("SOC", "mean")) .sort_values("depth_mid"))# 指数加权移动平均(alpha 可调,0~1)alpha = 0.5depth_mean["EWMA"] = depth_mean["mean_SOC"].ewm(alpha=alpha, adjust=False).mean()# 绘图(单一平滑曲线)plt.figure()plt.plot(depth_mean["EWMA"], depth_mean["depth_mid"])plt.gca().invert_yaxis()plt.xlabel("SOC (mg/g)")plt.ylabel("Soil Depth (cm)")plt.title("EWMA Smoothed SOC Profile")plt.show()
通过这个代码,即可得到如下示意图
从这个示例图可以得到,土壤有机碳含量随深度衰减而降低,此外,在土层30-40cm处,有明显波动。
在此基础上,我们又采用了LOESS 拟合,得到更平滑的一般曲线。具体完整代码如下:
# ============================================================# 完整流程:SOC 随深度变化的一般曲线# 1) 读取 Excel# 2) Soil depth 取中值# 3) 按深度层求平均 SOC(总体剖面)# 4) EWMA 预平滑# 5) 基于 EWMA 的 LOESS 拟合,得到更平滑的一般曲线# 6) 绘图(深度轴反转)# ============================================================import numpy as npimport pandas as pdimport matplotlib.pyplot as pltfrom statsmodels.nonparametric.smoothers_lowess import lowess# --------------------------# 1. 读取数据# --------------------------file_path = r"E:\R\mata\SOC.xlsx" # 改成你的路径df = pd.read_excel(file_path)# --------------------------# 2. Soil depth 取中值# --------------------------def depth_midpoint(depth_str): s = str(depth_str).replace("–", "-").replace("—", "-").strip() a, b = map(float, s.split("-")) return (a + b) / 2.0df["depth_mid"] = df["Soil depth"].apply(depth_midpoint)# --------------------------# 3. 按深度层求平均 SOC(总体剖面)# --------------------------depth_mean = ( df.groupby("depth_mid", as_index=False) .agg(mean_SOC=("SOC", "mean"), n=("SOC", "count")) .sort_values("depth_mid") .reset_index(drop=True))# --------------------------# 4. EWMA 预平滑# --------------------------alpha = 0.5 # 可调:越大越贴近原始,越小越平滑depth_mean["EWMA"] = depth_mean["mean_SOC"].ewm(alpha=alpha, adjust=False).mean()# --------------------------# 5. LOESS 拟合(基于 EWMA)# --------------------------frac = 0.3 # 可调:越大越平滑(0.25~0.4 常用)z = depth_mean["depth_mid"].to_numpy()soc_ewma = depth_mean["EWMA"].to_numpy()# lowess 返回 (z, soc_loess) 的数组(按 z 排序)loess_out = lowess(endog=soc_ewma, exog=z, frac=frac, it=0, return_sorted=True)z_loess = loess_out[:, 0]soc_loess = loess_out[:, 1]# --------------------------# 6. 绘图:散点(均值)+ EWMA + LOESS 曲线# --------------------------plt.figure()plt.scatter(depth_mean["mean_SOC"], depth_mean["depth_mid"], label="Depth mean (points)")plt.plot(depth_mean["EWMA"], depth_mean["depth_mid"], label=f"EWMA (alpha={alpha})")plt.plot(soc_loess, z_loess, label=f"LOESS on EWMA (frac={frac})")plt.gca().invert_yaxis() # 深度向下增加plt.xlabel("SOC (mg/g)")plt.ylabel("Soil Depth (cm)")plt.title("General SOC-Depth Curve (EWMA + LOESS)")plt.legend()plt.tight_layout()plt.show()# --------------------------# 7. 输出拟合结果表(可选)# --------------------------result = depth_mean.copy()# 将 LOESS 拟合值插值回原深度点,方便导出/对比result["LOESS_on_EWMA"] = np.interp(result["depth_mid"].to_numpy(), z_loess, soc_loess)print(result)# 如需导出结果:# result.to_excel("SOC_depth_EWMA_LOESS_results.xlsx", index=False)
由此代码,可以得到:
通过上图,我们得到一下结论:土壤有机碳含量总体上随剖面深度增加而持续下降,呈现明显的垂直递减趋势。0–20 cm 表层 SOC 含量最高,是主要碳储存层,表明有机质输入和生物活动主要集中于浅层土壤。20–80 cm 深度范围内 SOC 下降速率减缓,表现为渐进式衰减,说明有机碳在该层具有一定的稳定性和物理保护作用。在 100 cm 以下,SOC 含量趋于低值并接近稳定,表明深层土壤以稳定碳库为主,活跃碳输入有限。整体曲线形态符合典型的指数衰减型垂直分布模式,反映了有机碳随深度递减的普遍生态规律。
最后,得到了去除白噪声的多剖面拟合曲线。