使用 ggplotly() 时反转图例顺序

Reverse the legend order when using ggplotly()

我想颠倒水平条形图图例的顺序。将 guides(fill = guide_legend(reverse = TRUE)) 添加到 ggplot 时效果很好(见第二个图)。但是,在应用 ggplotly() 之后,图例再次采用默认顺序。

如何在不改变条形顺序的情况下反转plotly图例的顺序

library(ggplot2)
library(dplyr)
data(mtcars)

p1 <- mtcars %>%
  count(cyl, am) %>%
  mutate(cyl = factor(cyl), am = factor(am)) %>%
  ggplot(aes(cyl, n, fill = am)) +
  geom_col(position = "dodge") +
  coord_flip()
p1


p2 <- p1 + guides(fill = guide_legend(reverse = TRUE))
p2

plotly::ggplotly(p2)

一个简单的解决方案是定义因子变量水平的顺序 am:

library(ggplot2)
library(dplyr)
data(mtcars)


df <-  mtcars %>%
  count(cyl, am) %>%
  mutate(cyl = factor(cyl), am = factor(as.character(am), levels = c("1", "0"))) 

head(df)


p1 <- df %>%
  ggplot(aes(cyl, n, fill = am)) +
  geom_col(position = "dodge") +
  coord_flip()
p1

plotly::ggplotly(p1)

当您调用 ggplotly 时,它实际上只是创建一个列表并在该列表上调用一个函数。

所以如果你省去了那个中间步骤,你可以直接修改列表。因此,修改绘图输出。

library(ggplot2)
library(dplyr)
data(mtcars)

p1 <- mtcars %>%
  count(cyl, am) %>%
  mutate(cyl = factor(cyl), am = factor(am)) %>%
  ggplot(aes(cyl, n, fill = am)) +
  geom_col(position = "dodge") +
  coord_flip()

html_plot <- ggplotly(p1)

replace_1 <- html_plot[["x"]][["data"]][[2]]
replace_2 <- html_plot[["x"]][["data"]][[1]]
html_plot[["x"]][["data"]][[1]] <- replace_1
html_plot[["x"]][["data"]][[2]] <- replace_2

html_plot

plot output

在@Zac Garland 的精彩回答中添加一个适用于任意长度图例的解决方案:

library(ggplot2)
library(dplyr)

reverse_legend_labels <- function(plotly_plot) {
  n_labels <- length(plotly_plot$x$data)
  plotly_plot$x$data[1:n_labels] <- plotly_plot$x$data[n_labels:1]
  plotly_plot
}

p1 <- mtcars %>%
  count(cyl, am) %>%
  mutate(cyl = factor(cyl), am = factor(am)) %>%
  ggplot(aes(cyl, n, fill = am)) +
  geom_col(position = "dodge") +
  coord_flip()

p2 <- mtcars %>%
  count(am, cyl) %>%
  mutate(cyl = factor(cyl), am = factor(am)) %>%
  ggplot(aes(am, n, fill = cyl)) +
  geom_col(position = "dodge") +
  coord_flip()
p1 %>%
  plotly::ggplotly() %>%
  reverse_legend_labels()

p2 %>%
  plotly::ggplotly() %>%
  reverse_legend_labels()