使用子图循环 R Plotly 并隐藏除一个图例之外的所有图例

Looping through R Plotly with subplot and hiding all legend except one

我需要遍历 i 个因子迭代,并且每个因子都需要绘制为子图中的一个图。我想做的是隐藏第一次迭代的图例,并使用 legendgroup 将所有图例联系在一起。这是我到目前为止所做的:

library(plotly)
library(dplyr)

mtcars %>%
  mutate(vs = as.factor(vs)) %>%
  group_split(cyl) %>%
  lapply(function(i) {

    #show.legend <- ifelse(i == 1, TRUE, FALSE)

    show.legend <- if(i == 1) {TRUE} else {FALSE}

    plot_ly(
      data = i
      ,x = ~gear
      ,y = ~mpg
      ,color = ~vs
      ,type = "bar"
      ,legendgroup = ~vs
    ) %>%
      layout(
        barmode = "stack"
        ,showlegend = show.legend
      )
  }) %>%
  subplot(
    nrows = NROW(.)
    ,shareX = TRUE
    ,shareY = TRUE
    ,titleX = TRUE
    ,titleY = TRUE
    ,margin = 0.05
  )

但是这会产生错误并且没有图例:

Warning messages:
1: In if (i == 1) { :
  the condition has length > 1 and only the first element will be used

如果我使用 show.legend <- ifelse(i == 1, TRUE, FALSE)(上面已注释掉),我会得到多个图例,而不仅仅是一次。

我知道我可以执行以下操作,但我需要循环执行此操作。

p1 <- plot_ly(blah, showlegend = TRUE)
p2 <- plot_ly(blah, showlegend = FALSE)
P3 <- plot_ly(blah, showlegend = FALSE)

subplot(p1,p2,p3)

我相信我没有正确调用 i 迭代。作为另一种选择,我尝试了 case_when:

show.legend <- case_when(
      i == 1 ~ TRUE
      ,i != 1 ~ FALSE
    )

但是这会产生与 ifelse 相同的结果。

library(plotly)
library(dplyr)

    ## store plot as variable p
        p <- mtcars %>%
            mutate(vs = as.factor(vs)) %>%
            group_split(cyl) %>%
            lapply(function(i) {
                plot_ly(
                    data = i
                    ,x = ~gear
                    ,y = ~mpg
                    ,color = ~vs
                    ,type = "bar"
                    ,showlegend = TRUE ## include all legends in stored variable
                ) %>%
                    layout(
                        barmode = "stack"
                    )
            }) %>%
            subplot(
                nrows = NROW(.)
                ,shareX = TRUE
                ,shareY = TRUE
                ,titleX = TRUE
                ,titleY = TRUE
                ,margin = 0.05
            )
    ## remove unwanted legends from plot
        for (i in seq(3, length(p[["x"]][["data"]]))) {
            p[["x"]][["data"]][[i]][["showlegend"]] <- FALSE
        }
    ## show plot
        p

您的代码中有两个问题:

  1. i 不是 1:3,而是您正在通过 lapply 迭代的当前小标题(请参阅下面的 seq_along)。 这就是您收到警告的原因:

In if (i == 1) { : the condition has length > 1 and only the first element will be used

  1. showlegend 需要作为 plot_ly 而非 layout 的参数,因为子图总是采用 one 中的 layout它的地块。参见 ?subplot 及其参数 which_layout.

layout options found later in the sequence of plots will override options found earlier in the sequence


这是我认为你想要的:

library(plotly)
library(dplyr)

tibble_list <- mtcars %>%
  mutate(vs = as.factor(vs)) %>%
  group_split(cyl)

lapply(seq_along(tibble_list), function(i) {
  show_legend <- if (i == 1) {TRUE} else {FALSE}
  plot_ly(
    data = tibble_list[[i]],
    x = ~ gear,
    y = ~ mpg,
    color = ~ vs,
    type = "bar",
    legendgroup = ~ vs,
    showlegend = show_legend
  ) %>% layout(barmode = "stack")
}) %>% subplot(
  nrows = NROW(.),
  shareX = TRUE,
  shareY = TRUE,
  titleX = TRUE,
  titleY = TRUE,
  margin = 0.05,
  which_layout = 1
)

请找一个官方例子here