英文:
Plot bar chart with separate color legend - dash Plotly
问题
我尝试使用Dash制作柱状图来绘制特定值,但使用单独的列来映射颜色。使用以下代码,我正在绘制日期作为与下拉菜单条相对应的柱状图。
是否可能保持日期作为x轴,但使用DOW(星期几)作为离散颜色映射?我将附上当前的输出。日期被绘制出来,但存在一些问题。
- 
下拉菜单中每个日期的字符串格式不是日期时间格式。
 - 
颜色映射与星期几不匹配。
 
import dash
from dash import dcc
from dash import html
from dash.dependencies import Input, Output
import dash_bootstrap_components as dbc
import plotly.express as px
import plotly.graph_objs as go
import pandas as pd
from datetime import datetime as dt
# 你的数据处理部分...
# 创建Dash应用
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
# 定义布局
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'),
                    ),
            ]),
        ], width=5),
    ])
], fluid=True)
# 回调函数
@app.callback(
    Output('date-bar-chart', 'figure'),
    [Input("DATE", "value"),
    ])     
def date_chart(date):
    # 你的绘图部分...
if __name__ == '__main__':
    app.run_server(debug=True, port=8051)
你的问题主要是关于日期的格式和颜色映射,你需要对日期格式进行调整,并将DOW用作颜色映射。如有需要,你可以在回调函数中修改数据和布局以满足你的需求。
英文:
I'm trying to plot certain values using dash as a bar chart but use a separate column to map the colors. Using below, I'm plotting dates as a bar-chart that corresponds to a drop down bar.
Is it possible to keep the dates as the x-axis but use DOW (day of the week) as a discrete color map? I'll attach the current output below. The dates get plotted but there are a few issues.
- 
The string formatting for each date in the dropdown isn't in date time
 - 
The color map isn't sequenced to the day of the week
import dash from dash import dcc from dash import html from dash.dependencies import Input, Output import dash_bootstrap_components as dbc import plotly.express as px import plotly.graph_objs as go import pandas as pd from datetime import datetime as dt 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['DATE'], df['TIME'] = zip(*[(d.date(), d.time()) for d in df['TIMESTAMP']]) df['DATE'] = pd.to_datetime(df['DATE']) df = df.sort_values(by = 'DATE') df['DOW'] = df['DATE'].dt.weekday df = df.sort_values('DOW').reset_index(drop=True) df['DOW'] = df['DATE'].dt.day_name() 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='DATE', options=[ {'label': x, 'value': x} for x in df['DATE'].unique() ], value=df['DATE'].unique(), 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'), ), ]), ], width=5), ]) ], fluid=True) @app.callback( Output('date-bar-chart', 'figure'), [Input("DATE", "value"), ]) def date_chart(date): dff = df[df['DATE'].isin(date)] count = dff['DATE'].value_counts() data = px.bar(x = count.index, y = count.values, #color = dff['DOW'], ) layout = go.Layout(title = 'Date') fig = go.Figure(data = data, layout = layout) return fig if __name__ == '__main__': app.run_server(debug=True, port = 8051) 
答案1
得分: 2
不确定为什么您想要将DATE用作下拉菜单,但我认为您应该将其更改为字符串,然后将其传递给dcc.Dropdown。用以前的方式添加color_discrete_map,我认为您可以将代码修改如下:
import dash
from dash import dcc
from dash import html
from dash.dependencies import Input, Output
import dash_bootstrap_components as dbc
import plotly.express as px
import plotly.graph_objs as go
import pandas as pd
from datetime import datetime as dt
from dash.exceptions import PreventUpdate
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['DATE'], df['TIME'] = zip(*[(d.date(), d.time()) for d in df['TIMESTAMP']])
df['DATE'] = pd.to_datetime(df['DATE'], format='%Y-%m-%d')
df = df.sort values(by='DATE')
df['DOW'] = df['DATE'].dt.weekday
df = df.sort_values('DOW').reset_index(drop=True)
df['DOW'] = df['DATE'].dt.day_name()
df['DATE'] = df['DATE'].astype(str)
df['Color'] = df['DOW'].map(dict(zip(df['DOW'].unique(), px.colors.qualitative.Plotly[:len(df['DOW'].unique())]))
Color = df['Color'].unique()
Category = df['DOW'].unique()
Color = df['Color'].unique()
Category = df['DOW'].unique()
cats = dict(zip(Category, Color))
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='DATE',
            options=[
                {'label': x, 'value': x} for x in df['DATE'].unique()
            ],
            value=df['DATE'].unique(),
            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'),
                ),
            ]),
        ], width=5),
    ])
], fluid=True)
@app.callback(
    Output('date-bar-chart', 'figure'),
    [Input("DATE", "value"),
     ])
def date_chart(date):
    if date:
        dff = df[df['DATE'].isin(date)]
        count = dff.groupby(['DATE', "DOW"])['DATE'].count().reset_index(name='counts')
        data = px.bar(x=count['DATE'],
                      y=count['counts'],
                      color=count['DOW'],
                      color_discrete_map=cats,
                      )
        layout = go.Layout(title='Date')
        fig = go.Figure(data=data, layout=layout)
        return fig
    else:
        raise PreventUpdate
if __name__ == '__main__':
    app.run_server(debug=False, port=8051)
我在`callback`中使用了`groupby`来返回新的数据框,然后使用它来制作图表。希望这有所帮助。
<details>
<summary>英文:</summary>
Not sure why do you want to use `DATE` as Dropdown but I think you should change it to string and then pass it to `dcc.Dropdown`. Used the previous way to add `color_discrete_map` I think you can revise your code as below:
    import dash
    from dash import dcc
    from dash import html
    from dash.dependencies import Input, Output
    import dash_bootstrap_components as dbc
    import plotly.express as px
    import plotly.graph_objs as go
    import pandas as pd
    from datetime import datetime as dt
    from dash.exceptions import PreventUpdate
    
    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['DATE'], df['TIME'] = zip(*[(d.date(), d.time()) for d in df['TIMESTAMP']])
    df['DATE'] = pd.to_datetime(df['DATE'],format='%Y-%m-%d')
    
    df = df.sort_values(by = 'DATE')
    
    df['DOW'] = df['DATE'].dt.weekday
    df = df.sort_values('DOW').reset_index(drop=True)
    df['DOW'] = df['DATE'].dt.day_name()
    df['DATE'] = df['DATE'].astype(str)
    df['Color'] = df['DOW'].map(dict(zip(df['DOW'].unique(),
                        px.colors.qualitative.Plotly[:len(df['DOW'].unique())])))
    
    Color = df['Color'].unique()
    Category = df['DOW'].unique()
    
    Color = df['Color'].unique()
    Category = df['DOW'].unique()
    
    cats = dict(zip(Category,Color)) 
    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='DATE',
                options=[
                    {'label': x, 'value': x} for x in df['DATE'].unique()
                ],
                value=df['DATE'].unique(),
                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'), 
                        ),
                ]),
            ], width=5),
        ])
    ], fluid=True)
    
    
    @app.callback(
        Output('date-bar-chart', 'figure'),
        [Input("DATE", "value"),
        ])     
    
    def date_chart(date):
        if date:
            dff = df[df['DATE'].isin(date)]
            count = dff.groupby(['DATE',"DOW"])['DATE'].count().reset_index(name='counts')
            data = px.bar(x = count['DATE'], 
                      y = count['counts'],
                      color = count['DOW'],
                      color_discrete_map = cats,
                      )
    
            layout = go.Layout(title = 'Date')
            fig = go.Figure(data = data, layout = layout) 
    
            return fig
        else:
            raise PreventUpdate
    
    
    if __name__ == '__main__':
        app.run_server(debug=False, port = 8051)
I used groupby in `callback` to return new dataframe and then use it to make graph. Hope this help.
[![enter image description here][1]][1]
  [1]: https://i.stack.imgur.com/fylgg.png
</details>
				通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。



评论