如何使用ggplot2绘制平滑的等高线图?
如何使用ggplot2绘制平滑的等高线图?
嗨,我完全懂你的困扰——你用geom_contour_filled画出来的不是平滑等高线,核心问题在于你的原始数据是稀疏的离散网格点,ggplot的等高线函数没法直接从这么少的点生成流畅的曲线,得先对数据做插值处理,把稀疏点转换成密集网格,才能画出平滑的效果。
下面给你两种简单好用的解决方法:
方法一:用akima包做二维插值(最直观)
这个包专门处理二维数据插值,操作非常简单:
- 先安装并加载需要的包:
install.packages("akima") # 首次使用需要安装 library(ggplot2) library(akima) library(tidyr) # 用来整理数据格式
- 对原始数据插值,生成密集网格:
# 用interp生成插值后的密集数据,n参数控制网格密度,数值越大越平滑 interp_result <- interp(x = NigerianData$Nweight, y = NigerianData$Pweight, z = NigerianData$Yield, n = 100) # 生成100×100的密集网格 # 把插值结果转换成ggplot能识别的数据框格式 interp_df <- as.data.frame(interp_result) # 把宽格式数据转成长格式,方便ggplot调用 interp_df <- pivot_longer(interp_df, cols = -x, names_to = "y", values_to = "Yield") # 把y列的字符标签转换成数值 interp_df$y <- as.numeric(gsub("V", "", interp_df$y))
- 用插值后的数据绘制平滑等高线:
ggplot() + geom_contour_filled(data = interp_df, aes(x = x, y = y, z = Yield)) + geom_contour(data = interp_df, aes(x = x, y = y, z = Yield), color = "black", size = 0.3) + # 加黑色等高线线条 scale_fill_viridis_c(option = "plasma") + # 可选:用更美观的渐变配色 labs(title = "Contourplot of Yield at different fertilizer concentrations", x = "Nitrogen Rates", y = "Phosphate Rates", fill = "Yield") + theme_minimal()
方法二:用mgcv包拟合曲面(适合复杂数据)
如果你的数据不是规则网格,或者想要更精准的曲面拟合,可以试试这个方法:
- 安装加载包:
install.packages("mgcv") library(mgcv)
- 生成密集网格并拟合预测:
# 创建覆盖所有N、P浓度范围的密集网格 new_grid <- expand.grid(Nweight = seq(min(NigerianData$Nweight), max(NigerianData$Nweight), length.out = 100), Pweight = seq(min(NigerianData$Pweight), max(NigerianData$Pweight), length.out = 100)) # 用gam模型拟合曲面 gam_model <- gam(Yield ~ s(Nweight, Pweight), data = NigerianData) # 预测每个网格点的产量值 new_grid$Yield <- predict(gam_model, newdata = new_grid)
- 绘制平滑等高线图:
ggplot(new_grid, aes(x = Nweight, y = Pweight, z = Yield)) + geom_raster(aes(fill = Yield), interpolate = TRUE) + # 平滑填充底色 geom_contour(color = "black", size = 0.3) + scale_fill_viridis_c(option = "magma") + labs(title = "Smooth Contourplot of Yield", x = "Nitrogen Rates", y = "Phosphate Rates", fill = "Yield") + theme_bw()
为什么原始代码没效果?
你手里的NigerianData只有12个点,是3个氮水平×4个磷水平的稀疏网格,geom_contour_filled只能基于这些离散点生成生硬的分段线条,没有足够的数据点支撑平滑效果。插值后生成的密集网格(比如100×100=10000个点)就能让等高线变得流畅自然啦。
备注:内容来源于stack exchange,提问作者Karim Kahtaoui
相关产品推荐
相关产品推荐

