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

Dash Plotly:为带回调的柱状图设置固定颜色映射

问题解决方案

一、固定星期几的颜色

要让每个星期几保持固定颜色,核心是提前为所有星期几分配固定的颜色映射,而非每次过滤后动态生成。这样无论移除哪些星期几,剩余项都会沿用预定义的颜色。

修改步骤:

  1. 定义全局的星期几-颜色映射字典,确保每个星期几对应固定颜色:
# 预定义星期几的固定颜色映射
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]
}
  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

这样,无论过滤掉哪个星期几,剩余项的颜色都和初始状态一致,不会随操作变化。


二、保留星期几下拉选项,绘制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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 23:40:50