[R] How to scale arrows to approximately fill a plot region?

Uwe Ligges ligges at statistik.tu-dortmund.de
Wed Dec 7 21:20:51 CET 2011



On 07.12.2011 18:52, Michael Friendly wrote:
> In a variety of graphic applications, I plot some data, together with
> arrows representing variables
> or linear transformations of variables as vectors in the same space, as
> in a biplot.
>
> In my applications, the scale of the arrows is arbitrary -- all that
> matters is relative length.
> I'd like to blow them up or shrink them to fit the available space in
> the plot.
> The origin is typically at some mean for (x,y), but that is not
> necessarily so.
> There must be some general, perhaps approximate solution for this problem,
> but I can't see it.
>
> Below is a simple test case. I found the approximate solution, scale <-
> 14 by trial and error.
> [I'm ignoring aspect ratio, because that determines the bbox I calculate
> from the plot.]
>
>
> set.seed(123135251)
> x <- 2 + 5* rnorm(50)
> y <- 5 + 2* rnorm(50)
> plot(x,y)
>
> # get bounding box of plot region, in data coordinates
> bbox <- matrix(par("usr"), 2, 2, dimnames=list(c("min", "max"),c("x",
> "y")))
> # center vectors here
> origin <- colMeans(bbox)
> points(origin[1], origin[2], pch=16, cex=2)
>
> # vectors to be displayed in this space
> vectors <- cbind( runif(5), (runif(5)-.5))
>
> # draw arrows, given origin and length in xy
> Arrows <- function(xy, lenxy, length=.1, angle=10, ...) {
> arrows(xy[1], xy[2], xy[1]+lenxy[,1], xy[2]+lenxy[,2], length=length,
> angle=angle, ...)
> }
>
> ## How to determine scale so that vectors ~ fill the bounding box???
> scale <- 14
> Arrows(origin, scale*vectors)
>
>

Michael, you know it. Go and grab a coffee, this is school maths:

If you have a starting point and a direction as well as the plotting 
region, you can simply calculate a (positive ?) scale so that an arrow 
crosses the border. Now do this for all arrows and all borders and take 
the minimal positive value. Should be few lines of code only.

Therefore:

scale <- c(sapply(bbox[,"x"] - origin["x"], function(i) i/vectors[,1]),
            sapply(bbox[,"y"] - origin["y"], function(i) i/vectors[,2]))
scale <- min(scale[scale > 0])


Best wishes,
Uwe



More information about the R-help mailing list