使用Dash Plotly绘制带有独立颜色图例的条形图。

huangapple go评论52阅读模式
英文:

Plot bar chart with separate color legend - dash Plotly

问题

我尝试使用Dash制作柱状图来绘制特定值,但使用单独的列来映射颜色。使用以下代码,我正在绘制日期作为与下拉菜单条相对应的柱状图。

是否可能保持日期作为x轴,但使用DOW(星期几)作为离散颜色映射?我将附上当前的输出。日期被绘制出来,但存在一些问题。

  1. 下拉菜单中每个日期的字符串格式不是日期时间格式。

  2. 颜色映射与星期几不匹配。

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.

  1. The string formatting for each date in the dropdown isn't in date time

  2. 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)
    

使用Dash Plotly绘制带有独立颜色图例的条形图。

答案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({
           &#39;Type&#39;: [&#39;A&#39;,&#39;B&#39;,&#39;B&#39;,&#39;B&#39;,&#39;C&#39;,&#39;C&#39;,&#39;D&#39;,&#39;E&#39;,&#39;E&#39;,&#39;E&#39;,&#39;E&#39;,&#39;F&#39;,&#39;F&#39;,&#39;F&#39;],
           })
    
    N = 30
    df = pd.concat([df] * N, ignore_index=True)
    
    df[&#39;TIMESTAMP&#39;] = pd.date_range(start=&#39;2022/01/01 07:30&#39;, end=&#39;2022/01/30 08:30&#39;, periods=len(df))
    df[&#39;TIMESTAMP&#39;] = pd.to_datetime(df[&#39;TIMESTAMP&#39;], dayfirst = True).sort_values()
    
    df[&#39;DATE&#39;], df[&#39;TIME&#39;] = zip(*[(d.date(), d.time()) for d in df[&#39;TIMESTAMP&#39;]])
    df[&#39;DATE&#39;] = pd.to_datetime(df[&#39;DATE&#39;],format=&#39;%Y-%m-%d&#39;)
    
    df = df.sort_values(by = &#39;DATE&#39;)
    
    df[&#39;DOW&#39;] = df[&#39;DATE&#39;].dt.weekday
    df = df.sort_values(&#39;DOW&#39;).reset_index(drop=True)
    df[&#39;DOW&#39;] = df[&#39;DATE&#39;].dt.day_name()
    df[&#39;DATE&#39;] = df[&#39;DATE&#39;].astype(str)
    df[&#39;Color&#39;] = df[&#39;DOW&#39;].map(dict(zip(df[&#39;DOW&#39;].unique(),
                        px.colors.qualitative.Plotly[:len(df[&#39;DOW&#39;].unique())])))
    
    Color = df[&#39;Color&#39;].unique()
    Category = df[&#39;DOW&#39;].unique()
    
    Color = df[&#39;Color&#39;].unique()
    Category = df[&#39;DOW&#39;].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(&#39;Day of the week:&#39;, style={&#39;paddingTop&#39;: &#39;2rem&#39;}),
            dcc.Dropdown(
                id=&#39;DATE&#39;,
                options=[
                    {&#39;label&#39;: x, &#39;value&#39;: x} for x in df[&#39;DATE&#39;].unique()
                ],
                value=df[&#39;DATE&#39;].unique(),
                multi=True
            ),
    
        ], className=&quot;four columns&quot;,
        style={&#39;padding&#39;:&#39;2rem&#39;, &#39;margin&#39;:&#39;1rem&#39;} )
    
    ])
    
    app.layout = dbc.Container([
        dbc.Row([
            dbc.Col(html.Div(filter_box, className=&quot;bg-secondary h-100&quot;), width=2),
            dbc.Col([
                dbc.Row([
                    dbc.Col(dcc.Graph(id = &#39;date-bar-chart&#39;), 
                        ),
                ]),
            ], width=5),
        ])
    ], fluid=True)
    
    
    @app.callback(
        Output(&#39;date-bar-chart&#39;, &#39;figure&#39;),
        [Input(&quot;DATE&quot;, &quot;value&quot;),
        ])     
    
    def date_chart(date):
        if date:
            dff = df[df[&#39;DATE&#39;].isin(date)]
            count = dff.groupby([&#39;DATE&#39;,&quot;DOW&quot;])[&#39;DATE&#39;].count().reset_index(name=&#39;counts&#39;)
            data = px.bar(x = count[&#39;DATE&#39;], 
                      y = count[&#39;counts&#39;],
                      color = count[&#39;DOW&#39;],
                      color_discrete_map = cats,
                      )
    
            layout = go.Layout(title = &#39;Date&#39;)
            fig = go.Figure(data = data, layout = layout) 
    
            return fig
        else:
            raise PreventUpdate
    
    
    if __name__ == &#39;__main__&#39;:
        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>



huangapple
  • 本文由 发表于 2023年2月16日 14:00:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/75468388.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定