Plotly中px.timeline与make_subplots联用:子图条形拆分问题
Plotly Timeline子图条形拆分问题解决方案
问题背景
使用Plotly的px.timeline生成按分组区分的水平时间线条形图,用颜色表示不同状态,需要通过make_subplots将多个图垂直排列。单个图显示正常,但组合后每个子图内的条形被拆分为多个,无法保持每组一个条形的样式。
已尝试的方法:
- 移除
px.timeline中的color='status'参数,拆分问题解决,但无法为状态添加颜色区分 - 使用
add_trace()替代add_traces(),仅能显示True或False其中一种状态,无法同时展示两种
解决方案
核心原因是px.timeline生成的Trace默认共享全局Y轴的类别配置,组合子图时需手动为每个子图绑定独立的Y轴配置,同时保留颜色区分。具体步骤如下:
- 创建子图时明确每个子图的类型为
bar(timeline基于条形图实现) - 为每个
px.timeline生成的图,分别提取其Trace数据和Y轴配置,添加到对应子图位置 - 为每个子图单独应用原Timeline图的Y轴配置,确保分组显示正常
修改后的完整代码
import pandas as pd import plotly.express as px from plotly.subplots import make_subplots # 准备示例数据 data = [ [True, '2016-11-28 00:06:00.000000', '2016-11-28 00:10:00.000000', 'Lamp'], [False, '2016-11-28 00:10:00.000000', '2016-11-28 00:14:00.000000', 'Lamp'], [True, '2016-11-28 00:14:00.000000', '2016-11-28 00:18:00.000000', 'Lamp'] ] columns = ['status', 'start', 'end', 'group'] df = pd.DataFrame(data, columns=columns) df['start'] = pd.to_datetime(df['start']) df['end'] = pd.to_datetime(df['end']) # 创建垂直排列的子图,指定每个子图类型为bar subfig = make_subplots(rows=2, cols=1, specs=[[{"type": "bar"}], [{"type": "bar"}]]) # 生成两个独立的Timeline图 fig1 = px.timeline(df, x_start='start', x_end='end', y="group", color="status") fig2 = px.timeline(df, x_start='start', x_end='end', y="group", color="status") # 添加第一个子图的Trace和Y轴配置 subfig.add_traces(fig1.data, rows=1, cols=1) subfig.update_yaxes(fig1.layout.yaxis, row=1, col=1) # 添加第二个子图的Trace和Y轴配置 subfig.add_traces(fig2.data, rows=2, cols=1) subfig.update_yaxes(fig2.layout.yaxis, row=2, col=1) # 统一设置X轴为日期类型 subfig.update_xaxes(type='date') # 调整布局高度避免重叠 subfig.update_layout(height=600) subfig.show()
原理说明
px.timeline生成的图中,Y轴的类别(分组)配置是和当前图的布局绑定的。直接使用add_traces会让子图共享全局Y轴,导致条形被拆分。通过update_yaxes将每个原Timeline图的Y轴配置单独应用到对应子图,就能保证每个子图的分组显示正常,同时保留color='status'带来的颜色区分效果。
替代方案推荐
如果需要更精细化的控制,可以使用plotly.graph_objects手动构建每个时间线条形Trace,逐个添加到子图中。这种方式虽然代码量稍大,但能完全自定义每个Trace的样式和轴配置。
内容的提问来源于stack exchange,提问作者Norwort
相关产品推荐
相关产品推荐

