如何在R中绘制响应面等高线三元图以展示响应变量Gi的预测分布
问题原因
你写的代码不符合预期主要有两个核心问题:
- 三元图要求输入的X/Y/Z为成分数据,即三者之和为固定值,你之前用
rtmvtnorm生成的随机数据没有该约束,ggtern会自动对数据做归一化,导致和模型的输入维度不匹配,预测结果异常 - 你拟合的是三阶多项式模型,但插值时用了一阶线性回归,插值结果和你训练的模型效果完全不符
修正方案
直接基于你训练好的三阶模型生成符合成分约束的三元网格预测值,再绘制渐变响应面即可得到和示例一致的效果,完整可运行代码如下:
# 加载依赖包 library(compositions) library(tmvtnorm) library(ggtern) library(dplyr) # 原始数据与模型拟合(和你原有代码一致) X <- rep(c(45,40,55,40,43,50,43,50,43,48), each = 3) Y <- rep(c(15, 12,22,14,14,19,12,17,17,12 ), each = 3) Z <- rep(c(15,22,12,12,19,14,14,17,12,17), each = 3) Gi <- c(353,381,320,312,335,265,394,350,374,320,299,316,300,304,295,360,331,395, 351,280,342,299,303,279,374,364,419,306,290,315) Ft <- data.frame(X, Y, Z) model = lm(Gi ~ ilr(Ft) + I(ilr(Ft)^2) + I(ilr(Ft)^3)) # 生成符合成分约束的三元规则网格,约束X+Y+Z=75(匹配原始数据的总和范围) grid <- expand.grid( X = seq(10, 80, length.out = 100), Y = seq(5, 60, length.out = 100) ) %>% mutate(Z = 75 - X - Y) %>% filter(Z >= 5, Z <= 60) # 基于已有模型预测网格的Gi值 grid$pGi <- predict(model, newdata = list(Ft = as.matrix(grid[,c("X","Y","Z")]))) # 绘制三元渐变响应面 ggtern(data = grid, aes(x = X, y = Y, z = Z)) + geom_tile_tern(aes(fill = pGi)) + # 可选添加白色等高线,提升层次感 stat_contour_tern(aes(z = pGi), color = "white", alpha = 0.3, bins = 8) + scale_fill_gradient(low = "green", high = "blue", name = "预测Gi") + theme_gray() + theme(tern.axis.arrow.show = TRUE)
效果说明
运行上述代码可以直接输出你需要的渐变填充三元响应面:
- 渐变颜色完全匹配你训练的三阶模型的预测结果,不会出现插值偏差
- 生成的网格严格符合成分数据约束,三元坐标映射准确
- 可通过调整
length.out参数修改网格密度,调整bins参数修改等高线数量,调整scale_fill_gradient的配色参数修改渐变效果
内容的提问来源于stack exchange,提问作者Hoang Le
相关产品推荐
相关产品推荐

