Search code examples
rggplot2ggplotlybubble-chart

Bubble Chart using ggplotly - Changing the labels using a slider


First of all here is my data:

df <- structure(list(rowname = c(
  "AA - 2018", "AA - 2019", "AA - 2020",
  "AB - 2018", "AB - 2019", "AB - 2020"
), Class = c(
  "AA", "AA",
  "AA", "AB", "AB", "AB"
), Year = c(
  2018L, 2019L, 2020L, 2018L,
  2019L, 2020L
), Vol = c(0.3, 0.4, 0.5, 0.2, 0.4, 0.7), Profit = c(
  -0.1,
  -0.4, 0.2, 0.5, 0.2, -0.9
), Amount = c(1L, 1L, 2L, 3L, 4L, 5L)), class = "data.frame", row.names = c(NA, -6L))

I am trying to create a bubble chart where the size of the bubble is dependent on the amount and is positioned based on the profitability (as a % of the amount) on the x-axis and the volatility (as a % of the amount) on the y-axis. I have added a slider that uses the year column so that the bubbles can change as the slider changes year.

What i would like to do is introduce a label that uses the 'rowname' column as a label and it changes depending on the year that the slider is on. E.g. If the slider is on 2018 then one bubble will be labelled AA - 2018 and the other AB - 2018, once the slider changes to 2019 then the bubbles will be labelled AA - 2019 and AB - 2019 etc.

When i run the code below i get all the labels on all at the same time and it looks a complete mess.

Code is as follows:

Bound <- 0.05
y_high <- max(df$Vol) + Bound
   y_low <- 0

x_high <-max(df$Profit) + Bound
x_low <- min(df$Profit) - Bound

plot <- ggplot(df, aes(x = Profit, y = Vol, size = Amount, color = Class)) +
  geom_point(aes(frame = Year), alpha = 0.2) + scale_size(range = c(5,50)) +
  geom_text(label = rownames(df))+
  scale_y_continuous(labels = scales::percent,expand = c(0, 0), limits = c(y_low,y_high)) +
  scale_x_continuous(labels = scales::percent,expand = c(0, 0), limits = c(x_low,x_high)) +
 

fig <- ggplotly(plot)

fig

Solution

  • There are two issues with your code.

    1. You use the frame aes only ingeom_point. Therefore the points vary by frame, but not the labels. To solve this put frame = Year in the global aes, i.e. inside ggplot().

    2. You want the labels to be equal to the column rowname but use rownames(df) instead. To solve this issue map rowname on label.

    Try this:

    plot <- ggplot(df, aes(x = Profit, y = Vol, size = Amount, color = Class, frame = Year)) +
      geom_point(alpha = 0.2) +
      scale_size(range = c(5, 50)) +
      geom_text(aes(label = rowname), size = 5) +
      scale_y_continuous(labels = scales::percent, expand = c(0, 0), limits = c(y_low, y_high)) +
      scale_x_continuous(labels = scales::percent, expand = c(0, 0), limits = c(x_low, x_high))
    
    fig <- ggplotly(plot)
    
    fig
    

    enter image description here