0

New to programming and first time post.

I'm trying to create a stacked bubble chart to display how a population breaks down into it's proportions. My aim is to write this as a function so that I can use it repeatedly easily, but I need to get the meat of the code sorted before turning it to a function.

This is the type of plot I would like: enter image description here

This is the code I've tried so far:

library(ggplot2)

# some data
observations = c(850, 500, 200, 50)
plot_data = data.frame(
                    "x"         = rep.int(1,length(observations))
                   ,"y"         = rep.int(1,length(observations))
                   , "size"     = rep.int(1,length(observations))
                   ,"colour"    = c(1:length(observations)) 
                   )

# convert to percentage for relative sizes
for (i in 1:length(observations)) 
                {
                plot_data$size[i] = (observations[i]/max(observations))*100
                }

ggplot(plot_data,aes(x = x, y = y)) +
  geom_point(aes(size = size, color = colour)) +
  scale_size_identity() +
  scale_y_continuous (limits = c(0.5, 1.5)) +
  theme(legend.position = "none")     

This produces a bullseye type image.

My approach has been to try and work out how the circle radii are calculated, and then update the y value in the for loop for each entry such that all the circles touch at the base - this is where I have been failing.

So my question: How can I work out what the y coordinates for each circle needs to be?

Thank you for any help and hints.

Henrik
  • 65,555
  • 14
  • 143
  • 159

1 Answers1

2

I think this simplifies the answer that Henrick found:

circle <- function(center, radius, group) {
  th <- seq(0, 2*pi, len=200)
  data.frame(group=group,
             x=center[1] + radius*cos(th),
             y=center[2] + radius*sin(th))
}

# Create a named vector for your values
obs <- c(Org1=500, Org2=850, Org3=50, Org4=200)

# this reverse sorts them (so the stacked layered circles work)
# and makes it a list
obs <- as.list(rev(sort(obs)))

# need the radii
rads <- lapply(obs, "/", 2)

# need the max
x <- max(sapply(rads, "["))

# build a data frame of created circles
do.call(rbind.data.frame, lapply(1:length(rads), function(i) {
  circle(c(x, rads[[i]]), rads[[i]], names(rads[i]))
})) -> dat

# make the plot

gg <- ggplot(dat)
gg <- gg + geom_polygon(aes(x=x, y=y, group=group, fill=group), 
                        color="black")
gg <- gg + coord_equal()
gg <- gg + ggthemes::theme_map()
gg <- gg + theme(legend.position="right")
gg

enter image description here

You can tweak the guides/colors with standard ggplot functions.

hrbrmstr
  • 77,368
  • 11
  • 139
  • 205