How to remove duplicate legend entries w/ plotly subplots()
Another workaround using the tidyverse
. The following steps are added to the original MWE:
- Convert the
trans
column to a factor. - Use tidyr's
complete
to fill (non-NA) dummy values for the missing factor levels in eachclass
group. - Follow M-M's suggestion setting
showlegend
toTRUE
for a single group andlegendgroup
totrans
to link the legend entries between subplots.
library(plotly)
library(tidyverse)
mpg %>%
mutate_at("trans", as.factor) %>%
group_by(class) %>%
group_map(.f = ~{
## fill missing levels w/ displ = 0, cyl = first available value
complete(.x, trans, fill = list(displ = 0, cyl = head(.x$cyl, 1))) %>%
plot_ly(x = ~cyl, y = ~displ, color = ~trans, colors = "Paired", type = "bar",
showlegend = (.y == "2seater"), legendgroup = ~trans) %>%
layout(yaxis = list(title = as.character(.y)), barmode = "stack")
}) %>%
subplot(nrows = 2, shareX = TRUE, titleY = TRUE)
plotly
does not have facet
like ggplot2
so it will add legend for each subplot
or you can turn it off for some of them.
Here we do not have a layer with all the ~class
entries nor two plots with no intersection in class
which their combination also covers all of them. In that case, we could set showlegend
to TRUE
for those specific plot(s) and set it to FALSE
for the rest and also set the legendgroup
to trans
so we get a unique but also complete legend.
As I said, here we do not have that special case. So What I can think of are two possibilities:
Adding the whole data (duplicating whole dataframe) and assigning class of
All
to them. Then plotting that along with original data but keep the legend only forclass == All
.Using
ggplot::facet_wrap
and thenggplotly
to make aplotly
object. However, this would cause some issues withx-axis
(compareggplot
object toplotly
ones).
library(plotly)
library(ggplot2)
library(dplyr)
ly_plot <- . %>%
plot_ly(x = ~cyl, y = ~displ, color = ~trans,
type = 'bar', showlegend = ~all(legendC)) %>%
add_annotations(
text = ~unique(class),
x = 0.5,
y = 1,
yref = "paper",
xref = "paper",
xanchor = "middle",
yanchor = "top",
showarrow = FALSE,
font = list(size = 15))
mpg %>%
mutate(class= "_All_") %>%
rbind(.,mpg) %>%
mutate(legendC = (class == "_All_")) %>%
group_by(class) %>%
do(p = ly_plot(.)) %>%
subplot(nrows = 2, shareX = TRUE, titleX = TRUE) %>%
layout(barmode = 'stack')
#> Warning in RColorBrewer::brewer.pal(N, "Set2"): n too large,
#> allowed maximum for palette Set2 is 8
#> Returning the palette you asked for with that many colors
p <- ggplot(data = mpg, aes(x=cyl, y=displ, fill=trans))+
geom_bar(stat="identity") +
facet_wrap(~class)
p
ggplotly(p) #seems for this we should also set "colour = trans"