如何避免在 plotly 中重复图例并在 R 中垂直设置标题?

How can I avoid duplicate legend in plotly and set title vertically in R?

我使用的代码是:

DF <- data.frame(
  stringsAsFactors = FALSE,
  Month = c("2019-Dec","2019-Dec",
            "2019-Dec","2019-Dec","2020-Jan","2020-Jan","2020-Jan", "2020-Jan"),
  Week = c(4L, 4L, 5L, 5L, 1L, 1L, 1L, 2L),
  Cat = c("A", "B", "A", "C", "A", "B", "C", "A"),
  n = c(17L, 6L, 21L, 10L, 19L, 20L, 12L, 14L)
)

fig <- DF %>%
  split(DF$Month) %>%
  purrr::map(~{
    plot_ly(colors = c("A" = "red", "B" = "green", "C" = "blue", "D" = "black")) %>%
      add_bars(data = .x,
               x = .x$Week,
               y = .x$n,
               type = 'bar',
               split = .x$Cat,
               color = .x$Cat,
               legendgroup = .x$Cat) %>%
      layout(xaxis = list(showticklabels = FALSE, title = unique(.x$Month)))
  })

subplot(fig, shareY = TRUE, titleX = TRUE, margin = 0) %>% 
  layout(barmode = 'stack', showlegend =TRUE)

我在这里面临的问题是右侧的重复图例。而且我还希望月份标题垂直而不是水平。

提前致谢!

这里有一个解决方案,可以避免使用带参数的 showlegend=FALSE/TRUE 重复图例。我不确定 plotly 是否允许您旋转轴标题。但也许您可以尝试使用可以旋转的单个轴刻度?

"%>%" <- magrittr::"%>%"

DF_grp <- DF %>%
  split(DF$Month)


p <- lapply(seq_along(DF_grp),function(idx) {
  show_legend <- switch(idx,
                        "1"=TRUE,
                        "2"=FALSE)
  
  plotly:: plot_ly(colors = c("A" = "red",
                              "B" = "green",
                              "C" = "blue",
                              "D" = "black")) %>%
    plotly::add_bars(data=DF_grp[[idx]],
                     x=~Week,
                     y=~n,
                     type="bar",
                     split=~Cat,
                     color=~Cat,
                     legendgroup=~Cat,
                     showlegend=show_legend) %>%
    plotly::layout(xaxis=list(showticklabels=F,
                              title=unique(DF_grp[[idx]]$Month)),
                   barmode="stack",
                   showlegend =TRUE)
})

p %>%
  plotly::subplot(shareY = TRUE,
                  titleX = TRUE,
                  margin = 0)