1

Is there a simple way to make a bubble chart in R like this:

enter image description here

I've played around with ggplot with fake data and have gotten this far:

cat<-c("A", "A", "B", "B", "C", "C")
chara<-c("1", "0", "1", "0", "1", "0")
percent<-c(80, 20, 60, 40, 90,10)
xcoord<-c(10,10,11,11,12,12)
ycoord<-c(10,10,10,10,10,10)

DF<-data.frame(cat,chara, percent, xcoord, ycoord)

NewBubbleChart <- ggplot(DF, aes(x = cat, y = "", size = percent, label = NULL, fill = chara), legend = FALSE) +
                    geom_point(color = "grey50", shape = 21, alpha = 0.99) +  
                   #geom_text(size=4) +
                    theme_bw() +
                    scale_size(range = c(5, 20))

NewBubbleChart <- NewBubbleChart +
                    scale_fill_manual(name = "Type",
                                      values = c("darkblue", "lightblue"),
                                      labels = c("0" = "Type 0", "1" = "Type 1"))

I ended up not using the xcoord and ycoord part, but I left it in. I know that a bar chart would work too, but a bubble chart is wanted instead.

zx8754
  • 52,746
  • 12
  • 114
  • 209
user3731561
  • 25
  • 2
  • 5

2 Answers2

4

This seems to come pretty close.

library(ggplot2)
# function to calculate coords of a circle
circle <- function(center,radius) {
  th <- seq(0,2*pi,len=200)
  data.frame(x=center[1]+radius*cos(th),y=center[2]+radius*sin(th))
}
# example dataset, similar to graphic
df <- data.frame(bank=paste("Bank",LETTERS[1:5]),start=1000*(5:1),end=500*(5:1))    
max <- max(df$start)
n.bubbles <- nrow(df)
scale <- 0.4/sum(sqrt(df$start))
# calculate scaled centers and radii of bubbles
radii <- scale*sqrt(df$start)
ctr.x <- cumsum(c(radii[1],head(radii,-1)+tail(radii,-1)+.01))
# starting (larger) bubbles
gg.1  <- do.call(rbind,lapply(1:n.bubbles,function(i)cbind(group=i,circle(c(ctr.x[i],radii[i]),radii[i]))))
text.1 <- data.frame(x=ctr.x,y=-0.05,label=paste(df$bank,df$start,sep="\n"))
# ending (smaller) bubbles
radii <- scale*sqrt(df$end)
gg.2  <- do.call(rbind,lapply(1:n.bubbles,function(i)cbind(group=i,circle(c(ctr.x[i],radii[i]),radii[i]))))
text.2 <- data.frame(x=ctr.x,y=2*radii+0.02,label=df$end)
# make the plot
ggplot()+
  geom_polygon(data=gg.1,aes(x,y,group=group),fill="dodgerblue")+
  geom_path(data=gg.1,aes(x,y,group=group),color="grey50")+
  geom_text(data=text.1,aes(x,y,label=label))+
  geom_polygon(data=gg.2,aes(x,y,group=group),fill="green2")+
  geom_path(data=gg.2,aes(x,y,group=group),color="grey50")+
  geom_text(data=text.2,aes(x,y,label=label), color="white")+
  labs(x="",y="")+scale_y_continuous(limits=c(-0.1,2.5*scale*sqrt(max(df$start))))+
  coord_fixed()+
  theme(axis.text=element_blank(),axis.ticks=element_blank(),panel.grid=element_blank())

So this is a "bubble-in-bubble" chart, which represents the change in a metric (bank market capitalization in your graphic) between two events or times (before and after the economic collapse, in your graphic). In order for this to work the ending condition must be smaller than the starting condition (otherwise the "inner" bubble is larger than the outer bubble).

The trick bit is getting the circles to be aligned along their bottom edges. This is really difficult using geom_point(...), so I chose to just draw circles for the bubbles instead.

I suspect you'll have to tweak the positioning of the text a bit by hand in a real case. If you want multiple rows (as in the graphic), you might consider ggplot facets.

Finally, if you want the circles shaded (e.g. with a color gradient) this is not really what ggplot is intended for: it's possible but IMO much more work than it's worth.

jlhoward
  • 58,004
  • 7
  • 97
  • 140
  • wow this looks great! Thanks so much for helping me out with the code- I never would have come up with this solution(or it would have taken me a LONG time) - so I guess ggplot is relatively flexible. Not too worried about shading the circles- thanks again! – user3731561 Jul 14 '14 at 20:24
1

I'm not exactly sure how you want the chart to look, but you could try playing with gvisBubbleChart in the package googleVis:

library(googleVis)
##
DF <- cbind(
  DF,
  ID=paste0(DF$cat,DF$chara)
)
bChart <- gvisBubbleChart(
  data=DF,
  idvar="ID",
  xvar="xcoord",
  yvar="chara",
  colorvar="cat",
  sizevar="percent",
  options=list(vAxis='{minValue:.8, maxValue:3}')
)
plot(bChart)

enter image description here

nrussell
  • 18,382
  • 4
  • 47
  • 60
  • Similar to this type of chart, but with A0 on type of A1, B0 on top of B1...Looks like there is no easy way to do this in ggplot – user3731561 Jul 14 '14 at 14:25
  • Are you looking to do this in `ggplot2` specifically, or does it not matter? I'm sure it can be done with a little tweaking, which I don't mind helping you with. – nrussell Jul 14 '14 at 14:30
  • It doesn't have to be ggplot2. Any help/suggestions would be great- I am still fairly new to graphing in R. – user3731561 Jul 14 '14 at 14:33