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
相关产品推荐
相关产品推荐

