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

和自甴很熟 提交于 2021-02-19 07:48:05

问题


I need to loop through i iteration of factors, and each factor needs to be plotted as one plot in a subplot. What I would like to do is hiding the legend for every iteration bar the first one, and use legendgroup to tie all the legends together. This is what I have done so far:

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
  )

However this produces an error and no legend:

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

If I use show.legend <- ifelse(i == 1, TRUE, FALSE) (commented out above), I get multiple legends instead of just once.

I am aware I could do the below, but I need to this in a loop.

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

subplot(p1,p2,p3)

I believe I am not calling the i iteration properly. As another option I tried case_when:

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

However this produces the same result as ifelse.


回答1:


There are two issues in your code:

  1. i is not 1:3 but your current tibble you are iterating through via lapply (see seq_along below). That is why you get the warning:

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

  1. showlegend needs to be an argument to plot_ly not to layout because subplot always adopts the layout from one of its plots. see ?subplot and its argument which_layout.

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


Here is what I think you are after:

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
)

Please find an offical example here.




回答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



来源:https://stackoverflow.com/questions/58926716/looping-through-r-plotly-with-subplot-and-hiding-all-legend-except-one

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!