plotly: Updating data with dropdown selection

12,494

Solution 1

Is this what you were after?

require(plotly)
df <- data.frame(x = runif(200), y = runif(200), z = runif(200))
p <- plot_ly(df, x = ~x, y = ~y, mode = "markers", name = "A", visible = T) %>%
layout(
  title = "Drop down menus - Styling",
  xaxis = list(domain = c(0.1, 1)),
  yaxis = list(title = "y"),
  updatemenus = list(
    list(
      y = 0.7,
      buttons = list(
        list(method = "restyle",
             args = list("y", list(df$y)),  # put it in a list
             label = "Show A"),
        list(method = "restyle",
             args = list("y", list(df$z)),  # put it in a list
             label = "Show B")))
))
p

Solution 2

On the top of @jimmy G's answer.

You can automatically create the buttons so that you don't have to manually specify every single variable you want in the plot.

library(plotly)

df <- data.frame(x = runif(200), y = runif(200), z = runif(200), j = runif(200), k = rep(0.7, 200), i = rnorm(200,0.6,0.05))

create_buttons <- function(df, y_axis_var_names) {
  lapply(
    y_axis_var_names,
    FUN = function(var_name, df) {
      button <- list(
        method = 'restyle',
        args = list('y', list(df[, var_name])),
        label = sprintf('Show %s', var_name)
      )
    },
    df
  )
  
}

y_axis_var_names <- c('y', 'z', 'j', 'k', 'i')

p <- plot_ly(df, x = ~x, y = ~y, mode = "markers", name = "A", visible = T) %>%
     layout(
         title = "Drop down menus - Styling",
         xaxis = list(domain = c(0.1, 1)),
         yaxis = list(title = "y"),
         updatemenus = list(
             list(
                 y = 0.7,
                 buttons = create_buttons(df, y_axis_var_names)
             )
         ))
p


Hope you find it useful.

Share:
12,494
data_enthusiast
Author by

data_enthusiast

Updated on July 14, 2022

Comments

  • data_enthusiast
    data_enthusiast almost 2 years

    I am not sure if this is possible, but here is what I would like to do. I would like to update the data in a plotly plot by selecting from a dropdown menu.

    As a simple example, let's assume I have a data frame

    df <- data.frame(x = runif(200), y = runif(200), z = runif(200))
    

    from which I use df$x and df$y in a scatter plot. Two scenarios of data manipulation I would like to achieve using a dropdown:

    1. Replace df$y with df$z
    2. Plot only the first n values of df$x and df$y

    I looked at the following two examples, which I can easily reproduce: https://plot.ly/r/dropdowns/

    However, I have no idea how to pass the information regarding the data to be plotted based on the dropdown selection. For scenario 2 e.g. I have tried it with args = list("data", df[1:n,]) which did not work.

    For scenario 1 the (only?) way to go (according to the examples) seems to be hiding/showing the traces respectively. Is that the only way for scenario 2 as well?

    Any alternative ideas?

    Update 1: Add reproducible example

    So here is an example which achieve what I would like in scenario 1.

    require(plotly)
    df <- data.frame(x = runif(200), y = runif(200), z = runif(200))
    Sys.setenv("plotly_username"="xxx") #actual credentials replaced
    Sys.setenv("plotly_api_key"="xxx") #actual credentials replaced
    
    p <- plot_ly(df, x = df$x, y = df$y, mode = "markers", name = "A", visible = T) %>%
      add_trace(mode = "markers", y = df$z, name = "B", visible = T) %>%
      layout(
        title = "Drop down menus - Styling",
        xaxis = list(domain = c(0.1, 1)),
        yaxis = list(title = "y"),
        updatemenus = list(
          list(
            y = 0.7,
            buttons = list(
              list(method = "restyle",
                   args = list("visible", list(TRUE, TRUE)),
                   label = "Show All"),
    
              list(method = "restyle",
                   args = list("visible", list(TRUE, FALSE)),
                   label = "Show A"),
    
              list(method = "restyle",
                   args = list("visible", list(FALSE, TRUE)),
                   label = "Show B")))
        ))
    
    plotly_POST(p)
    

    Result here: https://plot.ly/~spietrzyk/96/drop-down-menus-styling/ This is based on the example from https://plot.ly/r/dropdowns/

    However, I am wondering if one could pass the data to be plotted instead of triggering changes to the visible property of individual traces.

    The one thing I tried was the following:

    p <- plot_ly(df, x = df$x, y = df$y, mode = "markers", name = "A", visible = T) %>%
      layout(
        title = "Drop down menus - Styling",
        xaxis = list(domain = c(0.1, 1)),
        yaxis = list(title = "y"),
        updatemenus = list(
          list(
            y = 0.7,
            buttons = list(
              list(method = "restyle",
                   args = list("y", df$y),
                   label = "Show A"),
              list(method = "restyle",
                   args = list("y", df$z),
                   label = "Show B")))
    ))
    

    Result here: https://plot.ly/~spietrzyk/98/drop-down-menus-styling/ This approach cannot work, as the data from df$z is not posted to the grid (https://plot.ly/~spietrzyk/99/).

    So I was wondering is there anyway to manipulate the data to be plotted based on dropdown selection, beyond plotting all traces and than switching the visible property by dropdown selections.

  • Mark Neal
    Mark Neal over 4 years
    Is it possible to make this example handle a list of length that is determined by the dataframe, not hardcoded as a list for each list item?
  • yts61
    yts61 about 4 years
    @jimmy G i have a similary question here: stackoverflow.com/questions/60556896/…, if you are free, please drop by and have a look, thank you.
  • Martin
    Martin over 2 years
    Most useful indeed! As an addition, multiple data attributes can be added in the arg function as shown in this answer: stackoverflow.com/a/69364462/8076560