如何在基础R(非ggplot)中为多图添加指数与二次多项式趋势线
基础R绘制非线性趋势线解决方案
基础R完全支持绘制非线性趋势线,无需依赖仅能生成直线的abline(),核心思路是先拟合对应模型,生成连续时间序列的预测值,再用lines()绘制平滑趋势线。以下是针对你的数据的具体实现代码和说明:
核心步骤
- 拟合对应模型:
- 指标S:用
nls()拟合指数衰减模型(或对数转换后用lm(),稳定性更高) - 指标k、Bg、Br:用
lm()拟合二次多项式模型
- 指标S:用
- 生成连续时间序列的预测值,确保趋势线平滑
- 在散点图上用
lines()叠加趋势线
完整代码示例
1. 模拟示例数据(替换为你的真实数据)
set.seed(123) time <- seq(0, 12, by=2) treatment <- rep(c("Control", "Grazing"), each=length(time)) S <- c(100, 80, 65, 52, 42, 35, 30, 22, 18, 14, 11, 9) + rnorm(12, 0, 3) k <- c(0.1, 0.15, 0.22, 0.28, 0.3, 0.27, 0.12, 0.18, 0.25, 0.32, 0.35, 0.33) + rnorm(12, 0, 0.02) Bg <- k * 1.2 + rnorm(12, 0, 0.03) Br <- k * 0.8 + rnorm(12, 0, 0.02) decomp_data <- data.frame(time, treatment, S, k, Bg, Br)
2. 绘制多图并添加趋势线
# 设置2行2列的多图布局,调整边距避免标题/坐标轴重叠 par(mfrow = c(2, 2), mar = c(4, 4, 2, 1)) # --- 指标S:指数衰减趋势 --- plot(S ~ time, data = decomp_data, col = ifelse(treatment == "Control", "blue", "red"), pch = 16, main = "S: 指数衰减趋势", xlab = "时间", ylab = "S值") # 拟合对照样地模型(两种方法选其一) # 方法1:nls直接拟合指数模型 ctrl_S <- nls(S ~ a*exp(-b*time), data = decomp_data[decomp_data$treatment == "Control",], start = list(a = 100, b = 0.1)) # 方法2:对数转换后用线性模型(拟合更稳定) # ctrl_S_lm <- lm(log(S) ~ time, data = decomp_data[decomp_data$treatment == "Control",]) # 生成连续时间预测序列(保证趋势线平滑) pred_time <- seq(min(time), max(time), length.out = 100) # 对应方法1的预测 pred_ctrl_S <- predict(ctrl_S, newdata = data.frame(time = pred_time)) # 对应方法2的预测 # pred_ctrl_S <- exp(predict(ctrl_S_lm, newdata = data.frame(time = pred_time))) lines(pred_time, pred_ctrl_S, col = "blue", lwd = 2) # 拟合并绘制放牧样地趋势线 graz_S <- nls(S ~ a*exp(-b*time), data = decomp_data[decomp_data$treatment == "Grazing",], start = list(a = 100, b = 0.1)) pred_graz_S <- predict(graz_S, newdata = data.frame(time = pred_time)) lines(pred_time, pred_graz_S, col = "red", lwd = 2) legend("topright", legend = c("对照", "放牧"), col = c("blue", "red"), pch = 16, lwd = 2) # --- 指标k:二次多项式趋势 --- plot(k ~ time, data = decomp_data, col = ifelse(treatment == "Control", "blue", "red"), pch = 16, main = "k: 二次多项式趋势", xlab = "时间", ylab = "k值") # 拟合对照样地二次模型 ctrl_k <- lm(k ~ poly(time, 2, raw = TRUE), data = decomp_data[decomp_data$treatment == "Control",]) pred_ctrl_k <- predict(ctrl_k, newdata = data.frame(time = pred_time)) lines(pred_time, pred_ctrl_k, col = "blue", lwd = 2) # 拟合放牧样地二次模型 graz_k <- lm(k ~ poly(time, 2, raw = TRUE), data = decomp_data[decomp_data$treatment == "Grazing",]) pred_graz_k <- predict(graz_k, newdata = data.frame(time = pred_time)) lines(pred_time, pred_graz_k, col = "red", lwd = 2) legend("topright", legend = c("对照", "放牧"), col = c("blue", "red"), pch = 16, lwd = 2) # --- 指标Bg:二次多项式趋势 --- plot(Bg ~ time, data = decomp_data, col = ifelse(treatment == "Control", "blue", "red"), pch = 16, main = "Bg: 二次多项式趋势", xlab = "时间", ylab = "Bg值") ctrl_Bg <- lm(Bg ~ poly(time, 2, raw = TRUE), data = decomp_data[decomp_data$treatment == "Control",]) pred_ctrl_Bg <- predict(ctrl_Bg, newdata = data.frame(time = pred_time)) lines(pred_time, pred_ctrl_Bg, col = "blue", lwd = 2) graz_Bg <- lm(Bg ~ poly(time, 2, raw = TRUE), data = decomp_data[decomp_data$treatment == "Grazing",]) pred_graz_Bg <- predict(graz_Bg, newdata = data.frame(time = pred_time)) lines(pred_time, pred_graz_Bg, col = "red", lwd = 2) legend("topright", legend = c("对照", "放牧"), col = c("blue", "red"), pch = 16, lwd = 2) # --- 指标Br:二次多项式趋势 --- plot(Br ~ time, data = decomp_data, col = ifelse(treatment == "Control", "blue", "red"), pch = 16, main = "Br: 二次多项式趋势", xlab = "时间", ylab = "Br值") ctrl_Br <- lm(Br ~ poly(time, 2, raw = TRUE), data = decomp_data[decomp_data$treatment == "Control",]) pred_ctrl_Br <- predict(ctrl_Br, newdata = data.frame(time = pred_time)) lines(pred_time, pred_ctrl_Br, col = "blue", lwd = 2) graz_Br <- lm(Br ~ poly(time, 2, raw = TRUE), data = decomp_data[decomp_data$treatment == "Grazing",]) pred_graz_Br <- predict(graz_Br, newdata = data.frame(time = pred_time)) lines(pred_time, pred_graz_Br, col = "red", lwd = 2) legend("topright", legend = c("对照", "放牧"), col = c("blue", "red"), pch = 16, lwd = 2)
关键说明
poly(time, 2, raw=TRUE):确保拟合的是常规二次多项式(time + time²),若不加raw=TRUE会生成正交多项式,不影响趋势线形状但系数解释逻辑不同。- 指数模型初始参数:
nls()需要初始值start,可根据你的数据初始S值设置a,衰减系数b设为0.1左右;若拟合报错,优先选择对数转换的线性模型方法。 - 连续预测序列:
length.out=100保证趋势线足够平滑,可根据需求调整数值。
内容的提问来源于stack exchange,提问作者EBH
相关产品推荐
相关产品推荐

