Dash Plotly:为带回调的柱状图设置固定颜色映射
问题解决方案
一、固定星期几的颜色
要让每个星期几保持固定颜色,核心是提前为所有星期几分配固定的颜色映射,而非每次过滤后动态生成。这样无论移除哪些星期几,剩余项都会沿用预定义的颜色。
修改步骤:
- 定义全局的星期几-颜色映射字典,确保每个星期几对应固定颜色:
# 预定义星期几的固定颜色映射 dow_color_map = { 'Monday': px.colors.qualitative.Plotly[0], 'Tuesday': px.colors.qualitative.Plotly[1], 'Wednesday': px.colors.qualitative.Plotly[2], 'Thursday': px.colors.qualitative.Plotly[3], 'Friday': px.colors.qualitative.Plotly[4], 'Saturday': px.colors.qualitative.Plotly[5], 'Sunday': px.colors.qualitative.Plotly[6] }
- 修改回调函数,直接使用全局映射,不再动态生成颜色:
def date_chart(dow): dff = df[df['DOW'].isin(dow)] count = dff['DOW'].value_counts().reindex(dow) # 按下拉选中的顺序排序 data = px.bar( x=count.index, y=count.values, color=count.index, color_discrete_map=dow_color_map # 使用预定义的固定颜色映射 ) layout = go.Layout(title='星期几计数') fig = go.Figure(data=data, layout=layout) return fig
这样,无论过滤掉哪个星期几,剩余项的颜色都和初始状态一致,不会随操作变化。
二、保留星期几下拉选项,绘制DATE计数并沿用星期几颜色
如果要保留星期几的下拉筛选,但图表显示DATE的计数,且每个日期的颜色由它所属的星期几决定(沿用固定颜色序列),可按以下方式修改:
核心逻辑:
- 下拉筛选星期几后,筛选出对应日期的数据
- 按
DATE统计计数 - 每个日期的颜色由其对应的
DOW(星期几)匹配预定义的颜色映射
修改后的回调函数:
def date_chart(dow): dff = df[df['DOW'].isin(dow)] # 按DATE统计计数,并保留每个DATE对应的DOW信息 date_count = dff.groupby(['DATE', 'DOW']).size().reset_index(name='Count') data = px.bar( date_count, x='DATE', y='Count', color='DOW', # 按星期几分配颜色 color_discrete_map=dow_color_map, # 沿用固定颜色映射 labels={'DATE': '日期', 'Count': '计数', 'DOW': '星期几'} ) layout = go.Layout(title='日期计数(按星期几配色)') fig = go.Figure(data=data, layout=layout) # 格式化日期显示,避免重叠 fig.update_layout(xaxis_tickformat='%Y-%m-%d') return fig
完整修改后的代码
from dash import dcc, html import dash_bootstrap_components as dbc import dash from dash.dependencies import Input, Output import plotly.graph_objs as go import plotly.express as px import pandas as pd df = pd.DataFrame({ 'Type': ['A','B','B','B','C','C','D','E','E','E','E','F','F','F'], }) N = 30 df = pd.concat([df] * N, ignore_index=True) df['TIMESTAMP'] = pd.date_range(start='2022/01/01 07:30', end='2022/01/30 08:30', periods=len(df)) df['TIMESTAMP'] = pd.to_datetime(df['TIMESTAMP'], dayfirst=True).sort_values() df['TIMESTAMP'] = df['TIMESTAMP'].dt.floor('1min') df['DATE'], df['TIME'] = zip(*[(d.date(), d.time()) for d in df['TIMESTAMP']]) df['DATE'] = pd.to_datetime(df['DATE']) df['YEAR'] = df['DATE'].dt.year df = df.sort_values(by='DATE') df['DOW'] = df['DATE'].dt.day_name() # 预定义星期几的固定颜色映射 dow_color_map = { 'Monday': px.colors.qualitative.Plotly[0], 'Tuesday': px.colors.qualitative.Plotly[1], 'Wednesday': px.colors.qualitative.Plotly[2], 'Thursday': px.colors.qualitative.Plotly[3], 'Friday': px.colors.qualitative.Plotly[4], 'Saturday': px.colors.qualitative.Plotly[5], 'Sunday': px.colors.qualitative.Plotly[6] } external_stylesheets = [dbc.themes.SPACELAB, dbc.icons.BOOTSTRAP] app = dash.Dash(__name__, external_stylesheets=external_stylesheets) filter_box = html.Div(children=[ html.Div(children=[ html.Label('Day of the week:', style={'paddingTop': '2rem'}), dcc.Dropdown( id='DOW', options=[{'label': x, 'value': x} for x in df['DOW'].unique()], value=['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday','Sunday'], multi=True ), ], className="four columns", style={'padding':'2rem', 'margin':'1rem'} ) ]) app.layout = dbc.Container([ dbc.Row([ dbc.Col(html.Div(filter_box, className="bg-secondary h-100"), width=2), dbc.Col([ dbc.Row([dbc.Col(dcc.Graph(id='date-bar-chart'), style={"padding-bottom": "10px"})]) ], width=5), dbc.Col([], width=5), ]) ], fluid=True) @app.callback( Output('date-bar-chart', 'figure'), [Input("DOW", "value")] ) # 选择下面的函数实现对应需求: # 需求1:显示星期几计数,颜色固定 def date_chart(dow): dff = df[df['DOW'].isin(dow)] count = dff['DOW'].value_counts().reindex(dow) # 按选中顺序排序 data = px.bar( x=count.index, y=count.values, color=count.index, color_discrete_map=dow_color_map ) layout = go.Layout(title='星期几计数') fig = go.Figure(data=data, layout=layout) return fig # 需求2:显示日期计数,颜色对应星期几 # def date_chart(dow): # dff = df[df['DOW'].isin(dow)] # date_count = dff.groupby(['DATE', 'DOW']).size().reset_index(name='Count') # data = px.bar( # date_count, # x='DATE', # y='Count', # color='DOW', # color_discrete_map=dow_color_map, # labels={'DATE': '日期', 'Count': '计数', 'DOW': '星期几'} # ) # layout = go.Layout(title='日期计数(按星期几配色)') # fig = go.Figure(data=data, layout=layout) # fig.update_layout(xaxis_tickformat='%Y-%m-%d') # return fig if __name__ == '__main__': app.run_server(debug=True, port=8051)
使用说明:
- 要实现固定颜色的星期几计数图,保留第一个
date_chart函数,注释第二个; - 要实现日期计数+星期几配色,注释第一个函数,启用第二个。
内容的提问来源于stack exchange,提问作者Chopin
相关产品推荐
相关产品推荐

