8

Let's generate some data:

x <- -10*cos(seq(0, pi, length.out = 100))+1
y <- 10*seq(0, pi, length.out = 100)
xerr <- rep(2, 100)
yerr <- rep(2, 100)
dd <- as.data.frame(cbind(x, y, xerr, yerr))

Here I have x and y coordinates of some points with their errors, xerr and yerr (for convenience I have set them constant). I would like to represent these errors with the size of the points. This is easily doable:

ggplot() + 
  geom_point(data = dd, aes(x, y, size = sqrt(xerr^2 + yerr^2)), colour = "gray") +
  geom_path(data = dd, aes(x, y), colour = "red", size = .5) +
  scale_size_identity() +
  theme_bw()

enter image description here

However, the size of these points is defined on a scale that doesn't have any relation with the scale of the plot. Is there a way to adjust the dimension of the points in relation to the scale of the plot? In the above example, the radius of each point should have size equal to 2.828 and not less than one as it is now.

VLC
  • 1,119
  • 1
  • 12
  • 14
  • The "size" of a point in R plots is generally set as a ratio to the default size which is not determined by either of the x or y-scales. In this case do you really want the points to span 2.8 units (radius or diameter?) on the x-scale??? If so, then multiply that size argument by an amount sufficient to approximate the desired spread, perhaps by a factor of 10. – IRTFM Oct 16 '13 at 17:06
  • You can use [scale_size](http://docs.ggplot2.org/current/scale_size.html) to set the size of any symbol relative to some scale you've established (usually a continuous or categorical variable in your df). If you're talking about pixel precision and scaling to the actual output size of the chart, that's trickier. :( – Adam Hyland Oct 16 '13 at 17:08
  • @DWin This is just an example, the errors in my data are way below that value. – VLC Oct 16 '13 at 17:09
  • If the size corresponds to x and y scales, you wouldn't get circles in your plot. Do you really want that? You should use `scale_size_continuous(range = c(1, 100))` and change the range to meet your needs. – Roland Oct 16 '13 at 17:09
  • @Roland You're right about the point you raise, but I can avoid it when representing my data. I'm more interested in a solution that doesn't require manual adjustments. – VLC Oct 16 '13 at 17:35
  • @AdamHyland Trickier? Do you mean difficult or impossible? – VLC Oct 17 '13 at 08:03
  • @VLC Difficult. Specifically with getting the sizes and positions to match across devices (i.e. pdf vs. png etc.) and between the preview (in RStudio or in an X11 window in base R) and the result. I'll try and post an answer this afternoon. – Adam Hyland Oct 17 '13 at 13:00

1 Answers1

7

One way is to explicitly draw ellipses with the axes defined by the size of the errors.

x <- -10*cos(seq(0, pi, length.out = 10))+1
y <- 10*seq(0, pi, length.out = 10)
xerr <- runif(10, 1, 5)
yerr <- runif(10, 1, 5)
dd <- as.data.frame(cbind(x, y, xerr, yerr))
dd$frame <- factor(seq(1:10))

For this purpose we define our function to generate ellipses:

ellipseFun <- function(center = c(0, 0), axes = c(1, 1), npoints = 101){
  tt <- seq(0,2*pi, length.out = npoints)
  xx <- center[1] + axes[1] * cos(tt)
  yy <- center[2] + axes[2] * sin(tt)
  return(data.frame(x = xx, y = yy))
}

We then generate the matrices for all ellipses:

ddEll <- data.frame()
for(k in levels(dd$frame)){
  ddEll <- rbind(ddEll, cbind(as.data.frame(with(dd[dd$frame == k,], ellipseFun(center = c(x, y), axes = c(xerr, yerr), npoints = 101))),frame = k))
}

And, finally, we can plot them:

library(ggplot2)
ggplot() + 
  geom_point(data = dd, aes(x, y)) +
  geom_polygon(data=ddEll, aes(x = x, y = y, group = frame), colour = "gray", fill = "red", alpha = .2) +
  scale_size_identity() +
  theme_bw() +
  xlim(c(-20, 20)) + 
  ylim(c(-5, 35)) +
  coord_fixed()

enter image description here

VLC
  • 1,119
  • 1
  • 12
  • 14
  • This is an absolute gem! For people using this, be sure to extend your `ylim()` and `xlim()` past the error ellipses or else you'll get some not fully drawn polygons. – James Aug 01 '16 at 14:23