在R中绘制3D数据

我有一个3D数据集:

data = data.frame( x = rep( c(0.1, 0.2, 0.3, 0.4, 0.5), each=5), y = rep( c(1, 2, 3, 4, 5), 5) ) data$z = runif( 25, min = (data$x*data$y - 0.1 * (data$x*data$y)), max = (data$x*data$y + 0.1 * (data$x*data$y)) ) data str(data) 

我想绘制它,但R alwyas的内置函数给出了错误

预期增加“x”和“y”值

 # ### 3D Plots ###################################################### # built-in function always give the error # "increasing 'x' and 'y' values expected" demo(image) image(x = data$x, y = data$y, z = data$z) demo(persp) persp(data$x,data$y,data$z) contour(data$x,data$y,data$z) 

当我在互联网上search时,我发现这个消息发生时,X和Y值的组合不是唯一的。 但在这里他们是独一无二的

我尝试了一些其他的库,并在那里工作没有问题。 但是我不喜欢这些情节的默认风格(内置函数应该满足我的期望)。

 # ### 3D Scatterplot ###################################################### # Nice plots without surface maps? install.packages("scatterplot3d", dependencies = TRUE) library(scatterplot3d) scatterplot3d(x = data$x, y = data$y, z = data$z) # ### 3D Scatterplot ###################################################### # Only to play around? install.packages("rgl", dependencies = TRUE) library(rgl) plot3d(x = data$x, y = data$y, z = data$z) lines3d(x = data$x, y = data$y, z = data$z) surface3d(x = data$x, y = data$y, z = data$z) 

为什么我的数据集不被内置函数接受?

谢谢你的帮助,

斯文

如果您正在处理网格间隔和序列无法保证增加或唯一(希望(x,y,z)组合至less是唯一的“真实”数据,即使这些三元组是重复的),我会推荐从不规则网格插入到正常网格的akima包。

使用你的data定义:

 library(akima) im <- with(data,interp(x,y,z)) with(im,image(x,y,z)) 

在这里输入图像说明

这不仅适用于image而且也适用于类似的function。

请注意, akima::interp将数据映射到的默认网格由跨越xy值范围的40个等间隔定义:

 > formals(akima::interp)[c("xo","yo")] $xo seq(min(x), max(x), length = 40) $yo seq(min(y), max(y), length = 40) 

但是,当然,这可以通过将参数xoyo传递给akima::interp来重写。

我使用lattice封装几乎所有我在R的情节,它有一个相应的情节,以称为wireframe 。 让data成为Sven定义它的方式。

 wireframe(z ~ x * y, data=data) 

线框图

或者如何(在Deepanyan Sarkar的书中修改图6.3):

 p <- wireframe(z ~ x * y, data=data) npanel <- c(4, 2) rotx <- c(-50, -80) rotz <- seq(30, 300, length = npanel[1]+1) update(p[rep(1, prod(npanel))], layout = npanel, panel = function(..., screen) { panel.wireframe(..., screen = list(z = rotz[current.column()], x = rotx[current.row()])) }) 

使用面板和更新的多个线框图

更新:用OpenGL绘制曲面

由于这篇文章不断引起人们的关注,我想添加OpenGL的方式来制作3-d地块(如下面的@tucson所示)。 首先,我们需要将数据集从xyz-tripplets重新格式化为轴向量xy以及matrixz

 x <- 1:5/10 y <- 1:5 z <- x %o% y z <- z + .2*z*runif(25) - .1*z library(rgl) persp3d(x, y, z, col="skyblue") 

RGL :: persp3d

这个图像可以使用鼠标自由地旋转和缩放,或者使用附加的命令修改,当你满意的时候用rgl.snapshot保存。

 rgl.snapshot("myplot.png") 

join其他人的解决scheme,我想build议使用Rplotly包,因为这对我来说工作得很好。

下面,我使用上面提到的重新格式化数据集,从xyz-tripplets到轴向量x和y以及matrixz:

 x <- 1:5/10 y <- 1:5 z <- x %o% y z <- z + .2*z*runif(25) - .1*z library(plotly) plot_ly(x=x,y=y,z=z, type="surface") 

在这里输入图像说明

渲染的表面可以使用鼠标旋转和缩放。 这在RStudio中运行得相当好。

您也可以使用R的内置volcano数据集来尝试:

 plot_ly(z=volcano, type="surface") 

在这里输入图像说明

我认为下面的代码是接近你想要的

 x <- c(0.1, 0.2, 0.3, 0.4, 0.5) y <- c(1, 2, 3, 4, 5) zfun <- function(a,b) {a*b * ( 0.9 + 0.2*runif(a*b) )} z <- outer(x, y, FUN="zfun") 

它给出了这样的数据(注意xy都在增加)

 > x [1] 0.1 0.2 0.3 0.4 0.5 > y [1] 1 2 3 4 5 > z [,1] [,2] [,3] [,4] [,5] [1,] 0.1037159 0.2123455 0.3244514 0.4106079 0.4777380 [2,] 0.2144338 0.4109414 0.5586709 0.7623481 0.9683732 [3,] 0.3138063 0.6015035 0.8308649 1.2713930 1.5498939 [4,] 0.4023375 0.8500672 1.3052275 1.4541517 1.9398106 [5,] 0.5146506 1.0295172 1.5257186 2.1753611 2.5046223 

和一个graphics一样

 persp(x, y, z) 

persp(x,y,z)

不知道为什么上面的代码不适用于库rgl ,但下面的链接有一个很好的例子与相同的库。 在R中运行代码,你将获得一个美丽的3d情节,你可以在任何angular度转身

http://statisticsr.blogspot.de/2008/10/some-r-functions.html

 ######################################################################## ## another example of 3d plot from my personal reserach, use rgl library ######################################################################## # 3D visualization device system library(rgl); data(volcano) dim(volcano) peak.height <- volcano; ppm.index <- (1:nrow(volcano)); sample.index <- (1:ncol(volcano)); zlim <- range(peak.height) zlen <- zlim[2] - zlim[1] + 1 colorlut <- terrain.colors(zlen) # height color lookup table col <- colorlut[(peak.height-zlim[1]+1)] # assign colors to heights for each point open3d() ppm.index1 <- ppm.index*zlim[2]/max(ppm.index); sample.index1 <- sample.index*zlim[2]/max(sample.index) title.name <- paste("plot3d ", "volcano", sep = ""); surface3d(ppm.index1, sample.index1, peak.height, color=col, back="lines", main = title.name); grid3d(c("x", "y+", "z"), n =20) sample.name <- paste("col.", 1:ncol(volcano), sep=""); sample.label <- as.integer(seq(1, length(sample.name), length = 5)); axis3d('y+',at = sample.index1[sample.label], sample.name[sample.label], cex = 0.3); axis3d('y',at = sample.index1[sample.label], sample.name[sample.label], cex = 0.3) axis3d('z',pos=c(0, 0, NA)) ppm.label <- as.integer(seq(1, length(ppm.index), length = 10)); axes3d('x', at=c(ppm.index1[ppm.label], 0, 0), abs(round(ppm.index[ppm.label], 2)), cex = 0.3); title3d(main = title.name, sub = "test", xlab = "ppm", ylab = "samples", zlab = "peak") rgl.bringtotop();