在Dash仪表盘中如何为Plotly多轨迹设置不同子类别颜色?
解决Dash仪表盘中子类别轨迹颜色一致的问题
我使用包含Date、Category、Sub-category、Expenditure四列的数据集,想要创建Dash仪表盘展示所选类别及其子类别随日期变化的支出情况。当前通过以下代码生成图表,但所有轨迹颜色一致,请问如何为不同子类别对应的轨迹设置不同颜色?
cats = df.Category.unique() tags={key: [] for key in cats} for cat in cats: tags[cat] = df[df.Category==cat].Subcat.unique() @callback(Output(graph,"figure"),Input(dropdown,"value")) def update_bar_chart(cat): mask = df['Category']==cat fig = px.bar(df[mask].groupby(df.Date)['Expense amount'].sum()) for i, tag in enumerate(tags[cat]): mask = df['Subcat']==tag fig.add_traces(list(px.scatter(df[mask].groupby(df.Date)['Expense amount'].sum()).select_traces())) return fig
问题原因
每次独立调用px.scatter()时,Plotly会默认使用颜色序列的第一个颜色,导致所有子类别轨迹颜色重复。
解决方案1:手动指定每个子类别颜色
通过预定义颜色序列,在循环添加轨迹时为每个子类别分配不同颜色:
import plotly.colors as pc cats = df.Category.unique() tags={key: [] for key in cats} for cat in cats: tags[cat] = df[df.Category==cat].Subcat.unique() # 选用Plotly内置定性颜色序列,也可自定义颜色列表 color_sequence = pc.qualitative.Plotly @callback(Output(graph,"figure"),Input(dropdown,"value")) def update_bar_chart(cat): mask = df['Category']==cat # 重置索引让Plotly正确识别轴字段 total_df = df[mask].groupby(df.Date)['Expense amount'].sum().reset_index(name='Total') fig = px.bar(total_df, x='Date', y='Total') for i, tag in enumerate(tags[cat]): mask_sub = df['Subcat']==tag sub_df = df[mask_sub].groupby(df.Date)['Expense amount'].sum().reset_index(name='Expense amount') scatter_fig = px.scatter(sub_df, x='Date', y='Expense amount') # 给当前子类别轨迹分配颜色 trace = scatter_fig.select_traces()[0] trace.marker.color = color_sequence[i % len(color_sequence)] # 设置轨迹名称为子类别名,方便图例识别 trace.name = tag fig.add_trace(trace) fig.update_layout(legend_title_text="子类别") return fig
解决方案2:按子类别分组自动分配颜色(更简洁)
重构代码,先按Date和Subcat分组聚合数据,直接用px.scatter()按子类别分组,Plotly会自动为每个子类别分配不同颜色:
cats = df.Category.unique() tags={key: [] for key in cats} for cat in cats: tags[cat] = df[df.Category==cat].Subcat.unique() @callback(Output(graph,"figure"),Input(dropdown,"value")) def update_bar_chart(cat): mask = df['Category']==cat # 生成总支出柱状图 total_df = df[mask].groupby('Date')['Expense amount'].sum().reset_index(name='Total') fig = px.bar(total_df, x='Date', y='Total', title=f"{cat} 类别总支出") # 按日期+子类别聚合支出数据 subcat_df = df[mask].groupby(['Date', 'Subcat'])['Expense amount'].sum().reset_index() # 通过color参数指定按子类别区分颜色 scatter_fig = px.scatter(subcat_df, x='Date', y='Expense amount', color='Subcat') # 将散点轨迹添加到柱状图中 fig.add_traces(scatter_fig.select_traces()) # 优化布局细节 fig.update_layout( legend_title_text="子类别", xaxis_title="日期", yaxis_title="支出金额" ) return fig
关键说明
- 两种方法都需要用
reset_index()将聚合后的Series转换为DataFrame,确保Plotly能正确识别轴字段。 - 第二种方法更易维护,Plotly会自动处理颜色映射、图例标签等细节,减少冗余代码。
内容的提问来源于stack exchange,提问作者boltz
相关产品推荐
相关产品推荐

