Plotly legendgroup 用于子图,因此单个图例控制所有图表

问题描述 投票:0回答:3

我在

plotly
中使用
r
来生成许多子图。下面显示了一个玩具示例。

library(shiny)
library(dplyr)
library(plotly)

## Toy Example
ui <- fluidPage(
  h3("Diamonds"),
  plotlyOutput("plot", height = 600)
)

server <- function(input, output, session) {

  # reduce down the dataset to make the example simpler
  dat <- diamonds %>% 
    filter(clarity %in% c("I1", "IF")) %>%
    mutate(clarity = factor(clarity, levels = c("I1", "IF")))

  output$plot <- renderPlotly({

    # Generates the chart for a single clarity
    byClarity <- function(df){

      Clarity <- df$clarity[1];

      plot_ly(df, x = ~carat, y = ~price, color = ~cut, name = ~clarity) %>%
        add_trace(
          type="bar"
          ## Also tried adding this with no success
          # legendgroup = ~cut
        ) %>%
        layout(
          barmode = "stack"
        )
    }

    dat %>% 
      split(.$clarity) %>% 
      lapply(byClarity) %>%
      subplot(nrows = NROW(.), shareX = TRUE, which_layout = "merge")
  })
} 

shinyApp(ui, server)

我想制作图例,点击图例上的“剪切”将显示/隐藏来自both图表的“剪切”,而不仅仅是与该图例相关的图表。

DefaultVsIdeal

我查看了 legendgroup 但无法弄清楚如何将它与

cut
而不是
clarity
相关联(
clarity
是我用来制作子图的分组)。

我还需要解决方案来处理原始

plot_ly
而不是
ggplotly
,因为我需要的其他
plot_ly
功能在
ggplotly
中不可用。

任何帮助将不胜感激。我正在使用

plotly_4.5.2
dplyr_0.5.0
shiny_0.14

r shiny plotly
3个回答
1
投票

好的,这是一个使用

ggplot2
的解决方案:

library(ggplot2)
library(dplyr)
library(plotly)
dat <- diamonds %>% 
  filter(clarity %in% c("I1", "IF")) %>%
  mutate(clarity = factor(clarity, levels = c("I1", "IF")))
# Function for nice labels
k_label <- function(x) {
 c(0, paste0((x)/1000,"K")[-1])
}
# ggplot
p <- ggplot(dat,aes(x=carat, y=price, fill=cut)) + 
           geom_bar(stat="identity") + 
           facet_wrap(~clarity,nrow=2, scales = "free_y") +
           scale_y_continuous(labels = k_label) + 
           theme_minimal() + ylab("") + xlab("") +
           theme(legend.title=element_blank(),
                 panel.grid.major.x=element_blank())
# a plotly
ggplotly(p)


1
投票

尝试将

legendgroup = ~cut
添加到两条轨迹中,并为其中一条轨迹设置
showlegend = F
。然后在布局中设置
showlegend = T

像这样:

plot_ly(df, x = ~carat, y = ~price, color = ~cut, name = ~clarity, legendgroup = ~cut, showlegend = T) %>%
    add_trace( type="bar", legendgroup = ~cut, showlegend = F) %>%
    layout(
      barmode = "stack",showlegend = T
    )

0
投票

我有一个纯 plot_ly 代码的工作示例。然而,这不是我最自豪的作品:

library(ggplot2)
library(dplyr)
library(plotly)
dat <- diamonds %>% 
    filter(clarity %in% c("I1", "IF")) %>%
    mutate(clarity = factor(clarity, levels = c("I1", "IF")))

firstPlot <- plot_ly(data = dat, x = ~carat, y = ~depth, legendgroup = ~cut, color = ~cut)
secondPlot <- plot_ly(data = dat, x = ~carat, y = ~price, legendgroup = ~cut, color = ~cut)

together <- subplot(firstPlot, secondPlot)
together

这产生了这个,但图例仍然有重复项。这可以用

showLegend = FALSE
参数解决,但不是以传统方式..

for (layer in 1L:(length(together$x$data) / 2L)) {
    together$x$data[[layer]]$showlegend <- FALSE
}
together

这给出了仍然链接在一起的最终图,同时只显示一个值。 如果您计划使用两个以上的子图,则可以更改 for 循环(也可以是 lapply)以选择所有层 除了第一个通过执行

length(unique(dat$cut)):length(together$x$data)
从长远来看更稳健。

注意:这适用于大多数 plot_ly 图表,但不适用于所有图表(例如

'box'
),所以如果您想应用它但仍需要帮助,请告诉我!

© www.soinside.com 2019 - 2024. All rights reserved.