2

Building on this post, I am trying to create two updatemenus in R plotly that would allow to select every possible combination of two factors.

This is what I have done so far:

library(plotly)

X <- data.frame(x = 1:6,
                y = 1:6,
                z = 1:6,
                gender = rep(c("M", "F"), each = 3),
                eyes = rep(c("B", "G"), 3))

gg <- ggplot(data = X, aes(x = x, y = y)) + 
  geom_point(aes(color = z, alpha = interaction(gender, eyes))) +
  scale_alpha_manual(values = rep(1, 4))


ggplotly(gg) %>% 
  layout(
    updatemenus = list(
      list(y = 1,
           buttons = list(
             list(method = "restyle",
                  args = list(list(visible = c(TRUE, TRUE, TRUE, TRUE)), 0:3),
                  label = "F&M"),
             list(method = "restyle",
                  args = list(list(visible = c(TRUE, TRUE)), c(0, 2)),
                  label = "F"),
             list(method = "restyle",
                  args = list(list(visible = c(TRUE, TRUE)), c(1, 3)),
                  label = "M"))),
      list(y = .8,
           buttons = list(
             list(method = "restyle",
                  args = list(list(visible = c(TRUE, TRUE, TRUE, TRUE)), 0:3),
                  label = "B&G"),
             list(method = "restyle",
                  args = list(list(visible = c(TRUE, TRUE)), 0:1),
                  label = "B"),
             list(method = "restyle",
                  args = list(list(visible = c(TRUE, TRUE)), 2:3),
                  label = "G")))
    )
  )
)

The data:

#  x y z gender eyes
#  1 1 1      M    B
#  2 2 2      M    G
#  3 3 3      M    B
#  4 4 4      F    G
#  5 5 5      F    B
#  6 6 6      F    G

This is the output, which does not work at all: enter image description here


Edit
For instance, if F and B are selected, I would expect only a single data point to be displayed, namely (5, 5).

mat
  • 2,412
  • 5
  • 31
  • 69

1 Answers1

3

When you created this plotly object, plotly divided it into five traces. So when you wanted to use visibility, you needed to address each of these traces. If you have any questions, let me know!

I used gg1 to find five traces and what was in each of these traces. You could look at gg1 in the source pane or plotly_json().

Typically (not always!), you'll find the traces at gg1$x$data where gg1 is the plotly object.

There are five traces. For each args, each trace needs a T or F for visibility.

  • The first trace only contains (5, 5), that's F B
  • The second trace contains (1, 1) and (3, 3); those are both M B
  • The third trace contains (4, 4) and (6, 6); those are both F G
  • The fourth trace contains (2, 2); that's M G
  • The fifth trace contains the color gradient that all traces use

Here's the code:

gg1 = plotly_build(gg) 

ggplotly(gg) %>% 
  layout(
    updatemenus = list(

      list(y = 1,
           buttons = list(
             list(method = "restyle",
                  args = list("visible", as.list(unlist(rep(T, 5)))),
                  label = "F&M"),
             list(method = "restyle",
                  args = list("visible", list(T, F, T, F, T)),
                  label = "F"),
             list(method = "restyle",
                  args = list("visible", list(F, T, F, T, T)),
                  label = "M")
             ) # end button
           ),  # end first button list
      list(y = .8,
           buttons = list(
             list(method = "restyle",
                  args = list("visible", as.list(unlist(rep(T, 5)))),
                  label = "B&G"),
             list(method = "restyle",
                  args = list("visible", list(T, T, F, F, T)),
                  label = "B"),
             list(method = "restyle",
                  args = list("visible", list(F, F, T, T, T)),
                  label = "G")
             ) # end button
           ) # end second menu list
    ) # end updatemenus
  ) # end layout


Update

From our comments, I do not believe that it's possible at this time to use updatemenus style buttons that interact with each other.

Kat
  • 15,669
  • 3
  • 18
  • 51
  • Thanks for clarifying that there are in fact 5 traces, I hadn't notice! I tried the code you provided, but it does not seem to work as intended. It seems that the two menus are working independently from each other. For instance if I select `F` and `B` I would expect only `F.B` data points to show up, but this is not the case. – mat Apr 10 '22 at 14:14
  • 1
    It took me a second to figure out what you meant! You are referring to the combination of the two dropdown options. At this time, I'm fairly confident that the functionality of interconnected dropdowns is not supported by `plotly`. However, you could add a third button that looks at both gender and eyes that would have all of the possible combinations in it. – Kat Apr 10 '22 at 15:11
  • That's precisely what I'm looking for, perhaps I wasn't clear enough. I could indeed have a dropdown menu with all combinations, the problem is, it grows exponentially as you add more factors, and would be thus impractical. – mat Apr 10 '22 at 16:13
  • You could potentially code it in JS. If you're using RMD, *nearly* any JS is possible. If you aren't using RMD, `plotly` uses `htmlwidgets`, so you could use "JS-ish." It's "-ish" because, despite all the books that say "JS" for htmlwidgets, it's not nearly that liberal. The limitations of the primary library (`plotly` in this case) and `htmlwidgets` are controllers. There are many ways I might look for an element or code changes using JS where only one or two of these might work with `htmlwidgets` and `plotly`. – Kat Apr 12 '22 at 03:58
  • 1
    @Kat I guess using plotly's [filter transforms](https://plotly.com/r/filter/) (unfortunately [deprecated](https://plotly.com/javascript/multiple-transforms/)) or `crosstalk` would be another option, as it was suggested to @mat [here](https://stackoverflow.com/a/71657272/9841389). – ismirsehregal Apr 12 '22 at 06:55
  • @Kat can you update your answer and mention that there's likely no way to achieve this via the `updatemenus` so I can approve it? Thanks! – mat Apr 14 '22 at 06:23
  • 1
    @mat, I updated my answer the other day but didn't comment on it. (I just realized that!) – Kat Apr 18 '22 at 16:58