I need to plot a 3D surface with 2D projections like the one below using R.
It features a 3D density plot, something easy to do in R using plotly, for example. The 2D surfaces on the other hand I've had no luck so far in my search for how to draw them. The best I've found is this example, but it uses Python instead of R.
I have also found that package RSM (Response Surface Methods) may have the tools to draw this graph, but I've studied the package documentation and looked for online examples and so far I have not been able to find anything close to this graph in quality.
Base R function persp looks like it could offer some answer too, but I've had no success using it to draw the 2D projections so far. Package plot3D may also offer clues to the solution.
Thanks in advance for any help on this.
Well I do not know how your data looks like but if you don't have an specific data you can use this reference of r-plotly surface.
Here is some example using volcano's data of R.
The trick is use contours()
The code:
# volcano is a numeric matrix that ships with R
plot_ly(z = ~volcano) %>% add_surface(
contours = list(
z = list(
show=TRUE,
usecolormap=TRUE,
highlightcolor="#ff0000",
project=list(z=TRUE)
),
y = list(
show=TRUE,
usecolormap=FALSE, # Projection without colormap
highlightcolor="#ff0000",
project=list(y=TRUE)
),
x = list(
show=TRUE,
usecolormap=TRUE,
highlightcolor="#ff0000",
project=list(x=TRUE)
)
)
)
The output:
Related
I'm trying to plot 3-dimensional vectors (x, y, z coordinates) onto a 3D coordinate system in R like in the picture below. Ideally, I would then like to construct 3d kernel density plots, also like in the image below.
Ideal result of vector plot and 3d kernel density plot
I have a matrix containing ~100 rows and one column for each coordinate (x, y , z). Initially, I tried arrow3D() from the plot3D package but I find the perspective to be sub-par, it's rather difficult to discern directions of the arrows from one perspective in the final plot. Next I tried the rgl package which gives me interactivity - great. Minimal working example:
library(rgl)
library(matlib)
data2 <- data.frame(replicate(6,rnorm(100))) #sample data set for minimum working example
colnames(data2) <- c("x_target", "y_target", "z_target", "x_start", "y_start", "z_start")
x1 <- data2$x_target - data2$x_start
y1 <- data2$y_target - data2$y_start
z1 <- data2$z_target - data2$z_start
vec <- (diag(6,3)) # coordinates for x, y and z axis
rownames(vec) <- c("X", "Y", "Z") # labels for x, y and z axis
z <- as.matrix((data.frame(x=x1, y=y1, z=z1)))
open3d()
vectors3d(vec, color=c(rep("black",3)), lwd=2, radius=1/25)
vectors3d(X=z, headlength=1/25)
(due to the random numbers generator the strange looking rods appear at different coordinates, not exactly like in the image i link to below)
The result of the code above is a version of the image link below. One set of coordinates produces a very strange looking more like rod object which is far longer then the coordinates would produce. If I plot the vectors individually, no such object is created. Anyone have any ideas why this happens? Also, if anyone has a tool (doesn't have to be R), that can create a 3D vector plot like in the first image, I'd be grateful. I find it to be very complicated in R, but I'm definitely a beginner.
Strange object to the right (long red rod that doesn't look like an arrow at all)
Thank you!
This is due to a bug in the matlib package, fixed in verson 0.9.2 of that package. I think you need to install it from Github instead of CRAN to get the bug fix:
devtools::install_github("friendly/matlib")
BTW, if you are using random numbers in a reproducible example, you can make it perfectly reproducible by something like
set.seed(123)
at the start (or some number other than 123). I saw reproducible problems with your example for set.seed(4).
I'm trying to figure out how to create surface plots with Plots.jl. I can create a spherical surface from a 2-d mesh like below:
using Plots
plotlyjs()
# Read the theta and phi angles from file...
x2d = sind(theta2d).*cosd(phi2d)
y2d = sind(theta2d).*sind(phi2d)
z2d = cosd(theta2d)
surface(x2d,y2d,z2d)
However, I want to have the surface color be controlled by a separate matrix like the plot below (made with Python).
from mayavi import mlab
# Create/read plot data...
mlab.figure(bgcolor=(1,1,1), fgcolor=(0.,0.,0.))
mlab.mesh(x2d, y2d, z2d, scalars=p2d, colormap='jet', vmax=5, vmin=-35)
Perhaps I should just use the Python plotting functions directly? Or maybe GLVisualize directly?
Thanks!
You can supply the matrix controlling the colors as the fill_z keyword. It doesn't work on all backends, but try plotljys and pyplot.
I want to plot a 3D array M where
M <- array(runif(64),dim=c(4,4,4))
A similar question is here with comments that this can be done using a common 3D plot in R, but I could find no such function in R which can be used to plot multidimensional arrays (say, a 3D array as in the above example). Any suggestion how to do it? Thanks.
Use melt to create a table of x,y,z,value, and then rgl to do a 3d plot:
library(reshape2)
library(rgl)
M=melt(M)
points3d(M$Var1,M$Var2,M$Var3)
That's just 64 points in a cube. You can scale and colour them:
points3d(M$Var1,M$Var2,M$Var3,size=10,color=rainbow(10)[M$value*10])
Use whatever method of mapping M$value to colour you prefer. Don't use rainbow palettes for real!
I cannot find a straightforward way to make a nice image plot in R, but in polar coordinates. I'm basically attempting to find a R equivalent for the 'polarplot3d' function in MATLAB. I've been playing around with ggplot2 package but without much luck. Am I missing a package that contains functionality for what I'm attempting? thanks in advance for any pointers.
Ok, I'm trying to be more clear about what I'm trying to do. Lets say I want to define a polar coordinate grid, increments in the radial direction are 50m and 2.5 degrees in theta. This should look like a dartboard.
My data (r and angle in below code) are correspond to a radial distance measure and an angle. My desired z-value is the counts of a bivariate histogram between r and angle within the increments described above defining the grid.
My data is like the following:
# synthetic data for angle and distance #
angle <- rnorm(500,mean=90,sd=15)
r <- rnorm(500,mean=700,sd=200)
# bivariate histogram #
observations <- table(cut(angle,breaks=c(seq(0,360,by=2.5))),cut(r,breaks=c(seq(0,1400,by=50))))
# the 'z' data are in observations for each bin of bivariate histogram #
# hot to plot a polar coord image? #
It's very slow to render on my system, but
library(reshape2)
library(ggplot2)
mm <- melt(counts)
ggplot(mm,aes(Var1,Var2,fill=value))+geom_tile()+coord_polar()
ggsave("polar1.png")
appears to work.
I think the following could work. Use mapproject() from the maproj library to transform my xy coordinates acording to a polar projection (or another), Then use as.image() (from fields package) function to build a image object from my new coordiantes and my Z values. Eventually use image.plot().
library("mapproj")
xyProj <- mapproject(x, y, projection="conic", parameters=-90)
library("fields")
im <- as.image(z, x=xyProj)
image.plot(im)
How can we plot a 3D plot for the in-out degree distribution.
I found the the plot here: http://en.wikipedia.org/wiki/Degree_distribution really interesting but I do not know if we can draw it using r ?
any ideas ?
update:
the data that I am using is the degree distribution of the in-degree and out-degree:
> head(dDistribution_in)
[1] 0.30117450 0.19379195 0.10654362 0.06291946 0.03775168 0.03313758
> head(dDistribution_out)
[1] 0.36115772 0.17072148 0.09228188 0.05369128 0.04572148 0.02055369
You can do this with perspective plots, here's an example that should help:
require(MASS)
set.seed(42)
persp(kde2d(rnorm(100), rnorm(100)), col="grey90", shade=1, theta=120, xlab="X")
If you're asking specifically about replicating this degree distribution, you can use the same idea on your data. Also, while 3D styled plots can look good, a clearer representation of that data may be something like a hexagonally-binned 2d histogram.
Update
Using the small sample of your data works fine:
d_in <- c(0.30117450, 0.19379195, 0.10654362, 0.06291946, 0.03775168, 0.03313758)
d_out <- c(0.36115772, 0.17072148, 0.09228188, 0.05369128, 0.04572148, 0.02055369)
persp(kde2d(d_in, d_out), col="grey90", shade=1, theta=120, xlab="X")
Not sure what you're doing wrong, but see this post on how to make a reproducible example.