rbuttonplotlyx-axis

Plotly R: Filtering Bars by Category Without Showing Extra Categories with buttons


here is my code. I am trying to create an interactive bar chart with Plotly in R, where buttons allow the user to select either Company 1 or Company 2.
However, when I filter the data using Plotly, some categories (EPISD) that do not belong to the selected company remain displayed on the x-axis.

I want each company to display only the corresponding EPISD values without showing empty or unrelated categories.

library(plotly)
library(data.table)

# Données
dt <- data.table(
  EPISD = c("A", "A", "B", "B", "C", "D", "D"),
  ENTRP = c(
    "company 1",
    "company 2",
    "company 1",
    "company 2",
    "company 2",
    "company 1",
    "company 2"
  ),
  prct_na = c(100, 0, 100, 5.3, 100, 94, 100)
)

plot_ly() %>%
  add_trace(
    data = dt[ENTRP == "company 1"],
    x = ~ EPISD,
    y = ~ prct_na,
    name = 'company 1',
    type = 'bar',
    visible = T
  ) %>%
  add_trace(
    data = dt[ENTRP == "company 2"],
    x = ~ EPISD,
    y = ~ prct_na,
    name = 'company 2',
    type = 'bar',
    visible = F
  ) %>%
  layout(updatemenus = list(list(
    type = "buttons",
    direction = "down",
    buttons = list(
      list(
        method = "restyle",
        args = list("visible", list(T, F)),
        label = "company 1"
      ),
      list(
        method = "restyle",
        args = list("visible", list(F, T)),
        label = "company 2"
      )
    )
  )))


Solution

  • So there are a couple of reason why unused x-breaks stay

    1. Switchting the visibility of two dataplots with list(T, F) does not cause plotly to update the categoryarray of the x.axis
    2. So we have to explicitly tell plotly the new x-axis values pertaining to each company AND
    3. update the xaxis list parameter categoryorder to redraw the x-axis

    You can also change layout attributes using method = update following this vignette. This allows to update the title for example.

    Code

    library(plotly)
    library(data.table)
    
    dt <- data.table( EPISD = c("A", "A", "B", "B", "C", "D", "D", "A", "F", "G", "F"), 
                      ENTRP = c( "company 1", "company 2", "company 1", "company 2", "company 2", "company 1", "company 2", "company 3", "company 3", "company 4", "company 4"), 
                      prct_na = c(100, 2, 100, 5.3, 100, 94, 100, 25, 14, 50, 10) )
    
    companies <- unique(dt$ENTRP)
    
    buttons_list <- lapply(seq_along(companies), function(i) { # build buttons list using lapply
      company <- companies[i]
      company_data <- dt[ENTRP == company]
      
      list(
        label = company,
        method = "update",
        args = list(
          list(
            x = list(company_data$EPISD), # set x values as before
            y = list(company_data$prct_na) # set y values as before
          ),
          list(
            title = paste(company, "Data"),
            xaxis = list(
              categoryorder = "category ascending"
            )
          )
        )
      )
    })
    
    plot_ly(x = dt[ENTRP == companies[1]]$EPISD, 
            y = dt[ENTRP == companies[1]]$prct_na, 
            type = 'bar',
            name = companies[1]) %>%
      layout(
        title = paste(companies[1], "Data"),
        xaxis = list(
          categoryorder = "category ascending"
        ),
        updatemenus = list(
          list(
            type = "buttons",
            direction = "down",
            buttons = buttons_list
          )
        )
      )