问题
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