英文:
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>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论