我有一个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)
当我在互联网上搜索时,我发现当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)
为什么我的数据集不被内置函数接受?
答案 0 :(得分:52)
我将lattice
包用于我在R中绘制的几乎所有内容,并且它具有与persp
wireframe
相对应的图表data
。让wireframe(z ~ x * y, data=data)
成为Sven定义它的方式。
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()]))
})
或者这个怎么样(Deepanyan Sarkar's book中的图6.3的修改):
x
由于这篇文章继续引起人们的注意,我想添加OpenGL方法来制作3-d图(如下面的@tucson所示)。首先,我们需要将数据集从xyz-tripplet重新格式化为轴向量y
和z
以及矩阵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")
进行保存。
{{1}}
答案 1 :(得分:21)
如果您使用的是“实际”数据,其网格间隔和序列无法保证增加或唯一(希望(x,y,z)
组合至少是唯一的,即使这些三元组是重复的),我建议akima
包用于从不规则网格到常规网格进行插值。
使用您对data
的定义:
library(akima)
im <- with(data,interp(x,y,z))
with(im,image(x,y,z))
这不仅适用于image
,也适用于类似的功能。
请注意,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
来覆盖这一点。
答案 2 :(得分:16)
添加到其他人的解决方案中,我建议您使用R
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")
包,因为这对我来说效果很好。
下面,我使用上面建议的重新格式化的数据集,从xyz-tripplets到轴向量x和y以及矩阵z:
volcano
可以使用鼠标旋转和缩放渲染曲面。这在RStudio中运行得相当好。
您也可以使用R
中的内置plot_ly(z=volcano, type="surface")
数据集进行尝试:
{{1}}
答案 3 :(得分:8)
我认为以下代码接近你想要的代码
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
和
之类的图表persp(x, y, z)
答案 4 :(得分:3)
不确定为什么上面的代码不适用于库rgl
,但以下链接对同一个库有一个很好的例子。
在R中运行代码,您将获得一个漂亮的3d图,您可以在各个角度转动。
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();