2

I have data consisting of a set of circles with radii. The scale of the x, y and radius is the same.

x    y    radius
0.1  0.8  0.1
0.4  0.4  0.2
0.6  0.2  0.9
0.3  0.6  0.5
0.5  0.5  0.2
...
0.9  0.1  0.1

When I use:

myplot <- ggplot() + geom_point(data=df, aes(x=x, y=y, size=(2*radius)))

the resulting plot is a bubble plot with the size scaled to the radius. I want a bubble plot where radius of bubble = radius (i.e. the radius of the bubble is in the native units).

How can I achieve this (in ggplot2)?

user5061
  • 655
  • 8
  • 12
  • 1
    that's been asked a [few times](https://groups.google.com/forum/#!msg/ggplot2/f0I4tWWOhbs/iELUIITpVR0J) before in the mailing list; IIRC there's not easy way to do that, one of the problems being that the x and y axes don't necessarily have the same scale (so you'd need ellipses rather than circles). – baptiste May 28 '14 at 10:57
  • 1
    In this case x and y axis have the same scale. – user5061 May 28 '14 at 11:26

2 Answers2

7

So it turns out that there doesn't seem to be a simple way to do this.

I checked out the mailing list entry linked to by baptiste (which is for a single circle) and extended using a for loop to plot each circle one at a time.

df = data.frame(x=c(0.1,0.4,0.6, 0.3, 0.5,0.9), y=c(0.8,0.4,0.2,0.6,0.5,0.1), r=c(0.1,0.2,0.2,0.1,0.2,0.1))

angle <- seq(-pi, pi, length = 50)

myplot = ggplot()
for (i in 1:length(df$x)) {
        df_temp = data.frame(x = df$x[i] + df$r[i]*sin(angle), y = df$y[i] + df$r[i]*cos(angle))
        myplot = myplot + geom_polygon(data=df_temp, aes(x=x, y=y), inherit.aes=F)
      }
myplot = myplot + geom_point(data=df, aes(x=x, y=y))

This gives:

enter image description here

There is a slight change in the example dataset to make things clearer on the plot. I've also plotted the coordinates of the circle centres here.

Edit: suggested improvement, only drawing one polygon layer.

circularise <- function(d, n=360){
  angle <- seq(-pi, pi, length = n)
  make_circle <- function(x,y,r,id){
    data.frame(x=x+r*cos(angle), y=y+r*sin(angle), id)
  }
  lmat <- mapply(make_circle, id = seq_len(nrow(d)), 
                x = d[,1], y=d[,2], r=d[,3], SIMPLIFY = FALSE)
  do.call(rbind, lmat)
}

circles <- circularise(df)

p = ggplot() + 
  geom_point(data=df, aes(x=x, y=y))

p + geom_polygon(aes(x,y,group=id, fill=id), data=circles) +
    coord_fixed()
baptiste
  • 75,767
  • 19
  • 198
  • 294
user5061
  • 655
  • 8
  • 12
  • note that you don't need a for loop and many layers: `geom_polygon` can draw multiple polygons at once, you simply need to give it a data.frame with the points and group ids. – baptiste May 28 '14 at 16:28
2

When you want the radius relative to the scale of the x and y variable, you can use the scale_size_continuous parameter and set the ranges for the scale. An example:

# reading some example data
df <- read.table(header=TRUE, text="x    y    radius
0.1  0.8  0.1
0.4  0.4  0.2
0.6  0.2  0.9
0.3  0.6  0.5
0.5  0.5  0.2
0.9  0.1  0.1")

# creating the plot
ggplot(data=df) + 
  geom_point(aes(x=x, y=y, size=radius*2), shape=20, alpha=0.4, show_guide=FALSE) +
  scale_size_continuous(range = c(10, 500)) +
  theme_bw()

which gives: enter image description here

By variing the values in range = c(10, 500), you can change it to what you want. The first value is the size of the smallest point and the second value the size of the largest point.

Jaap
  • 81,064
  • 34
  • 182
  • 193
  • No I want the bubbles to have radius exactly equal to the number I specify for radius. (p.s. good point about radius vs. diameter. I will edit the question). – user5061 May 28 '14 at 10:09
  • For example the point that has radius 0.9 should be of a size such that it fills most of the plot with the data I've specified... – user5061 May 28 '14 at 10:16
  • @user5061 see my update, is this what you'r looking for? – Jaap May 28 '14 at 11:49
  • 1
    @Jaap the OP wants the radius to correspond to the units of the x and y axes (native units in grid parlance). – baptiste May 28 '14 at 12:07
  • @Jaap sort of. This answer is correct for this dataset but one would have to set the range for each plot? I have a set of simulations that I want to visualise without having to tweak each plot individually. – user5061 May 28 '14 at 13:04
  • This does not resolve the issue for me, circles are still scaling when zooming. – Untitpoi Jul 23 '19 at 13:08