Search code examples
rggplot2chartsr-packagebubble-chart

Create a Bubble chart with packcircles I want circles instead of ovals plus legend ggplot


I want to create a chart with the package packcircles as well as ggplot. and export it with my print device I use in this case "ragg".

I have three issues

  1. The circles I want get converted into ovals when I print it
  2. The text inside the bubbles , I want to be able to resize it so it fits the size of the bubbles. The smalles bubble has size 14 and it is barely noticeable.
  3. I want my legend to have the segment I defined in the dataframe "data", instead I get the "id" numbers.

I have tried this:

library(tidyverse)
library(ggthemes)
library(scales)
library(ggtext)
library(ggrepel)
library(ragg)    
library(systemfonts)   
library(magick)
library(png)
library(ggnewscale) 
library(ggh4x)
library(packcircles)

theme_b <- function( ) {
  
  theme(
    panel.background = element_rect(fill ="white"),
    panel.grid.major.y  = element_line(color = "white"),
    panel.grid.major.x  = element_blank(),
    panel.grid.minor = element_blank(),
    axis.ticks  = element_blank(),
    axis.ticks.length.x = unit(0.15,"cm"), 
    plot.background = element_rect(fill="white"),
    legend.background = element_rect(fill="transparent"),
    legend.key = element_blank(),
    axis.title.x = element_blank(),
    axis.text = element_blank(),

    plot.title = element_textbox(size=32,color="black",vjust=1,
                                 family = "merriweather",width = unit(1, "npc"),
                                 margin= margin(r=-40,b=80),
                                 lineheight = 1.3),
    plot.caption.position = "plot",
    plot.caption = element_textbox(size=12,color="black",margin= margin(t = 10, b=10,r=60),
                                   lineheight = 1.2,
                                   family = "montserrat",
                                   width = unit(1, "npc")),
    
    axis.title.y.right = element_blank(),
    axis.title.y.left = element_blank(),
    axis.line.x = element_blank(),
    plot.margin = unit(c(1,2,0,1),"cm"),
    legend.direction = "horizontal",
    legend.spacing.x = unit(0.4, 'cm'),
    legend.position = c(.30, 1.06),
    legend.text = element_text(size = 13,color="black",
                               margin = margin(l = -10)),
    legend.title = element_markdown(size = 13,
                                    color = "black",
                                    family = "montserrat",
                                    lineheight = 1.2),

    
    
  )
}



# Create data
data <- data.frame(Segment=c("Small","Medium", "Large", "Extra Large", 
                                    "Extra extra large"), 
                          value=c(10000, 3000, 400, 300, 70)) 
packing <- circleProgressiveLayout(data$value, sizetype='area')

data <- cbind(data, packing)

data_gg <- circleLayoutVertices(packing, npoints=50)


tp <- "Clothing Size Inventory"
c1 <- "Source: Company"
lnd <- "**Size table"


p <- ggplot() + 
  
  # Make the bubbles
  geom_polygon(data = data_gg, 
               aes(x, y, group = id, fill=as.factor(id)), alpha = 0.6) +
  labs(title = tp,
       caption = c1,
       fill = lnd) +
  scale_fill_manual(values = c("#edf8b1","#c7e9b4","#7fcdbb","#41b6c4",
                               "#1d91c0"),
                    guide = guide_legend(title.position = "top",ncol = 2)) + 
  guides(fill=guide_legend(title.position = "top",
                           byrow = TRUE,
                           nrow = 2),
         alpha="none",
         size = "none") + 
  geom_text(data = data, 
            aes(x, y, size=c(30,24,15,15,14), label = round(value/1000,2))) +
  scale_size_continuous(range = c(1,5)) +
  
  # General theme:
  theme_b() + 
  coord_equal()



p2 <- p + 
  coord_cartesian(clip = "off")


agg_png("bubbles_example2.png", width = 8, height = 8, units = "in", res = 300)
p2
dev.off()

I get this: bubble chart

I want this: bubble chart desired


Solution

  • The causes of the issues you have and the way to fix them are as follows:

    1. The circles appear as ovals because you are overwriting coord_equal with coord_cartesian. There is no need to do this as far as I can see.
    2. The fill legend shows the circle IDs because that is what you have mapped to the fill aesthetic. Fortunately, these IDs are the same as the row numbers of your data, so you can pass data$Segment to the breaks argument of scale_fill_manual.
    3. The text size is different from what you think you specified because you have used scale_size_continuous with a range of 1-5, so the text will always be in that range. You probably want scale_size_identity.

    Putting all this together, we have:

    ggplot(data_gg, aes(x, y)) + 
      geom_polygon(aes(group = id, fill = factor(id)), alpha = 0.6) +
      labs(title = tp, caption = c1, fill = lnd) +
      scale_fill_manual(values = c("#edf8b1", "#c7e9b4", "#7fcdbb", 
                                   "#41b6c4", "#1d91c0"), labels = data$Segment) + 
      guides(fill = guide_legend(title.position = "top", byrow = TRUE, nrow = 2),
             size = "none") + 
      geom_text(data = data, 
                aes(size = c(30, 24, 15, 15, 10)/2, label = round(value/1000,2))) +
      scale_size_identity() +
      theme_b() + 
      coord_equal()
    

    enter image description here