如何在R中创建类似MATLAB样式的三维曲面图

16

我发现在 R 中创建美观的三维表面比较具有挑战性。我熟悉这些解决方案(persp, image, wireframe, lattice, rgl 以及其他一些在 Stack Overflow 中的问题中提到的解决方案),但结果并不理想。

是否可能在 R 中创建类似 MATLAB 中的三维表面图?

图片描述

Here is the MATLAB code
    % Create a grid of x and y points
    points = linspace(-2, 0, 20);
    [X, Y] = meshgrid(points, -points);

    % Define the function Z = f(X,Y)
    Z = 2./exp((X-.5).^2+Y.^2)-2./exp((X+.5).^2+Y.^2);

    % "phong" lighting is good for curved, interpolated surfaces. "gouraud"
    % is also good for curved surfaces
    surf(X, Y, Z); view(30, 30);
    shading interp;
    light;
    lighting phong;
    title('lighting phong', 'FontName', 'Courier', 'FontSize', 14);

这个情节现代、色彩鲜艳、美观大方,代码语法非常易读。

在基础R中是否可能实现这一点?


6
这段话的意思是:这些图形很具有挑战性,因为大多数数据科学工作者认为3D图形与“现代、彩色等”相距甚远,只是一种无用的噱头,应该留在90年代;但说真的,图形设计专家特夫特非常有影响力,我相信他会告诉你上述观点是浪费墨水(像素),最好使用扁平的彩色图像,这样你可以更真实地感受到数据。 - Stephen Henderson
2
如果你删掉抱怨/主观的部分(“为什么在基础R中做漂亮的3D曲面图这么具有挑战性?”),我会点赞这个问题。library(emdbook); library(rgl)很有用;curve3d(2/exp((-.5)^2+y^2)-2/exp((x+.5)^2+y^2),sys3d="rgl", xlim=c(0,2),ylim=c(-2,0))是一个开始,虽然它没有颜色。(你需要使用基础R解决方案的特定原因吗?)如果你“熟悉解决方案”,为什么不展示一个起点并告诉我们哪里不“好”呢? - Ben Bolker
@BenBolker 正是这个问题。有几个“尝试”(包括emdbook、rlg),但没有真正直接的解决方案。基础 R 是一个很棒的绘图工具。但是,当你进入 3D 领域时,你会得到让人想起 70 年代的图形解决方案。似乎在基础 R 中没有对美观现代 3D 绘图的兴趣,任何尝试都需要额外的包。令人遗憾的是,我必须学习和使用其他程序才能获得漂亮的 3D 绘图。 - ECII
1
我同意没有一个提供美观、方便、一体化解决方案的确实很遗憾。但我不明白为什么它不在基本R中就成了问题。(MATLAB难道也不是通过插件提供大量功能吗?) - Ben Bolker
1
如果您提供一个例子并指出其中的问题,那么这将更有生产力。这样人们就可以尝试提供改进的解决方案来回答您的问题。 - Ben Bolker
显示剩余5条评论
2个回答

21
"

jet.colors是R语言中的一个调色板,类似于Matlab中的一种调色板:

"
points = seq(-2, 0, length=20)
#create a grid
XY = expand.grid(X=points,Y=-points)
# A z-function 
Zf <- function(X,Y){
     2./exp((X-.5)^2+Y^2)-2./exp((X+.5)^2+Y^2);
     }
# populate a surface
Z <- Zf(XY$X, XY$Y)
zlim <- range(Z)
zlen <- zlim[2] - zlim[1] + 1

jet.colors <-   # function from grDevices package
      colorRampPalette(c("#00007F", "blue", "#007FFF", "cyan",
                      "#7FFF7F", "yellow", "#FF7F00", "red", "#7F0000"))
colorzjet <- jet.colors(100)  # 100 separate color 
require(rgl)
open3d()
rgl.surface(x=points, y=matrix(Z,20), 
            coords=c(1,3,2),z=-points, 
            color=colorzjet[ findInterval(Z, seq(min(Z), max(Z), length=100))] )
axes3d()
rgl.snapshot("copyMatlabstyle.png")

CopyMatlab.style.png"

我承认让颜色与“Z轴”(实际上是rgl y轴)对齐似乎非常不直观。如果您想要Matlab提供的闪亮、镜面效果,可以尝试调整照明角度。

enter image description here

您也可以添加或删除照明:

clear3d(type = "lights")
light3d(theta=0, phi=0)
light3d(theta=0, phi=0)  # twice as much light.

之后:

 grid3d("x")
 grid3d("y")
 grid3d("z")

 rgl.snapshot("copyMatlabstyle3.png")

enter image description here

您可以使用以下方法将y-grid放置在表面“后面”:

grid3d("y+")

对于axes3d或者axis3d的调用,类似的微调可以改变刻度的位置。

如果需要更多例子,请查看http://rgm3.lab.nig.ac.jp/RGM/R_image_list并搜索'plot3d',会出现R2BayesX::plot3d函数的示例。 请查看Karline Soetaert的plot3D包的vignette,"50 ways to plot a volcano"


非常好。您可以使用grid3d()来添加表面网格,就像MATLAB绘图中一样。我必须承认,在这些情况下,我发现镜面光线会分散注意力。(值得一提的是,在比尔·克利夫兰的书籍中确实有关于三维透视图的讨论——因此它们至少具有一些统计图形纯粹主义的资质。此外,我同意上面评论者的观点,即图示中的三维效果是浪费的,但他肯定不会一般反对它——他的一个标题是“逃离平面”...) - Ben Bolker
1
我发现将3D图形与等高线图并置时特别有用。等高线图可以使得数字值的合理提取变得容易,而3D图则可以让人欣赏最陡峭变化的“形状”和位置。 - IRTFM
感谢DWin不仅提供了漂亮的答案,还提供了网站链接以供阅读。在这个例子中,颜色并不是很有用(但它是一个简单的例子)。我觉得当人们想要同时将另一个维度映射到图表时,颜色+3D是有用的。我发现这样的图表非常有用,不仅在出版/报告阶段,而且在数据分析阶段,可以同时可视化超过2个维度。干杯,谢谢。 - ECII

5
这可能不能完全满足您的需求,但我发布它是为了吸引更好的答案。
X <- Y <-  seq(-2, 0, length.out= 20)
Z <- outer(X,Y,
           function(X,Y) 2/exp((X-.5)^2+Y^2)-2/exp((X+.5)^2+Y^2))
cc <- colorRamp(rev(rainbow(10)))
Zsc <- (Z-min(Z))/diff(range(Z))
rgbvec2col <- function(x) do.call(rgb,c(as.list(x),list(max=255)))
colvec <- apply(cc(Zsc),1,rgbvec2col)

library(rgl)
surface3d(X,Y,Z,col=colvec)
bbox3d(color=c("white","black"))

我花了至少3个小时才想出一个“更好的答案”。在这个过程中,我学到了很多东西。 - IRTFM

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接