如何在R中基于expand.grid生成的变量绘制3D平面?
解决3D平面绘图的矩阵格式问题
我来帮你搞定这个3D绘图的难题!你遇到的核心卡点是从长格式的组合数据转换为部分绘图包要求的矩阵格式,其实我们有两种思路可以解决,一种是直接用支持长格式数据的交互式绘图工具,另一种是把数据转换成矩阵格式适配传统静态绘图包。
第一步:先整理完整的数据框
首先我们把计算得到的res合并到组合数据框里,方便后续处理:
# 将结果合并到组合数据框 combis$res <- res # 查看数据结构,确认每个n和prob的组合都对应一个res head(combis)
方案1:用plotly绘制交互式3D图(无需矩阵格式)
plotly是非常好用的交互式绘图库,它直接支持长格式数据,不需要提前转换为矩阵,而且生成的图可以拖拽旋转,方便查看细节。
代码示例:
library(plotly) # 绘制3D曲面图(如果觉得曲面不够平滑,也可以先插值,但你的离散数据直接绘制也能展示趋势) plot_ly(combis, x = ~n, y = ~prob, z = ~res, type = "surface") %>% layout(scene = list( xaxis = list(title = "n"), yaxis = list(title = "prob"), zaxis = list(title = "res") )) # 如果曲面效果不符合预期,也可以用3D散点图叠加半透明曲面 plot_ly(combis, x = ~n, y = ~prob, z = ~res, type = "scatter3d", mode = "markers", marker = list(size = 2, color = "darkblue")) %>% add_surface(z = ~res, x = ~n, y = ~prob, opacity = 0.4, colorscale = "Blues") %>% layout(scene = list( xaxis = list(title = "n"), yaxis = list(title = "prob"), zaxis = list(title = "res") ))
方案2:转换为矩阵格式,适配传统静态绘图包
如果一定要用需要矩阵格式的工具(比如基础R的persp或lattice的wireframe),我们可以把长格式数据转换成宽格式的矩阵。
代码示例:
library(tidyr) # 把长格式数据转换为宽格式:行是n的取值,列是prob的取值,单元格是res wide_data <- combis %>% pivot_wider( id_cols = n, # 以n作为行标识 names_from = prob, # 以prob作为列名 values_from = res # 填充res的值 ) # 提取矩阵部分(去掉n列) res_matrix <- as.matrix(wide_data[, -1]) # 设置行名和列名,方便绘图时标注坐标轴 rownames(res_matrix) <- wide_data$n colnames(res_matrix) <- unique(combis$prob) # 用基础R的persp绘制静态3D图 persp( x = unique(combis$n), y = unique(combis$prob), z = res_matrix, xlab = "n", ylab = "prob", zlab = "res", main = "3D Plot of res vs n & prob", theta = 30, # 调整视角角度 phi = 30, col = "lightblue" ) # 或者用lattice包的wireframe绘制更美观的静态图 library(lattice) wireframe( res_matrix ~ n * prob, data = wide_data, xlab = "n", ylab = "prob", zlab = "res", shade = TRUE, # 开启阴影效果增强立体感 colorkey = TRUE # 显示颜色对应的值刻度 )
注意事项:
- 因为你用
expand.grid生成了所有prob和n的组合,所以转换宽格式时不会有缺失值,如果遇到缺失情况,可以在pivot_wider里加values_fill = 0来填充。 - 如果你希望曲面更平滑,可以用
akima包的interp函数对数据进行插值,再绘制曲面。
内容的提问来源于stack exchange,提问作者George
相关产品推荐
相关产品推荐

