Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

updatemenus > buttons don't behave as expected when restyling y axis (ignores color channel) #2379

Open
jack-davison opened this issue Aug 15, 2024 · 1 comment

Comments

@jack-davison
Copy link

library(plotly)

dat <- structure(list(date = structure(c(1230768000, 1230771600, 1230775200, 
  1230778800, 1230782400, 1230786000, 1230789600, 1230793200, 1230796800, 
  1230800400, 1230768000, 1230771600, 1230775200, 1230778800, 1230782400, 
  1230786000, 1230789600, 1230793200, 1230796800, 1230800400, 1230768000, 
  1230771600, 1230775200, 1230778800, 1230782400, 1230786000, 1230789600, 
  1230793200, 1230796800, 1230800400, 1230768000, 1230771600, 1230775200, 
  1230778800, 1230782400, 1230786000, 1230789600, 1230793200, 1230796800, 
  1230800400), tzone = "GMT", class = c("POSIXct", "POSIXt")), 
      nox = c(113, 40, 48, 36, 40, 50, 50, 53, 80, 111, NA, NA, 
      NA, NA, NA, NA, NA, NA, NA, NA, 130, 63, 76, 69, 61, 61, 
      61, 92, 57, 50, 31, 34, 27, 19, 21, 25, 19, 31, 42, 48), 
      pm10 = c(46, 49, 46, NA, 38, 32, 36, 32, 30, 32, NA, NA, 
      NA, NA, NA, NA, NA, NA, NA, NA, 53, 46, 45, 43, 37, 35, 37, 
      38, 33, 31, 44, 39, 40, 35, 34, 30, 28, 31, 29, 27), site = structure(c(1L, 
      1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 
      2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 4L, 
      4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L), levels = c("1", "2", 
      "3", "4"), class = "factor")), row.names = c(NA, -40L), class = c("tbl_df", 
  "tbl", "data.frame"))

plot_ly(x = dat$date, y = dat$nox) |>
  add_lines(color = dat$site) |>
  layout(updatemenus = list(list(
    type = "buttons",
    y = 0.8,
    buttons = list(
      list(
        method = "restyle",
        args = list("y", list(dat$nox)),
        label = "NO<sub>x</sub>"
      ),
      list(
        method = "restyle",
        args = list("y", list(dat$pm10)),
        label = "PM<sub>10</sub>"
      )
    )
  )))

I would imagine that clicking the "NOx" button would do effectively nothing, but instead it seems to strip away the color feature of the plot.

Before clicking:

image

After clicking:

image

Am I doing something wrong, or is this a bug?

@wholmes105
Copy link

wholmes105 commented Oct 14, 2024

It's not a bug, but I wouldn't say it's intuitive for R users, either. layout.updatemenus, plotlyProxy(), and the like more closely resemble the plotly.js side of things than they do the handy abstractions you find in plot_ly(). In your case, you left off the optional third argument inside of the lists you gave to args. That argument specifies which trace(s) you want your button to update, and it updates all of them if the argument is left off.

What's happening here isn't that the color is being stripped away, it's that all the y values for each trace are being updated to match that of the first trace; since the x values already matched each other, this stacks each trace one on top of the other, and the extra y values you gave aren't plotted since they don't have corresponding x values. The code here has what I think was your expected behavior:

dat |>
  plot_ly(x = ~date, y = ~nox) |>
  add_lines(color = ~site) |>
  layout(updatemenus = list(list(
    type = 'buttons',
    y = 0.8,
    buttons = ~list(
      list(
        method = 'restyle',
        # args = list('y', list(nox[1:10], nox[21:30], nox[31:40])),
        args = list('y', na.omit(nox) |> split(site[!is.na(nox)], drop = TRUE) |> unname()),
        label = 'NO<sub>x</sub>'
      ),
      list(
        method = 'restyle',
        # args = list('y', list(pm10[1:10], pm10[21:30], pm10[31:40])),
        args = list('y', na.omit(pm10) |> split(site[!is.na(pm10)], drop = TRUE) |> unname()),
        label = 'NO<sub>10</sub>'
      )
    )
  )))

In that example, I commented what the code would be if I hardcoded the new y values, but the uncommented version is more robust (though less straightforward). If you're looking for an easier way to do this, I have an old PR for a helper function called plotly_merge() that would do most of the heavy lifting for you. Here's an example of what it would look like:

list(
  'NO<sub>x</sub>' = dat |>
    plot_ly(x = ~date, y = ~nox) |>
    add_lines(color = ~site),
  'NO<sub>10</sub>' = dat |>
    plot_ly(x = ~date, y = ~pm10) |>
    add_lines(color = ~site)
) |> 
  plotly_merge(type = 'buttons', y = 0.8)

Edit: here is a link to the PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants