How to link plotly traces for legend and colour selection?

徘徊边缘 提交于 2019-12-21 18:00:09

问题


Problem

I am migrating a number of ggplot/ggvis plots to plotly in a shiny application. There is an issue I've encountered regarding the linking of traces. I want to be able to show/hide traces by group on the legend, which is shared between related data frames.

Minimal working example

# load libraries
library(dplyr)
library(plotly)
library(viridis)

# contrived data to represent actual data points
df1 <- data.frame(x = rnorm(100),
                  y = rnorm(100),
                  group = rep(c("G1", "G2", "G3", "G4"), 25))

# contrived data to represent theoretical relationship
df2 <- data.frame(x = c(rep(-2, 4), rep(2, 4)),
                  y = c(seq(1.9, 1, -0.3), seq(-1, -1.9, -0.3)),
                  group = rep(c("G1", "G2", "G3", "G4"), 2))

# create plot with scatter and line traces
df1 %>%
  plot_ly(x = x,
          y = y,
          color = group,
          colors = viridis(n_distinct(group)),
          mode = "markers") %>%
  add_trace(x = x,
            y = y,
            color = group,
            colors = viridis(n_distinct(group)),
            mode = "lines",
            data = df2)

Attempts so far

My online searches and especially reading the plotly documentation have not taken me far.

I can add showlegend = FALSE to the second trace. That does go part way to addressing the challenge, however, I still want to show/hide that trace based on the group value.

Possible solutions

Based on the architecture of plotly, it seems that if I could put the scatter and line onto one trace per group then I would get the desired behaviour. However, it seems that a trace may only have a single "mode", which is why I've taken the approach that I have.

If I continue down the path I've started, I think I need to somehow trap the "on click" event for the legend and show/hide the group traces... but I'm not really sure where to begin with that.

Related / Secondary

In my MWE, I have set the colors argument to viridis. While that is unimportant to the problem, I have not found a way to ensure the colour selection is instead linked to the group (i.e. if the trace for group on df1 is blue, I want to make the same group blue on the trace for df2. If this is non-trivial and warrants a second question (I searched and found no match... possibly because it is trivial and I'm missing something simple), then I'll ask this part separately.


回答1:


Revisiting history for posterity

Several changes to ggplot2 and plotly in the intervening time since this question was first asked. In the current version (4.7.1) there is an argument legendgroup that attends to solving the problem.

Lazy code

Please forgive the minimum effort placed on elegant coding, however, this extension to the MWE demonstrates the ability to show/hide traces by group.

df1_G1 <- df1 %>% filter(group == "G1")
df2_G1 <- df2 %>% filter(group == "G1")
df1_G2 <- df1 %>% filter(group == "G2")
df2_G2 <- df2 %>% filter(group == "G2")
df1_G3 <- df1 %>% filter(group == "G3")
df2_G3 <- df2 %>% filter(group == "G3")
df1_G4 <- df1 %>% filter(group == "G4")
df2_G4 <- df2 %>% filter(group == "G4")

plot_ly(type = "scatter", mode = "markers") %>%
  add_trace(df1_G1, x = df1_G1$x, y = df1_G1$y, color = I("red"),
            legendgroup = "G1", name = "G1 - scatter") %>%
  add_trace(df2_G1, x = df2_G1$x, y = df2_G1$y, color = I("red"),
            legendgroup = "G1", name = "G1 - line", mode = "lines") %>%
  add_trace(df1_G2, x = df1_G2$x, y = df1_G2$y, color = I("green"), 
            legendgroup = "G2", name = "G2 - scatter") %>%
  add_trace(df2_G2, x = df2_G2$x, y = df2_G2$y, color = I("green"),
            legendgroup = "G2", name = "G2 - line", mode = "lines") %>%
  add_trace(df1_G3, x = df1_G3$x, y = df1_G3$y, color = I("blue"),
            legendgroup = "G3", name = "G3 - scatter") %>%
  add_trace(df2_G3, x = df2_G3$x, y = df2_G3$y, color = I("blue"),
            legendgroup = "G3", name = "G3 - line", mode = "lines") %>%
  add_trace(df1_G4, x = df1_G4$x, y = df1_G4$y, color = I("orange"), 
            legendgroup = "G4", name = "G4 - scatter") %>%
  add_trace(df2_G4, x = df2_G4$x, y = df2_G4$y, color = I("orange"), 
            legendgroup = "G4", name = "G4 - line", mode = "lines")

Sample output

Showing the first group G1 deselected. Also note that the colours have been made to match between the scatter and line traces for the same group.



来源:https://stackoverflow.com/questions/36415819/how-to-link-plotly-traces-for-legend-and-colour-selection

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!