10

I'm using scatter3d and the 3 axes just have two endpoint values. how can I get labels throughout the entire axis, just like the normal plot() function does?

IRTFM
  • 258,963
  • 21
  • 364
  • 487
CodeGuy
  • 28,427
  • 76
  • 200
  • 317
  • This seems very helpful but I'm having trouble doing it. If I type car:::scatter.default it returns : Error in get(name, envir = asNamespace(pkg), inherits = FALSE) : object 'scatter.default' not found but car:::scatter3d.default returns the entire function. Do you I edit the scatter3d.default? When I add the if (axis.scales) code to the scatter3d.default I get an error that saying : Error in match.arg(id.method) : object 'id.method' not found? Do you have the full version of the code edits that I could use? Thanks!! – Megan Nov 22 '11 at 16:51
  • @Megan: That was my error: now fixed below. (Didn't see this because it wasn't under my answer or addressed to me.) Re: full code. I could but then the answer would be somewhat bulky. I'm not sure how the rest of the audience feels about "bulky" answers. – IRTFM Nov 23 '11 at 16:01
  • Note the full version of the code (with another tweak or two) is now linked from http://stackoverflow.com/questions/8231007/having-trouble-executing-the-edits-to-scatter3d-default/ – Ben Bolker Nov 30 '11 at 17:10

2 Answers2

28

Oh well. I took it as a challenge.

Obviously you need to:

require(rgl)
require(car)
require(mgcv) # for the example

Copy the car:::scatter3d.default code and paste it back, assigning it to scatter3d.default.

Add these lines early in the code for scatter3d.default:

 showLabels3d <- car:::showLabels3d  
 nice <- car:::nice  
  # since you will be losing their connection to the unexposed fns in car

Then in the code block following the second if(axis.scales){ ...}, substitute this code:

 if (axis.scales) {
   x.labels <-  seq(lab.min.x, lab.max.x, 
                       by=diff(range(lab.min.x, lab.max.x))/4)
   x.at <- seq(min.x, max.x, by=nice(diff(range(min.x, max.x))/4))
      rgl.texts(x.at, -0.05, 0, x.labels, col = axis.col[1])

   z.labels <-  seq(lab.min.z, lab.max.z, 
                       by=diff(range(lab.min.z, lab.max.z))/4)
   z.at <- seq(min.z, max.z, by=diff(range(min.z, max.z))/4)
      rgl.texts(0, -0.1, z.at, z.labels, col = axis.col[3])

   y.labels <-  seq(lab.min.y, lab.max.y, 
                       by=diff(range(lab.min.y, lab.max.y))/4)
   y.at <- seq(min.y, max.y, by=diff(range(min.y, max.y))/4)
      rgl.texts(-0.05, y.at, -0.05, y.labels, col = axis.col[2])
                }

(You may need to replace the code for scatter3d.formula so that doesn't look in the car NAMESPACE for the routinely dispatched scatter method. I simply replaced the scatter3d call inside car:::scatter3d.formula with "scatter3d.default" so the interpreter would first look at the newly defined function.)

Edit: a better method than mucking with scatter3d.formula is to assign the car namespace/environment to the new function with this code:

environment(scatter3d.default) <- environment(car:::scatter3d.formula)

Then if you do this:

scatter3d(prestige ~ income + education, data=Duncan)

You get this (taken with a screenshot program) enter image description here

IRTFM
  • 258,963
  • 21
  • 364
  • 487
  • 10
    Would like to be able to +more for the amount of effort you put in here. – Ben Bolker Nov 21 '11 at 01:39
  • @Ben Bolker: You probably have an idea how many errors I made in the process of figuring this out. – IRTFM Nov 21 '11 at 02:32
  • Great answer, but I'm having a bit of trouble running it. Is scatter3d the same as `scatterplot3d`? I presume you also need to run "data(Duncan)" before trying to plot. – csgillespie Nov 21 '11 at 09:32
  • No, `scatter3d` is in pkg:car and `scatterplot3d` is in pkg:scatterplot3d. I did not need to run data(Duncan) but if one did not run require(car) (or library(car)) , one might need to do so. The RGL version in pkg:car lets you interactively control the rotation of the axis and plot and the plane points and axis lables move together. `scatterplot3d` results in a static graphic. You cannot move it interactively and it also does not have a formula interface as far as I can tell. – IRTFM Nov 21 '11 at 13:40
  • 1
    Nice. Note you can use `rgl.snapshot` to generate images of `rgl` plot windows. – James Nov 22 '11 at 11:54
0

There is a new option that adds interior axis labels, from the help of scatter3d:

axis.ticks

if TRUE, print interior axis-“tick” labels; the default is FALSE. (The code for this option was provided by David Winsemius.)

Alex
  • 15,186
  • 15
  • 73
  • 127