You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R语言Plotly子图共享图例问题求助

嘿,我来帮你搞定这个Plotly子图共享图例的问题!你的核心需求是让一个图例同时控制两个子图的对应trace,现在的问题是你只在第一个子图的第一个trace设置了showlegend=F,后面的trace依然会生成图例条目,导致合并后图例重复;而如果给整个图设置showlegend=F又会直接移除所有图例。

解决方法:统一trace属性+控制单个trace的图例显示

要实现共享图例,关键是让两个子图中对应类别的trace拥有完全相同的name和fillcolor,然后让其中一个子图的所有trace都显示图例,另一个子图的所有trace都隐藏图例。这样Plotly会自动关联同名同样式的trace,点击图例时两个子图的对应元素会同步响应。

修改你的代码如下:

1. 修改非中国区域的图表代码(所有trace隐藏图例)

coronavirus_not_china <- coronavirus %>% filter(!(country == "China"))
cases_not_china_plot <- coronavirus_not_china %>% 
  group_by(type, date) %>% 
  summarise(total_cases = sum(cases)) %>% 
  pivot_wider(names_from = type, values_from = total_cases) %>% 
  arrange(date) %>% 
  mutate(active = confirmed - death - recovered) %>% 
  mutate(active_total = cumsum(active), 
         recovered_total = cumsum(recovered), 
         death_total = cumsum(death)) %>% 
  plot_ly(x = ~ date, 
          y = ~ active_total, 
          name = 'Active', 
          fillcolor = '#1f77b4', 
          type = 'scatter', 
          mode = 'none', 
          stackgroup = 'one', 
          showlegend = FALSE) %>%  # 第一个trace隐藏图例
  add_trace(y = ~ death_total, 
            name = "Death", 
            fillcolor = '#E41317',
            showlegend = FALSE) %>%  # 第二个trace隐藏图例
  add_trace(y = ~recovered_total, 
            name = 'Recovered', 
            fillcolor = 'forestgreen',
            showlegend = FALSE) %>%  # 第三个trace隐藏图例
  layout(title = "Distribution of Covid19 Cases outside China", 
         yaxis = list(title = "Number of Cases", showgrid = T))  # 移除单独的legend设置,统一在子图后处理

2. 中国区域的图表代码保持不变(默认显示所有trace的图例)

coronavirus_china <- coronavirus %>% filter((country == "China"))
cases_china_plot <- coronavirus_china %>% 
  group_by(type, date) %>% 
  summarise(total_cases = sum(cases)) %>% 
  pivot_wider(names_from = type, values_from = total_cases) %>% 
  arrange(date) %>% 
  mutate(active = confirmed - death - recovered) %>% 
  mutate(active_total = cumsum(active), 
         recovered_total = cumsum(recovered), 
         death_total = cumsum(death)) %>% 
  plot_ly(x = ~ date, 
          y = ~ active_total, 
          name = 'Active', 
          fillcolor = '#1f77b4', 
          type = 'scatter', 
          mode = 'none', 
          stackgroup = 'one') %>%  # 默认showlegend=T,不用额外设置
  add_trace(y = ~ death_total, 
            name = "Death", 
            fillcolor = '#E41317') %>% 
  add_trace(y = ~recovered_total, 
            name = 'Recovered', 
            fillcolor = 'forestgreen') %>% 
  layout(title = "Distribution of Covid19 Cases inside China", 
         yaxis = list(title = "Number of Cases", showgrid = F))

3. 子图合并代码(统一设置图例和全局标题)

subplot(cases_not_china_plot, cases_china_plot, nrows = 2, margin = 0.05, shareX = T) %>% 
  layout(title = "Coronavirus cases outside China and in China", 
         yaxis = list(title = "Number of cases"),
         legend = list(x = 0.1, y = 0.9))  # 统一设置图例位置

额外优化建议(减少重复代码)

你会发现两个图表的数据处理逻辑几乎完全一样,只是过滤条件不同。可以把这部分封装成一个函数,让代码更简洁易维护:

# 封装数据处理函数
prepare_covid_data <- function(data, country_condition) {
  data %>% 
    filter({{country_condition}}) %>% 
    group_by(type, date) %>% 
    summarise(total_cases = sum(cases)) %>% 
    pivot_wider(names_from = type, values_from = total_cases) %>% 
    arrange(date) %>% 
    mutate(active = confirmed - death - recovered) %>% 
    mutate(active_total = cumsum(active), 
           recovered_total = cumsum(recovered), 
           death_total = cumsum(death))
}

# 生成两个数据集
china_data <- prepare_covid_data(coronavirus, country == "China")
not_china_data <- prepare_covid_data(coronavirus, !(country == "China"))

# 生成图表
cases_china_plot <- china_data %>% 
  plot_ly(x = ~ date, y = ~ active_total, name = 'Active', fillcolor = '#1f77b4', type = 'scatter', mode = 'none', stackgroup = 'one') %>% 
  add_trace(y = ~ death_total, name = "Death", fillcolor = '#E41317') %>% 
  add_trace(y = ~recovered_total, name = 'Recovered', fillcolor = 'forestgreen') %>% 
  layout(title = "Distribution of Covid19 Cases inside China", yaxis = list(title = "Number of Cases", showgrid = F))

cases_not_china_plot <- not_china_data %>% 
  plot_ly(x = ~ date, y = ~ active_total, name = 'Active', fillcolor = '#1f77b4', type = 'scatter', mode = 'none', stackgroup = 'one', showlegend = FALSE) %>% 
  add_trace(y = ~ death_total, name = "Death", fillcolor = '#E41317', showlegend = FALSE) %>% 
  add_trace(y = ~recovered_total, name = 'Recovered', fillcolor = 'forestgreen', showlegend = FALSE) %>% 
  layout(title = "Distribution of Covid19 Cases outside China", yaxis = list(title = "Number of Cases", showgrid = T))

# 合并子图
subplot(cases_not_china_plot, cases_china_plot, nrows = 2, margin = 0.05, shareX = T) %>% 
  layout(title = "Coronavirus cases outside China and in China", 
         yaxis = list(title = "Number of cases"),
         legend = list(x = 0.1, y = 0.9))

这样修改后,点击图例中的任意条目,两个子图对应的类别都会同步显示/隐藏,完美实现共享图例的效果!

内容的提问来源于stack exchange,提问作者Simon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 07:22:40