簡體   English   中英

在情節子情節中合並圖例

[英]Merging legends in plotly subplot

我有幾個組,其中每個組都有幾個類,我測量了連續值:

set.seed(1)

df <- data.frame(value = c(rnorm(100,1,1), rnorm(100,2,1), rnorm(100,3,1),
                           rnorm(100,3,1), rnorm(100,1,1), rnorm(100,2,1),
                           rnorm(100,2,1), rnorm(100,3,1), rnorm(100,1,1)),
                 class = c(rep("c1",100), rep("c2",100), rep("c3",100),
                           rep("c2",100), rep("c4",100), rep("c1",100),
                           rep("c4",100), rep("c3",100), rep("c2",100)),
                 group = c(rep("g1",300), rep("g2",300), rep("g3",300)))

df$class <- factor(df$class, levels =c("c1","c2","c3","c4"))
df$group <- factor(df$group, levels =c("g1","g2","g3"))

並非數據中的每個組都具有相同的類,或者說不同的是每個組都有所有類的子集。

我正在嘗試為每個組生成R plotly密度曲線,按類進行顏色編碼,然后使用plotly函數將它們全部組合成一個subplot

這就是我正在做的:

library(dplyr)
library(ggplot2)
library(plotly)


set.seed(1)

df <- data.frame(value = c(rnorm(100,1,1), rnorm(100,2,1), rnorm(100,3,1),
                           rnorm(100,3,1), rnorm(100,1,1), rnorm(100,2,1),
                           rnorm(100,2,1), rnorm(100,3,1), rnorm(100,1,1)),
                 class = c(rep("c1",100), rep("c2",100), rep("c3",100),
                           rep("c2",100), rep("c4",100), rep("c1",100),
                           rep("c4",100), rep("c3",100), rep("c2",100)),
                 group = c(rep("g1",300), rep("g2",300), rep("g3",300)))

df$class <- factor(df$class, levels =c("c1","c2","c3","c4"))
df$group <- factor(df$group, levels =c("g1","g2","g3"))

plot.list <- lapply(c("g1","g2","g3"), function(g){
  density.df <- do.call(rbind,lapply(unique(dplyr::filter(df, group == g)$class),function(l)
    ggplot_build(ggplot(dplyr::filter(df, group == g & class == l),aes(x=value))+geom_density(adjust=1,colour="#A9A9A9"))$data[[1]] %>%
      dplyr::select(x,y) %>% dplyr::mutate(class = l)))
  plot_ly(x = density.df$x, y = density.df$y, type = 'scatter', mode = 'lines',color = density.df$class) %>%
    layout(title=g,xaxis = list(zeroline = F), yaxis = list(zeroline = F))
})
subplot(plot.list,nrows=length(plot.list),shareX=T)

這使: 在此處輸入圖片說明

我想解決的問題是:

  1. 讓圖例只出現一次(現在它為每個組重復)合並所有類
  2. 讓標題出現在每個子圖中,而不僅僅是現在的最后一個圖。 (我知道我可以簡單地將組名作為 x 軸標題,但我寧願節省該空間,因為實際上我有 3 個以上的組)

您可以使用以下代碼

library(tidyverse)
library(plotly)

ggplotly(
  ggplot(df, aes(x=value, col = class)) + 
  geom_density(adjust=1) + 
  facet_wrap(~group, ncol = 1) +
    theme_minimal() + 
    theme(legend.position = 'top')
)

這給了我以下情節在此處輸入圖片說明

使用plot_ly()有點棘手,至少如果您想堅持使用color參數從數據中生成多個跟蹤。

您需要考慮到您的類變量來定義legendgroup組。 legendgroup但不會合並傳說物品放入一個(它只是它們分組)。

因此,為了避免圖例中的重復條目,您需要為那些要隱藏的圖例跟蹤設置showlegend = FALSE

由於您不使用循環(或 lapply)來創建子圖的單個軌跡,我們無法在生成圖時控制每個軌跡的可見性(通過上述color參數 - 我們可以隱藏或顯示plot_ly調用的所有跟蹤 - 通過add_trace我們可以單獨控制每個跟蹤)。 因此,我僅為第一個圖設置showlegend = TRUE並強制它通過虛擬數據顯示所有可用類。 請參閱以下內容:

set.seed(1)

df <- data.frame(value = c(rnorm(100,1,1), rnorm(100,2,1), rnorm(100,3,1),
                           rnorm(100,3,1), rnorm(100,1,1), rnorm(100,2,1),
                           rnorm(100,2,1), rnorm(100,3,1), rnorm(100,1,1)),
                 class = c(rep("c1",100), rep("c2",100), rep("c3",100),
                           rep("c2",100), rep("c4",100), rep("c1",100),
                           rep("c4",100), rep("c3",100), rep("c2",100)),
                 group = c(rep("g1",300), rep("g2",300), rep("g3",300)))

df$class <- factor(df$class, levels =c("c1","c2","c3","c4"))
df$group <- factor(df$group, levels =c("g1","g2","g3"))

library(dplyr)
library(ggplot2)
library(plotly)

plot.list <- lapply(c("g1","g2","g3"), function(g){
  density.df <- do.call(rbind,lapply(unique(dplyr::filter(df, group == g)$class),function(l)
    ggplot_build(ggplot(dplyr::filter(df, group == g & class == l),aes(x=value))+geom_density(adjust=1,colour="#A9A9A9"))$data[[1]] %>%
      dplyr::select(x,y) %>% dplyr::mutate(class = l)))
  
  p <- plot_ly(data = density.df, x = ~x, y = ~y, type = 'scatter', mode = 'lines', color = ~class, legendgroup = ~class, showlegend = FALSE) %>%
    layout(xaxis = list(zeroline = F), yaxis = list(zeroline = FALSE)) %>%
    add_annotations(
      text = g,
      x = 0.5,
      y = 1.1,
      yref = "paper",
      xref = "paper",
      xanchor = "middle",
      yanchor = "top",
      showarrow = FALSE,
      font = list(size = 15)
    )
  if(g == "g1"){
    dummy_df <- data.frame(class = unique(df$class))
    dummy_df$x <- density.df$x[1]
    dummy_df$y <- density.df$y[1]
    p <- add_trace(p, data = dummy_df, x = ~x, y = ~y, color = ~class, type = "scatter", mode = "lines", showlegend = TRUE, legendgroup = ~class, hoverinfo = 'none')
  }
  p
})

subplot(plot.list, nrows = length(plot.list), shareX = TRUE)

結果

另一種方法(避免虛擬數據解決方法)是在循環中(或通過 lapply)創建每個跟蹤,並根據項目的第一次出現控制它的圖例可見性。

此外,我認為應該可以使用?plotly::style控制圖例項的?plotly::style 但是,我目前無法控制單個跟蹤。 在這里提出了一個問題。

關於子圖的標題,請看這個

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM