如何用rayshader将ggplot2的2D折线图、直方图转为3D图?
解决rayshader转换ggplot2折线图与直方图为3D的问题
一、3D折线图实现方案
plot_gg对geom_line的3D支持有限,因为它主要基于图层的填充区域转换为3D高度,无填充的线条默认仅显示为平面元素。要实现真正的3D折线效果,可结合ggplot2构建基础底图,再用rayshader原生函数添加立体线条:
- 将分类x轴转换为数值,方便3D空间定位
- 用
plot_gg生成基础平面,再通过add_3d_lines添加立体线条
修改后的代码:
library(rayshader) library(ggplot2) df2 = data.frame(supp=rep(c("VC", "OJ"), each=3), dose=rep(c("D0.5", "D1", "D2"),2), len=c(6.8, 15, 33, 4.2, 10, 29.5)) # 把分类dose转为数值格式 df2$dose_num = as.numeric(factor(df2$dose)) # 绘制带点的基础底图 gg_line = ggplot(data=df2, aes(x=dose_num, y=len, color=supp)) + geom_point(size=3) + scale_x_continuous(breaks=1:3, labels=c("D0.5", "D1", "D2")) # 转换为3D底图 plot_gg(gg_line, raytrace = TRUE, width = 4, zoom = 0.60, theta = -45, phi = 30, windowsize = c(1400,866), multicore = TRUE) # 分别添加两组数据的3D线条 vc_data = subset(df2, supp=="VC") oj_data = subset(df2, supp=="OJ") add_3d_lines(x = vc_data$dose_num, y = vc_data$len, z = 0.2, # z值控制线条悬浮高度 color = "blue", linewidth = 3) add_3d_lines(x = oj_data$dose_num, y = oj_data$len, z = 0.2, color = "orange", linewidth = 3) render_snapshot()
二、3D直方图实现方案
geom_histogram的柱子无法被plot_gg直接拉伸为3D,推荐两种解决思路:
方法1:基于ggplot2 + plot_gg调整
将直方图转换为geom_col的填充柱形,让plot_gg识别柱子高度:
library(rayshader) library(ggplot2) df = data.frame( sex=factor(rep(c("F", "M"), each=200)), weight=round(c(rnorm(200, mean=55, sd=5), rnorm(200, mean=65, sd=5))) ) # 提前计算直方图的统计数据 hist_data = ggplot_build(ggplot(df, aes(x=weight)) + geom_histogram())$data[[1]] # 用geom_col绘制可被3D识别的填充柱形 gg_hist = ggplot(hist_data, aes(x=x, y=density)) + geom_col(fill="white", color="black") + geom_density(data=df, aes(x=weight, y=..density..), alpha=.2, fill="#FF6666") # 转换为3D,通过height参数控制柱子高度 plot_gg(gg_hist, raytrace = TRUE, width = 4, zoom = 0.60, theta = -45, phi = 30, windowsize = c(1400,866), height = 0.5, multicore = TRUE)
方法2:直接使用rayshader原生hist3d函数
若不需要ggplot2的样式,用原生函数生成3D直方图更直接:
library(rayshader) library(ggplot2) df = data.frame( sex=factor(rep(c("F", "M"), each=200)), weight=round(c(rnorm(200, mean=55, sd=5), rnorm(200, mean=65, sd=5))) ) # 分别计算男女体重的直方图密度 female_hist = hist(df$weight[df$sex=="F"], plot=FALSE) male_hist = hist(df$weight[df$sex=="M"], plot=FALSE) # 合并为矩阵格式 hist_matrix = matrix(0, nrow=length(female_hist$mids), ncol=2) hist_matrix[,1] = female_hist$density hist_matrix[,2] = male_hist$density # 绘制3D直方图 hist_matrix %>% sphere_shade(texture="desert") %>% plot_3d(hist_matrix, zscale=0.2, theta=-45, phi=30, xlab="Weight", ylab="Sex", zlab="Density", windowsize=c(1400,866)) render_snapshot()
关键提示
plot_gg仅能将ggplot中有填充的图层转换为3D高度,线条、点等无填充元素默认是平面的,需额外处理- 折线图:通过
add_3d_lines手动添加立体线条,z轴参数控制线条的悬浮高度 - 直方图:优先转为
geom_col填充柱形,或直接用rayshader原生函数生成纯3D效果
内容的提问来源于stack exchange,提问作者Ed_Gravy
相关产品推荐
相关产品推荐

