可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
imagine I have a 3 columns matrix
x, y, z where z is a function of x and y.
I know how to plot a "scatter plot" of these points with plot3d(x,y,z)
But if I want a surface instead I must use other commands such as surface3d The problem is that it doesn't accept the same inputs as plot3d it seems to need a matrix with
How can I get this matrix? I've tried with the command interp, as I do when I need to use contour plots.
How can I plot a surface directly from x,y,z without calculating this matrix? If I had too many points this matrix would be too big.
cheers
回答1:
If your x and y coords are not on a grid then you need to interpolate your x,y,z surface onto one. You can do this with kriging using any of the geostatistics packages (geoR, gstat, others) or simpler techniques such as inverse distance weighting.
I'm guessing the 'interp' function you mention is from the akima package. Note that the output matrix is independent of the size of your input points. You could have 10000 points in your input and interpolate that onto a 10x10 grid if you wanted. By default akima::interp does it onto a 40x40 grid:
> require(akima) ; require(rgl) > x=runif(1000) > y=runif(1000) > z=rnorm(1000) > s=interp(x,y,z) > dim(s$z) [1] 40 40 > surface3d(s$x,s$y,s$z)
That'll look spiky and rubbish because its random data. Hopefully your data isnt!
回答2:
You can use the function outer()
to generate it.
Have a look at the demo for the function persp()
, which is a base graphics function to draw perspective plots for surfaces.
Here is their first example:
x
The same applies to surface3d()
:
require(rgl) surface3d(x, y, z)
回答3:
rgl
is great, but takes a bit of experimentation to get the axes right.
If you have a lot of points, why not take a random sample from them, and then plot the resulting surface. You can add several surfaces all based on samples from the same data to see if the process of sampling is horribly affecting your data.
So, here is a pretty horrible function but it does what I think you want it to do (but without the sampling). Given a matrix (x, y, z) where z is the heights it will plot both the points and also a surface. Limitations are that there can only be one z for each (x,y) pair. So planes which loop back over themselves will cause problems.
The plot_points = T
will plot the individual points from which the surface is made - this is useful to check that the surface and the points actually meet up. The plot_contour = T
will plot a 2d contour plot below the 3d visualization. Set colour to rainbow
to give pretty colours, anything else will set it to grey, but then you can alter the function to give a custom palette. This does the trick for me anyway, but I'm sure that it can be tidied up and optimized. The verbose = T
prints out a lot of output which I use to debug the function as and when it breaks.
plot_rgl_model_a
The add_rgl_model
does the same job without the options, but overlays a surface onto the existing 3dplot.
add_rgl_model
So my approach would be to, try to do it with all your data (I easily plot surfaces generated from ~15k points). If that doesn't work, take several smaller samples and plot them all at once using these functions.
回答4:
You could look at using Lattice. In this example I have defined a grid over which I want to plot z~x,y. It looks something like this. Note that most of the code is just building a 3D shape that I plot using the wireframe function.
The variables "b" and "s" could be x or y.
require(lattice) # begin generating my 3D shape b
回答5:
Maybe is late now but following Spacedman, did you try duplicate="strip" or any other option?
x=runif(1000) y=runif(1000) z=rnorm(1000) s=interp(x,y,z,duplicate="strip") surface3d(s$x,s$y,s$z,color="blue") points3d(s)