在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
将数据映射到的默认网格由跨越x
和y
值范围的40个等间隔定义:
> formals(akima::interp)[c("xo","yo")] $xo seq(min(x), max(x), length = 40) $yo seq(min(y), max(y), length = 40)
但是,当然,这可以通过将参数xo
和yo
传递给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重新格式化为轴向量x
和y
以及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.snapshot
保存。
rgl.snapshot("myplot.png")
join其他人的解决scheme,我想build议使用R
的plotly
包,因为这对我来说工作得很好。
下面,我使用上面提到的重新格式化数据集,从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")
它给出了这样的数据(注意x
和y
都在增加)
> 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)
不知道为什么上面的代码不适用于库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();