Bubble Chart with bubbles aligned along their bott

2019-04-17 12:41发布

问题:

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

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.

回答1:

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.



回答2:

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)



标签: r charts