在R中拟合y=ab^x指数模型并在图中显示正确方程的方法
解决指数模型方程显示问题的方法
问题根源
stat_poly_eq是为多项式线性模型设计的,当你传入formula = y ~ exp(x)时,它会把exp(x)当成单一的线性预测项,输出的是y = β₀ + β₁·exp(x)这种线性形式,而非你需要的指数模型y = abˣ。另外你当前用stat_smooth(method="lm", formula=y~exp(x))拟合的模型也不是标准指数模型,它本质是带指数项的线性模型,和目标模型y=abˣ完全不同。
正确解决方案
针对目标指数模型y=abˣ,有两种可行方案,都能在图中显示正确的指数形式方程:
方案1:非线性最小二乘拟合(直接拟合y=abˣ)
用nls直接拟合非线性指数模型,手动提取参数后用annotate添加方程和R²值:
y <- c(0.04, 0.04, 0.03, 0.03, 0.04, 0.03, 0.02, 0.03, 0.03, 0.02, 0.08, 0.04, 0.04, 0.07, 0.04, 0.05, 0.12, 0.05, 0.13, 0.11, 0.11, 0.33, 0.03, 0.08) x <- c(3.75, 4.25, 1.77, 4.24, 2.99, 3.82, 1.85, 3.17, 2.64, 2.10, 4.23, 3.81, 3.55, 3.73, 3.85, 4.31, 4.35, 3.80, 7.26, 5.91, 8.15, 8.56, 7.49, 8.12) df <- data.frame(x, y) # 拟合非线性指数模型,start参数是初始值,可根据数据调整 nls_fit <- nls(y ~ a * b^x, data = df, start = list(a = 0.01, b = 1.2)) params <- coef(nls_fit) a_val <- round(params["a"], 4) b_val <- round(params["b"], 4) # 计算R²值 ss_res <- sum(residuals(nls_fit)^2) ss_tot <- sum((df$y - mean(df$y))^2) r_sq <- round(1 - ss_res/ss_tot, 4) # 构建支持LaTeX解析的方程和R²文本 eq_text <- paste0("y == ", a_val, " \\times ", b_val, "^x") r_sq_text <- paste0("R^2 == ", r_sq) # 绘图 ggplot(data = df, aes(x = x, y = y)) + geom_point(size = 3) + stat_smooth(method = "nls", formula = y ~ a * b^x, start = list(a = 0.01, b = 1.2), se = TRUE) + annotate("text", x = 0.1, y = 0.85, label = eq_text, parse = TRUE, size = 3.5, hjust = 0) + annotate("text", x = 0.1, y = 0.8, label = r_sq_text, parse = TRUE, size = 3.5, hjust = 0) + theme_classic()
方案2:对数转换后拟合线性模型
把指数模型y=abˣ取自然对数,转换为线性模型ln(y)=ln(a)+x·ln(b),拟合后再转换回指数形式显示:
# 拟合对数转换后的线性模型 lm_fit <- lm(log(y) ~ x, data = df) coefs <- coef(lm_fit) a_val <- round(exp(coefs[1]), 4) b_val <- round(exp(coefs[2]), 4) r_sq <- round(summary(lm_fit)$r.squared, 4) # 构建支持LaTeX解析的方程和R²文本 eq_text <- paste0("y == ", a_val, " \\times ", b_val, "^x") r_sq_text <- paste0("R^2 == ", r_sq) # 绘图,用stat_function绘制指数模型曲线 ggplot(data = df, aes(x = x, y = y)) + geom_point(size = 3) + stat_function(fun = function(x) a_val * b_val^x, color = "#00BFC4", linetype = 1) + annotate("text", x = 0.1, y = 0.85, label = eq_text, parse = TRUE, size = 3.5, hjust = 0) + annotate("text", x = 0.1, y = 0.8, label = r_sq_text, parse = TRUE, size = 3.5, hjust = 0) + theme_classic()
关键提醒
- 如果目标是拟合
y=abˣ,不要用stat_smooth(method="lm", formula=y~exp(x)),这个拟合的是y=β0+β1exp(x),和指数模型不是一回事。 stat_poly_eq无法直接处理非线性模型或对数转换后的模型来输出指数形式方程,手动提取参数并用annotate添加文本是更可靠的方式。
内容的提问来源于stack exchange,提问作者Sean Hats
相关产品推荐
相关产品推荐

