简体   繁体   English

R 中的 Plot 3D 数据

[英]Plot 3D data in R

I have a 3D dataset:我有一个 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)

And I want to plot it, but the built-in-functions of R alwyas give the error我想 plot 它,但是 R 的内置函数总是给出错误

increasing 'x' and 'y' values expected预期增加“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)

When I searched on the internet, I found that this message happens when combinations of X and Y values are not unique.当我在互联网上搜索时,我发现当 X 和 Y 值的组合不唯一时会出现此消息。 But here they are unique.但在这里它们是独一无二的。

I tried some other libraries and there it works without problems.我尝试了其他一些库,它可以正常工作。 But I don't like the default style of the plots (the built-in functions should fulfill my expectations).但我不喜欢绘图的默认样式(内置函数应该满足我的期望)。

# ### 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)

Why are my datasets not accepted by the built-in functions?为什么我的数据集不被内置函数接受?

I use the lattice package for almost everything I plot in R and it has a corresponing plot to persp called wireframe . I use the lattice package for almost everything I plot in R and it has a corresponing plot to persp called wireframe . Let data be the way Sven defined it.data成为 Sven 定义的方式。

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

线框图

Or how about this (modification of fig 6.3 in Deepanyan Sarkar's book ):或者这个怎么样(修改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()]))
    })

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

Update: Plotting surfaces with OpenGL更新:使用 OpenGL 绘制曲面

Since this post continues to draw attention I want to add the OpenGL way to make 3-d plots too (as suggested by @tucson below).由于这篇文章继续引起人们的注意,我想添加 OpenGL 方法来制作 3-d 绘图(如下面的@tucson 所建议)。 First we need to reformat the dataset from xyz-tripplets to axis vectors x and y and a matrix z .首先,我们需要将数据集从 xyz-tripplets 重新格式化为轴向量xy以及矩阵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::persp3d

This image can be freely rotated and scaled using the mouse, or modified with additional commands, and when you are happy with it you save it using rgl.snapshot .该图像可以使用鼠标自由旋转和缩放,或者使用其他命令进行修改,当您对它感到满意时,您可以使用rgl.snapshot保存它。

rgl.snapshot("myplot.png")

If you're working with "real" data for which the grid intervals and sequence cannot be guaranteed to be increasing or unique (hopefully the (x,y,z) combinations are unique at least, even if these triples are duplicated), I would recommend the akima package for interpolating from an irregular grid to a regular one.如果您正在使用“真实”数据,其网格间隔和序列不能保证增加或唯一(希望(x,y,z)组合至少是唯一的,即使这些三元组重复),我会推荐akima package 从不规则网格插值到规则网格。

Using your definition of data :使用您对data的定义:

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

在此处输入图像描述

And this should work not only with image but similar functions as well.这不仅适用于image ,还适用于类似的功能。

Note that the default grid to which your data is mapped to by akima::interp is defined by 40 equal intervals spanning the range of x and y values:请注意, 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)

But of course, this can be overridden by passing arguments xo and yo to akima::interp .但当然,这可以通过将 arguments xoyo传递给akima::interp interp 来覆盖。

Adding to the solutions of others, I'd like to suggest using the plotly package for R , as this has worked well for me.除了其他人的解决方案,我想建议使用plotly package 为R ,因为这对我来说效果很好。

Below, I'm using the reformatted dataset suggested above, from xyz-tripplets to axis vectors x and y and a matrix z:下面,我使用上面建议的重新格式化的数据集,从 xyz-tripplets 到轴向量 x 和 y 以及矩阵 z:

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")

在此处输入图像描述

The rendered surface can be rotated and scaled using the mouse.渲染的表面可以使用鼠标进行旋转和缩放。 This works fairly well in RStudio.这在 RStudio 中运行良好。

You can also try it with the built-in volcano dataset from R :您还可以使用R中的内置volcano数据集进行尝试:

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

在此处输入图像描述

I think the following code is close to what you want我认为下面的代码接近你想要的

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")

It gives data like this (note that x and y are both increasing)它给出了这样的数据(注意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

and a graph like和一个像

persp(x, y, z)

persp(x, y, z)

Not sure why the code above did not work for the library rgl , but the following link has a great example with the same library.不知道为什么上面的代码不适用于库rgl ,但下面的链接有一个很好的例子,使用相同的库。 Run the code in R and you will obtain a beautiful 3d plot that you can turn around in all angles .运行 R 中的代码,您将获得一个漂亮的 3d plot ,您可以在各个角度转身

http://statisticsr.blogspot.de/2008/10/some-r-functions.html 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();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM