问题
How can I remove the duplicates in my legend when using plotly's subplots()?
Here is my MWE:
library(plotly)
library(ggplot2)
library(tidyr)
mpg %>%
group_by(class) %>%
do(p = plot_ly(., x = ~cyl, y = ~displ, color = ~trans, type = 'bar')) %>%
subplot(nrows = 2, shareX = TRUE, titleX = TRUE) %>%
layout(barmode = 'stack')
回答1:
Another workaround using the tidyverse. The following steps are added to the original MWE:
- Convert the
transcolumn to a factor. - Use tidyr's
completeto fill (non-NA) dummy values for the missing factor levels in eachclassgroup. - Follow M-M's suggestion setting
showlegendtoTRUEfor a single group andlegendgrouptotransto 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)
回答2:
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
Allto them. Then plotting that along with original data but keep the legend only forclass == All.Using
ggplot::facet_wrapand thenggplotlyto make aplotlyobject. However, this would cause some issues withx-axis(compareggplotobject toplotlyones).
library(plotly)
library(ggplot2)
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"
来源:https://stackoverflow.com/questions/57253488/how-to-remove-duplicate-legend-entries-w-plotly-subplots