3d scatterplot in R using rgl plot3d - different size for each data point?
Asked Answered
K

2

6

I am using

plot3d(x,y,z, col=test$color, size=4) 

to plot a 3d scatterplot of my dataset with R, but with rgl the size argument only takes one size.

Is it possible to have different sizes for each data point, perhaps with another library, or is there a simple workaround?

Thanks for your ideas!

Kushner answered 26/4, 2012 at 21:53 Comment(2)
It be great to have a reproducible example: with(iris, plot3d(Sepal.Length, Sepal.Width, Petal.Length, col=Species))Advantageous
This does not seem to work: iris$num<-rownames(iris) with(iris, plot3d(Sepal.Length, Sepal.Width, Petal.Length, col=Species)) library(plyr) d_ply(.data=iris, .variables="num", function(x) {points3d(x=x$Sepal.Length, y=x$Sepal.Width, z=x$Petal.Length, size=x$Petal.Width)})Advantageous
D
6

Here's a work-around along the same lines suggested by Etienne. The key idea is to set up the plot, then use a separate call to points3d() to plot the points in each size class.

# Break data.frame into a list of data.frames, each to be plotted 
# with points of a different size
size <- as.numeric(cut(iris$Petal.Width, 7))
irisList <- split(iris, size)

# Setup the plot
with(iris, plot3d(Sepal.Length, Sepal.Width, Petal.Length, col=Species, size=0))

# Use a separate call to points3d() to plot points of each size
for(i in seq_along(irisList)) {
    with(irisList[[i]], points3d(Sepal.Length, Sepal.Width, 
                                 Petal.Length, col=Species, size=i))
}

(FWIW, it does appear that there's no way to get plot3d() to do this directly. The problem is that plot3d() uses the helper function material3d() to set point sizes and as shown below, material3d() only wants to take a single numeric value.)

material3d(size = 1:7)
# Error in rgl.numeric(size) : size must be a single numeric value
Decigram answered 27/4, 2012 at 0:27 Comment(3)
Thank you very much Etienne and Josh, at least it seems that I am not the only one struggling with this. Does somebody know, if any other package could provide this functionality, because I think it is very useful?Kushner
Hmm. Does the workaround not do it for you? What functionality do you need in your 3D plot? If you need dynamic graphics (i.e. rotate/scale by mouse), hidden line removal, lighting effects, etc., then you're pretty much stuck with rgl. Otherwise you could try something like scatterplot3d. It is conceivable that rgl could be hacked/updated to allow efficient per-point size specification, but it would be worth knowing why it's worth the effort ...Selinski
Thanks a lot for your help, sorry for the late reply! I know just used tet for labeling the points because to adapt the size was too complicated. It would have been nice to have just one dimension more, but perhaps it would have been too much anyway...Kushner
I
1

Just in case anyone else stumbles across this years later, it is now completely possible to pass a variable into the size argument, e.g. with(test, plot3d(x,y,z, col=test$color, size=test$size)).

Actually, you can conduct operations on the data being fed to size and it will also work. I succeeded in making a basic size ratio with something along the lines of size = x/(max(x,na.rm=TRUE)-min(x,na.rm=TRUE)).

While it is true that material3d will only accept single numeric values, the expression or variable fed to size within the with statement should be evaluated beforehand, so material3d should still only see a single size value for each plotted point. Just a heads up since I spent a an hour or so fiddling with the workaround posted here before realizing it was unnecessary.

Inlaid answered 21/2, 2018 at 14:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.