【问题标题】:Looping through R Plotly with subplot and hiding all legend except one使用子图循环遍历 R Plotly 并隐藏除一个之外的所有图例
【发布时间】:2020-03-14 12:57:39
【问题描述】:

我需要循环遍历因子的 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 &lt;- 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 相同的结果。

【问题讨论】:

    标签: r loops plotly legend r-plotly


    【解决方案1】:

    您的代码中有两个问题:

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

    在 if (i == 1) { : 条件长度 > 1 并且只有第一个 将使用元素

    1. showlegend 必须是 plot_ly 的参数,而不是 layout 的参数,因为 subplot 总是采用 one 中的 layout。请参阅?subplot 及其参数which_layout

    稍后在绘图序列中找到的布局选项将覆盖 在序列前面找到的选项


    这就是我认为你所追求的:

    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

    【讨论】:

    • 这就像一个魅力,谢谢。我根本不知道 which_layout 参数。并且没想到要用use seq_along。我想是因为我将 group_cycle 管道传输到 lapply 管道会自动提供迭代。干杯
    【解决方案2】:
    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
    

    【讨论】:

    • 嗨@saheed 谢谢你 - 这是正确的方向,但在我接受答案之前我只有一个后续问题。这部分代码seq(3, length(p[["x"]][["data"]])) 指的是图例条目 3、4、5,我知道我们将其删除。有没有办法以编程方式做到这一点?但实际数据可能有动态数量的图例,所以我正在寻找一种方法来删除它们,就像你所做的那样
    • 我还添加了legendgroup = ~vs,以便我们可以控制所有子图上的变量。
    • 根据所提出的问题,此解决方案将删除除第一个迭代之外的每个迭代的图例(即使还有更多。)我不确定在调用 plotly 时是否有办法做到这一点功能。
    • 查看这一行for (i in seq(3, length(p[["x"]][["data"]]))) 代码会删除图例条目 3、4、5 并留下 1 和 2。但是,它并没有删除“除第一个迭代之外的每个迭代的图例”。不过感谢您的意见 - 我确实认为这是正确的方向
    猜你喜欢
    • 2014-06-18
    • 2011-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-27
    • 2021-11-03
    • 2019-11-04
    相关资源
    最近更新 更多