3

The general idea is to create a plotly chart that can toggled between showing a count and a percentage. I am able to change which traces are shown using updatemenu, and the axis ticks can change dynamically, but when I toggle to "%" in the example below, the legend disappears.

I'm not at all a plotly pro which is why I'm using ggplotly() (my real example is more complex and ggplolty() works great!) and I'm wondering if I have to manually add a legend to % traces (3, 4) to have a legend displayed when the first traces are made invisible?

library(ggplot2)
library(plotly)

df <- structure(list(outcome = c("a", "b", "a", "b", "a", "b", "a", 
"b", "a", "b"), n = c(59, 191, 28, 67, 29, 56, 33, 45, 32, 40
), pct = c(0.208480565371025, 0.674911660777385, 0.288659793814433, 
0.690721649484536, 0.337209302325581, 0.651162790697674, 0.4125, 
0.5625, 0.444444444444444, 0.555555555555556), day = c(1L, 1L, 
2L, 2L, 3L, 3L, 4L, 4L, 5L, 5L)), class = "data.frame",
row.names = c(NA, -10L))

p <- ggplot(df, aes(day, n, color = outcome)) +
  geom_line() +
  geom_line(aes(y = pct))

ggplotly(p, dynamicTicks = TRUE) %>% 
  style(visible = FALSE, traces = 3:4) %>% 
  layout(
    updatemenus = list(
      list(
        buttons = list(
          list(args = list("visible", list(TRUE, TRUE, FALSE, FALSE)),
               label = "n"),

          list(args = list("visible", list(FALSE, FALSE, TRUE, TRUE)),
               label = "%")
          )
        )
      )
    )

enter image description here

enter image description here

NOTE: This is also posted on RStudio Community, but has not received any answers.

mfherman
  • 392
  • 4
  • 16

1 Answers1

5

@mfherman - here's what I came up with:

library(ggplot2)
library(plotly)
library(scales)

df <- structure(list(outcome = c("a", "b", "a", "b", "a", "b", "a", 
                                 "b", "a", "b"), n = c(59, 191, 28, 67, 29, 56, 33, 45, 32, 40
                                 ), pct = c(0.208480565371025, 0.674911660777385, 0.288659793814433, 
                                            0.690721649484536, 0.337209302325581, 0.651162790697674, 0.4125, 
                                            0.5625, 0.444444444444444, 0.555555555555556), day = c(1L, 1L, 
                                                                                                   2L, 2L, 3L, 3L, 4L, 4L, 5L, 5L)), class = "data.frame",
                row.names = c(NA, -10L))

p <- ggplot(df, aes(day, n, color = outcome)) +
  geom_line() +
  geom_line(aes(y = pct)) + 
  theme(legend.position="bottom", legend.box = "horizontal")



chart_type <- list(
  type = "buttons",
  direction = "right",
  xanchor = 'center',
  yanchor = "top",
  x = 0.5,
  y = 1.27,
  buttons = list(
    list(
      label = "nvals",
      method = "update",
      args = list( list("visible", list(TRUE, TRUE, FALSE, FALSE)), 
                   list( yaxis = list( range = c(0,200) ,
                                       ticksuffix = "") )
                  )),
    list(
        label = "%vals",
        method = "update",
        args = list( list("visible", list(FALSE, FALSE, TRUE, TRUE)), 
                     list( yaxis = list( range = c(0,100) ,
                                         ticksuffix = "%") )
        ))
  ))

# https://plotly.com/r/custom-buttons/#relayout-button



p2 <- ggplotly(p, dynamicTicks = TRUE, width = 640, height = 420) %>% 
  style(visible = FALSE, traces = 3:4) %>% 
  layout(
      legend = list(orientation = "h",y = 0.8, x = 0.8),
      updatemenus = list( chart_type )
)


for (i in 1:ncol(df)){
  p2$x$data[[i]]$showlegend <- TRUE
}
p2

Important part is at the bottom -> looks like the p2$x$data[[i]]$showlegend values are being set to false on the second chart by default. Might be worth opening as an issue on the github project for this to be added as an option on the layout list. Looks like they have a hide_legend option only right now... weird.

https://github.com/ropensci/plotly/issues

Kudos to this issue for helping me figure this out:

https://github.com/ropensci/plotly/issues/842

enter image description here enter image description here

EDIT: added % yaxis as requested in comment

sgdata
  • 2,543
  • 1
  • 19
  • 44
  • This is it, thanks! A tangential question is how to get the y axis label to change to % format when the drop down is selected. It looks like you can specify a layout change in a button, but I haven't yet been able to get it to change both the layout and style in one button. – mfherman May 05 '20 at 19:58
  • 1
    Added the % yaxis for you and cleaned up the button list methods for you. Learned quite a bit about plotly doing this exercise. – sgdata May 06 '20 at 20:23