Plotly:如何制作多索引下拉选项? [英] Plotly: How to make a multiple index dropdown option?

查看:58
本文介绍了Plotly:如何制作多索引下拉选项?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下不同时间范围内具有相同索引号的数据

 Time CallOI PutOI CallLTP PutLTP29500 下午 3:30 502725 554775 343.70 85.5029500 下午 3:15 568725 629700 357.15 81.7029500 2:59 下午 719350 689850 337.85 95.4529500 2:45 下午 786975 641575 360.00 108.3529500 下午 2:30 823500 626875 336.50 127.8029500 2:15 下午 812450 631800 308.55 143.0029500 下午 2:00 974700 617750 389.80 120.0029500 1:45 下午 1072675 547100 262.55 186.8529500 下午 1:30 1272300 469600 206.85 232.0029600 下午 3:30 502725 554775 343.70 85.5029600 下午 3:15 568725 629700 357.15 81.7029600 2:59 下午 719350 689850 337.85 95.4529600 2:45 下午 786975 641575 360.00 108.3529600 下午 2:30 823500 626875 336.50 127.8029600 2:15 下午 812450 631800 308.55 143.0029600 2:00 PM 974700 617750 389.80 120.0029600 1:45 下午 1072675 547100 262.55 186.8529600 下午 1:30 1272300 469600 206.85 232.0029700 下午 3:30 502725 554775 343.70 85.5029700 下午 3:15 568725 629700 357.15 81.7029700 2:59 下午 719350 689850 337.85 95.4529700 2:45 下午 786975 641575 360.00 108.3529700 下午 2:30 823500 626875 336.50 127.8029700 2:15 下午 812450 631800 308.55 143.0029700 下午 2:00 974700 617750 389.80 120.0029700 1:45 下午 1072675 547100 262.55 186.8529700 下午 1:30 1272300 469600 206.85 232.00

使用下面的代码我制作了图表:

subfig = make_subplots(specs=[[{secondary_y": True}]])# 用 px.line 创建两个独立的图形,每个图形都包含来自多列的数据fig = px.line(df,x='Time', y='Call OI')fig2 = px.line(df,x='Time', y='Call LTP')fig2.update_traces(yaxis=y2")subfig.add_traces(fig.data + fig2.data)subfig.layout.xaxis.title=时间"subfig.layout.yaxis.title=OI";subfig.layout.yaxis2.type=日志";subfig.layout.yaxis2.title=价格"# 重新着色是必要的,否则来自 fig 和 fig2 的行将共享每种颜色# 例如线性-,对数- = 蓝色;Linear+, Log+ = red...我们不想要这个subfig.for_each_trace(lambda t: t.update(line=dict(color=t.marker.color)))subfig.show()

我想要选择不同索引的下拉菜单,并且图表数据会相应更改.例如,如果我从下拉列表 29600 中选择它只显示该索引号的数据,并且还有一种方法可以从左到右翻转 x 轴(时间).提前感谢您提供任何解决方案

解决方案

Edit 2 - 使用链接数据集更新建议

为了使用

编辑 2 的完整代码

导入集合导入破折号将熊猫导入为 pdfrom dash.dependencies import 输出,输入从 dash.exceptions 导入防止更新从 jupyter_dash 导入 JupyterDash将 dash_core_components 导入为 dcc将 dash_html_components 导入为 html从 dash.dependencies 导入输入、输出、状态、ClientsideFunction将 dash_bootstrap_components 导入为 dbc将 dash_core_components 导入为 dcc将 dash_html_components 导入为 html从 plotly.subplots 导入 make_subplots导入 plotly.graph_objects as godfi = pd.read_clipboard(sep=',')df = dfi.copy()idx = list(df['执行价格'].unique())app = JupyterDash()app.layout = html.Div([dcc.Store(id='memory-output'),dcc.Dropdown(id='memory-countries', options=[{'value': x, 'label': x} for x in idx], multi=False, value=idx[0]),dcc.Dropdown(id='memory-field', options=[{'值':'默认','标签':'默认'},{'value': 'reverse', 'label': 'reverse'},], 值='默认'),html.div([dcc.Graph(id='memory-graph'),])])@app.callback(Output('memory-output', 'data'),[输入('内存国家','值')])def filter_countries(idx_selected):如果不是 idx_selected:# 返回初始加载/未选择国家/地区的所有行.返回(idx_selected)返回(idx_selected)@app.callback(Output('memory-graph', 'figure'),[输入('内存输出','数据'),输入('内存字段','值')])def on_data_set_graph(数据,字段):# 打印(数据)#全局dff如果数据为无:提高预防更新#图形设置fig = make_subplots(specs=[[{secondary_y": True}]])dff = df[df['执行价格']==数据]fig.add_trace(go.Scatter(x=dff.Time, y = dff['Call OI'], name = 'Call'), secondary_y=True)fig.add_trace(go.Scatter(x=dff.Time, y = dff['Call LTP'], name = 'Put'), secondary_y=False)# 翻转轴如果字段 != '默认':fig.update_layout(xaxis = dict(autorange='reversed'))返回(图)app.run_server(mode='inline', port = 8072, dev_tools_ui=True,dev_tools_hot_reload =True,threaded=True,debug=True)

编辑 - 更新了轴翻转的建议

我的最新建议基于

这是完整的代码:

导入集合导入破折号将熊猫导入为 pdfrom dash.dependencies import 输出,输入从 dash.exceptions 导入防止更新从 jupyter_dash 导入 JupyterDash将 dash_core_components 导入为 dcc将 dash_html_components 导入为 html从 dash.dependencies 导入输入、输出、状态、ClientsideFunction将 dash_bootstrap_components 导入为 dbc将 dash_core_components 导入为 dcc将 dash_html_components 导入为 html从 plotly.subplots 导入 make_subplots导入 plotly.graph_objects as godf = pd.DataFrame({'Time': {(29500, '3:30'): 'PM',(29500, '3:15'): '下午',(29500, '2:59'): '下午',(29500, '2:45'): '下午',(29500, '2:30'): '下午',(29500, '2:15'): '下午',(29500, '2:00'): '下午',(29500, '1:45'): '下午',(29500, '1:30'): '下午',(29600, '3:30'): '下午',(29600, '3:15'): '下午',(29600, '2:59'): '下午',(29600, '2:45'): '下午',(29600, '2:30'): '下午',(29600, '2:15'): '下午',(29600, '2:00'): '下午',(29600, '1:45'): '下午',(29600, '1:30'): '下午',(29700, '3:30'): '下午',(29700, '3:15'): '下午',(29700, '2:59'): '下午',(29700, '2:45'): '下午',(29700, '2:30'): '下午',(29700, '2:15'): '下午',(29700, '2:00'): '下午',(29700, '1:45'): '下午',(29700, '1:30'): '下午'},'CallOI': {(29500, '3:30'): 502725,(29500, '3:15'): 568725,(29500, '2:59'): 719350,(29500, '2:45'): 786975,(29500, '2:30'): 823500,(29500, '2:15'): 812450,(29500, '2:00'): 974700,(29500, '1:45'): 1072675,(29500, '1:30'): 1272300,(29600, '3:30'): 502725,(29600, '3:15'): 568725,(29600, '2:59'): 719350,(29600, '2:45'): 786975,(29600, '2:30'): 823500,(29600, '2:15'): 812450,(29600, '2:00'): 974700,(29600, '1:45'): 1000000,(29600, '1:30'): 1272300,(29700, '3:30'): 502725,(29700, '3:15'): 568725,(29700, '2:59'): 719350,(29700, '2:45'): 786975,(29700, '2:30'): 823500,(29700, '2:15'): 812450,(29700, '2:00'): 974700,(29700, '1:45'): 1172675,(29700, '1:30'): 1272300},'PutOI': {(29500, '3:30'): 554775,(29500, '3:15'): 629700,(29500, '2:59'): 689850,(29500, '2:45'): 641575,(29500, '2:30'): 626875,(29500, '2:15'): 631800,(29500, '2:00'): 617750,(29500, '1:45'): 547100,(29500, '1:30'): 469600,(29600, '3:30'): 554775,(29600, '3:15'): 629700,(29600, '2:59'): 689850,(29600, '2:45'): 641575,(29600, '2:30'): 626875,(29600, '2:15'): 631800,(29600, '2:00'): 617750,(29600, '1:45'): 547100,(29600, '1:30'): 469600,(29700, '3:30'): 554775,(29700, '3:15'): 629700,(29700, '2:59'): 689850,(29700, '2:45'): 641575,(29700, '2:30'): 626875,(29700, '2:15'): 631800,(29700, '2:00'): 617750,(29700, '1:45'): 547100,(29700, '1:30'): 469600},'CallLTP': {(29500, '3:30'): 343.7,(29500, '3:15'): 357.15,(29500, '2:59'): 337.85,(29500, '2:45'): 360.0,(29500, '2:30'): 336.5,(29500, '2:15'): 308.55,(29500, '2:00'): 389.8,(29500, '1:45'): 262.55,(29500, '1:30'): 206.85,(29600, '3:30'): 343.7,(29600, '3:15'): 357.15,(29600, '2:59'): 337.85,(29600, '2:45'): 360.0,(29600, '2:30'): 336.5,(29600, '2:15'): 308.55,(29600, '2:00'): 389.8,(29600, '1:45'): 262.55,(29600, '1:30'): 206.85,(29700, '3:30'): 343.7,(29700, '3:15'): 357.15,(29700, '2:59'): 337.85,(29700, '2:45'): 360.0,(29700, '2:30'): 336.5,(29700, '2:15'): 308.55,(29700, '2:00'): 389.8,(29700, '1:45'): 262.55,(29700, '1:30'): 206.85},'PutLTP': {(29500, '3:30'): 85.5,(29500, '3:15'): 81.7,(29500, '2:59'): 95.45,(29500, '2:45'): 108.35,(29500, '2:30'): 127.8,(29500, '2:15'): 143.0,(29500, '2:00'): 120.0,(29500, '1:45'): 186.85,(29500, '1:30'): 232.0,(29600, '3:30'): 85.5,(29600, '3:15'): 81.7,(29600, '2:59'): 95.45,(29600, '2:45'): 108.35,(29600, '2:30'): 127.8,(29600, '2:15'): 143.0,(29600, '2:00'): 120.0,(29600, '1:45'): 186.85,(29600, '1:30'): 232.0,(29700, '3:30'): 85.5,(29700, '3:15'): 81.7,(29700, '2:59'): 95.45,(29700, '2:45'): 108.35,(29700, '2:30'): 127.8,(29700, '2:15'): 143.0,(29700, '2:00'): 120.0,(29700, '1:45'): 186.85,(29700, '1:30'): 232.0}})df = df.reset_index()idx = list(df['level_0'].unique())app = JupyterDash()app.layout = html.Div([dcc.Store(id='memory-output'),dcc.Dropdown(id='memory-countries', options=[{'value': x, 'label': x} for x in idx], multi=False, value=idx[0]),dcc.Dropdown(id='memory-field', options=[{'值':'默认','标签':'默认'},{'value': 'reverse', 'label': 'reverse'},],值='默认'),html.div([dcc.Graph(id='memory-graph'),])])@app.callback(Output('memory-output', 'data'),[输入('内存国家','值')])def filter_countries(idx_selected):如果不是 idx_selected:# 返回初始加载/未选择国家/地区的所有行.返回(idx_selected)返回(idx_selected)@app.callback(Output('memory-graph', 'figure'),[输入('内存输出','数据'),输入('内存字段','值')])def on_data_set_graph(数据,字段):# 打印(数据)如果数据为无:提高预防更新#图形设置fig = make_subplots(specs=[[{secondary_y": True}]])dff = df[df['level_0']==数据]fig.add_trace(go.Scatter(x=dff.level_1, y = dff.CallOI, name = 'Call'), secondary_y=True)fig.add_trace(go.Scatter(x=dff.level_1, y = dff.PutOI, name = 'Put'), secondary_y=False)# 翻转轴如果字段 != '默认':fig.update_layout(xaxis = dict(autorange='reversed'))返回(图)app.run_server(mode='inline', port = 8072, dev_tools_ui=True,dev_tools_hot_reload =True,threaded=True,debug=True)


建议 1


您尚未指定如何使用您的数字.但假设它在 JupyterLab 中,我强烈推荐使用 JupyterDash.我发现这比 r-beginners 在

完整代码

将 numpy 导入为 np将熊猫导入为 pd导入 plotly.express 作为 px导入 plotly.graph_objects as go从 jupyter_dash 导入 JupyterDash将 dash_core_components 导入为 dcc将 dash_html_components 导入为 html从 dash.dependencies 导入输入,输出从 plotly.subplots 导入 make_subplots从 dash.dependencies 导入输入、输出、状态# 数据df = pd.DataFrame({'Time': {(29500, '3:30'): 'PM',(29500, '3:15'): '下午',(29500, '2:59'): '下午',(29500, '2:45'): '下午',(29500, '2:30'): '下午',(29500, '2:15'): '下午',(29500, '2:00'): '下午',(29500, '1:45'): '下午',(29500, '1:30'): '下午',(29600, '3:30'): '下午',(29600, '3:15'): '下午',(29600, '2:59'): '下午',(29600, '2:45'): '下午',(29600, '2:30'): '下午',(29600, '2:15'): '下午',(29600, '2:00'): '下午',(29600, '1:45'): '下午',(29600, '1:30'): '下午',(29700, '3:30'): '下午',(29700, '3:15'): '下午',(29700, '2:59'): '下午',(29700, '2:45'): '下午',(29700, '2:30'): '下午',(29700, '2:15'): '下午',(29700, '2:00'): '下午',(29700, '1:45'): '下午',(29700, '1:30'): '下午'},'CallOI': {(29500, '3:30'): 502725,(29500, '3:15'): 568725,(29500, '2:59'): 719350,(29500, '2:45'): 786975,(29500, '2:30'): 823500,(29500, '2:15'): 812450,(29500, '2:00'): 974700,(29500, '1:45'): 1072675,(29500, '1:30'): 1272300,(29600, '3:30'): 502725,(29600, '3:15'): 568725,(29600, '2:59'): 719350,(29600, '2:45'): 786975,(29600, '2:30'): 823500,(29600, '2:15'): 812450,(29600, '2:00'): 974700,(29600, '1:45'): 1000000,(29600, '1:30'): 1272300,(29700, '3:30'): 502725,(29700, '3:15'): 568725,(29700, '2:59'): 719350,(29700, '2:45'): 786975,(29700, '2:30'): 823500,(29700, '2:15'): 812450,(29700, '2:00'): 974700,(29700, '1:45'): 1172675,(29700, '1:30'): 1272300},'PutOI': {(29500, '3:30'): 554775,(29500, '3:15'): 629700,(29500, '2:59'): 689850,(29500, '2:45'): 641575,(29500, '2:30'): 626875,(29500, '2:15'): 631800,(29500, '2:00'): 617750,(29500, '1:45'): 547100,(29500, '1:30'): 469600,(29600, '3:30'): 554775,(29600, '3:15'): 629700,(29600, '2:59'): 689850,(29600, '2:45'): 641575,(29600, '2:30'): 626875,(29600, '2:15'): 631800,(29600, '2:00'): 617750,(29600, '1:45'): 547100,(29600, '1:30'): 469600,(29700, '3:30'): 554775,(29700, '3:15'): 629700,(29700, '2:59'): 689850,(29700, '2:45'): 641575,(29700, '2:30'): 626875,(29700, '2:15'): 631800,(29700, '2:00'): 617750,(29700, '1:45'): 547100,(29700, '1:30'): 469600},'CallLTP': {(29500, '3:30'): 343.7,(29500, '3:15'): 357.15,(29500, '2:59'): 337.85,(29500, '2:45'): 360.0,(29500, '2:30'): 336.5,(29500, '2:15'): 308.55,(29500, '2:00'): 389.8,(29500, '1:45'): 262.55,(29500, '1:30'): 206.85,(29600, '3:30'): 343.7,(29600, '3:15'): 357.15,(29600, '2:59'): 337.85,(29600, '2:45'): 360.0,(29600, '2:30'): 336.5,(29600, '2:15'): 308.55,(29600, '2:00'): 389.8,(29600, '1:45'): 262.55,(29600, '1:30'): 206.85,(29700, '3:30'): 343.7,(29700, '3:15'): 357.15,(29700, '2:59'): 337.85,(29700, '2:45'): 360.0,(29700, '2:30'): 336.5,(29700, '2:15'): 308.55,(29700, '2:00'): 389.8,(29700, '1:45'): 262.55,(29700, '1:30'): 206.85},'PutLTP': {(29500, '3:30'): 85.5,(29500, '3:15'): 81.7,(29500, '2:59'): 95.45,(29500, '2:45'): 108.35,(29500, '2:30'): 127.8,(29500, '2:15'): 143.0,(29500, '2:00'): 120.0,(29500, '1:45'): 186.85,(29500, '1:30'): 232.0,(29600, '3:30'): 85.5,(29600, '3:15'): 81.7,(29600, '2:59'): 95.45,(29600, '2:45'): 108.35,(29600, '2:30'): 127.8,(29600, '2:15'): 143.0,(29600, '2:00'): 120.0,(29600, '1:45'): 186.85,(29600, '1:30'): 232.0,(29700, '3:30'): 85.5,(29700, '3:15'): 81.7,(29700, '2:59'): 95.45,(29700, '2:45'): 108.35,(29700, '2:30'): 127.8,(29700, '2:15'): 143.0,(29700, '2:00'): 120.0,(29700, '1:45'): 186.85,(29700, '1:30'): 232.0}})df = df.reset_index()external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']app = JupyterDash(__name__, external_stylesheets=external_stylesheets)# 下拉选项标准 = 列表(df['level_0'].unique())options = [{'label': i, 'value': i} for i in conditions]选项.append# 应用布局app.layout = html.Div([html.div([html.div([dcc.Dropdown(id='linedropdown',选项=选项,value=options[0]['value'],),],),],className='row'),html.div([html.div([dcc.Graph(id='linechart'),],),],),])@app.callback([输出('折线图','图形')],[输入('linedropdown','值')])def update_graph(linedropdown):# 使用 linedropdown 选择dff = df[df['level_0']==linedropdown]# 创建带有辅助 y 轴的图形fig = make_subplots(specs=[[{secondary_y": True}]])# 添加跟踪 1fig.add_trace(go.Scatter(x=dff['level_1'], y=dff['CallOI'], name="Call OI"),secondary_y=真,)# 添加跟踪 2fig.add_trace(go.Scatter(x=dff['level_1'], y=dff['CallLTP'], name="Call LTP"),secondary_y=假,)fig.update_layout(title = 'Index:' + str(linedropdown))返回([图])# 运行应用程序并在笔记本中内联显示结果app.run_server(mode='inline', port = 8040, dev_tools_ui=True, debug=True,dev_tools_hot_reload =真,线程=真)

I have data with same index number for different timeframe as below

           Time CallOI  PutOI   CallLTP PutLTP  
29500   3:30 PM 502725  554775  343.70  85.50   
29500   3:15 PM 568725  629700  357.15  81.70   
29500   2:59 PM 719350  689850  337.85  95.45   
29500   2:45 PM 786975  641575  360.00  108.35  
29500   2:30 PM 823500  626875  336.50  127.80  
29500   2:15 PM 812450  631800  308.55  143.00  
29500   2:00 PM 974700  617750  389.80  120.00  
29500   1:45 PM 1072675 547100  262.55  186.85  
29500   1:30 PM 1272300 469600  206.85  232.00  
29600   3:30 PM 502725  554775  343.70  85.50   
29600   3:15 PM 568725  629700  357.15  81.70   
29600   2:59 PM 719350  689850  337.85  95.45   
29600   2:45 PM 786975  641575  360.00  108.35  
29600   2:30 PM 823500  626875  336.50  127.80  
29600   2:15 PM 812450  631800  308.55  143.00  
29600   2:00 PM 974700  617750  389.80  120.00  
29600   1:45 PM 1072675 547100  262.55  186.85  
29600   1:30 PM 1272300 469600  206.85  232.00  
29700   3:30 PM 502725  554775  343.70  85.50   
29700   3:15 PM 568725  629700  357.15  81.70   
29700   2:59 PM 719350  689850  337.85  95.45   
29700   2:45 PM 786975  641575  360.00  108.35  
29700   2:30 PM 823500  626875  336.50  127.80  
29700   2:15 PM 812450  631800  308.55  143.00  
29700   2:00 PM 974700  617750  389.80  120.00  
29700   1:45 PM 1072675 547100  262.55  186.85  
29700   1:30 PM 1272300 469600  206.85  232.00  

using below code i have made chart :

subfig = make_subplots(specs=[[{"secondary_y": True}]])

# create two independent figures with px.line each containing data from multiple columns
fig = px.line(df,x='Time', y='Call OI')
fig2 = px.line(df,x='Time', y='Call LTP')

fig2.update_traces(yaxis="y2")

subfig.add_traces(fig.data + fig2.data)
subfig.layout.xaxis.title="Time"
subfig.layout.yaxis.title="OI"
subfig.layout.yaxis2.type="log"
subfig.layout.yaxis2.title="Price"
# recoloring is necessary otherwise lines from fig und fig2 would share each color
# e.g. Linear-, Log- = blue; Linear+, Log+ = red... we don't want this
subfig.for_each_trace(lambda t: t.update(line=dict(color=t.marker.color)))
subfig.show()

I want dropdown menu which selects different index and the chart data changes accordingly. example if i select from drop down 29600 it shows only data for that index number and also is there a way to flip x axis (time) from left to right. Thanks in advance for any solutions

解决方案

Edit 2 - Updated suggestion with linked dataset

In order to use the full dataset provided in the link, just download that content as a csv file, open it and copy the contents, and then run the code below to get the next figure. The data is picked up using dfi = pd.read_clipboard(sep=','). There is really no need to bother with setting 'Strike Price as index. Please note that the dataset has a lot of 0 values, but selecting, for example, 26100 will at least produce a meaningful output:

Complete code for edit 2

import collections
import dash
import pandas as pd

from dash.dependencies import Output, Input
from dash.exceptions import PreventUpdate

from jupyter_dash import JupyterDash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State, ClientsideFunction
import dash_bootstrap_components as dbc
import dash_core_components as dcc
import dash_html_components as html
from plotly.subplots import make_subplots
import plotly.graph_objects as go

dfi = pd.read_clipboard(sep=',')
df = dfi.copy()

idx = list(df['Strike Price'].unique())

app = JupyterDash()

app.layout = html.Div([
    dcc.Store(id='memory-output'),
    dcc.Dropdown(id='memory-countries', options=[
        {'value': x, 'label': x} for x in idx
    ], multi=False, value=idx[0]), 
        dcc.Dropdown(id='memory-field', options=[
        {'value': 'default', 'label': 'default'},
        {'value': 'reverse', 'label': 'reverse'},
    ], value='default'),
    
    html.Div([
        dcc.Graph(id='memory-graph'),
    ])
])


@app.callback(Output('memory-output', 'data'),
              [Input('memory-countries', 'value')])
def filter_countries(idx_selected):
    if not idx_selected:
        # Return all the rows on initial load/no country selected.
        return(idx_selected)
    return(idx_selected)

@app.callback(Output('memory-graph', 'figure'),
              [Input('memory-output', 'data'),
              Input('memory-field', 'value')])
def on_data_set_graph(data, field):
#     print(data)
#     global dff
    if data is None:
        raise PreventUpdate
    
    # figure setup
    fig = make_subplots(specs=[[{"secondary_y": True}]])

    dff = df[df['Strike Price']==data]
    fig.add_trace(go.Scatter(x=dff.Time, y = dff['Call OI'], name = 'Call'), secondary_y=True)
    fig.add_trace(go.Scatter(x=dff.Time, y = dff['Call LTP'], name = 'Put'), secondary_y=False)
    
    # flip axis
    if field != 'default':
        fig.update_layout(xaxis = dict(autorange='reversed'))
    
    return(fig)

app.run_server(mode='inline', port = 8072, dev_tools_ui=True,
          dev_tools_hot_reload =True, threaded=True, debug=True)

Edit - Updated suggestion with axis flipping

My latest suggestion builds on an example under the section Share data between callbacks from dcc.Store and makes the necessary adjustments to work for your use case. I've also incorporated a functionality to flip your x-axis values using: fig.update_layout(xaxis = dict(autorange='reversed'))

Here's the result:

And here's the complete code:

import collections
import dash
import pandas as pd

from dash.dependencies import Output, Input
from dash.exceptions import PreventUpdate

from jupyter_dash import JupyterDash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State, ClientsideFunction
import dash_bootstrap_components as dbc
import dash_core_components as dcc
import dash_html_components as html
from plotly.subplots import make_subplots
import plotly.graph_objects as go

df = pd.DataFrame({'Time': {(29500, '3:30'): 'PM',
                              (29500, '3:15'): 'PM',
                              (29500, '2:59'): 'PM',
                              (29500, '2:45'): 'PM',
                              (29500, '2:30'): 'PM',
                              (29500, '2:15'): 'PM',
                              (29500, '2:00'): 'PM',
                              (29500, '1:45'): 'PM',
                              (29500, '1:30'): 'PM',
                              (29600, '3:30'): 'PM',
                              (29600, '3:15'): 'PM',
                              (29600, '2:59'): 'PM',
                              (29600, '2:45'): 'PM',
                              (29600, '2:30'): 'PM',
                              (29600, '2:15'): 'PM',
                              (29600, '2:00'): 'PM',
                              (29600, '1:45'): 'PM',
                              (29600, '1:30'): 'PM',
                              (29700, '3:30'): 'PM',
                              (29700, '3:15'): 'PM',
                              (29700, '2:59'): 'PM',
                              (29700, '2:45'): 'PM',
                              (29700, '2:30'): 'PM',
                              (29700, '2:15'): 'PM',
                              (29700, '2:00'): 'PM',
                              (29700, '1:45'): 'PM',
                              (29700, '1:30'): 'PM'},
                             'CallOI': {(29500, '3:30'): 502725,
                              (29500, '3:15'): 568725,
                              (29500, '2:59'): 719350,
                              (29500, '2:45'): 786975,
                              (29500, '2:30'): 823500,
                              (29500, '2:15'): 812450,
                              (29500, '2:00'): 974700,
                              (29500, '1:45'): 1072675,
                              (29500, '1:30'): 1272300,
                              (29600, '3:30'): 502725,
                              (29600, '3:15'): 568725,
                              (29600, '2:59'): 719350,
                              (29600, '2:45'): 786975,
                              (29600, '2:30'): 823500,
                              (29600, '2:15'): 812450,
                              (29600, '2:00'): 974700,
                              (29600, '1:45'): 1000000,
                              (29600, '1:30'): 1272300,
                              (29700, '3:30'): 502725,
                              (29700, '3:15'): 568725,
                              (29700, '2:59'): 719350,
                              (29700, '2:45'): 786975,
                              (29700, '2:30'): 823500,
                              (29700, '2:15'): 812450,
                              (29700, '2:00'): 974700,
                              (29700, '1:45'): 1172675,
                              (29700, '1:30'): 1272300},
                             'PutOI': {(29500, '3:30'): 554775,
                              (29500, '3:15'): 629700,
                              (29500, '2:59'): 689850,
                              (29500, '2:45'): 641575,
                              (29500, '2:30'): 626875,
                              (29500, '2:15'): 631800,
                              (29500, '2:00'): 617750,
                              (29500, '1:45'): 547100,
                              (29500, '1:30'): 469600,
                              (29600, '3:30'): 554775,
                              (29600, '3:15'): 629700,
                              (29600, '2:59'): 689850,
                              (29600, '2:45'): 641575,
                              (29600, '2:30'): 626875,
                              (29600, '2:15'): 631800,
                              (29600, '2:00'): 617750,
                              (29600, '1:45'): 547100,
                              (29600, '1:30'): 469600,
                              (29700, '3:30'): 554775,
                              (29700, '3:15'): 629700,
                              (29700, '2:59'): 689850,
                              (29700, '2:45'): 641575,
                              (29700, '2:30'): 626875,
                              (29700, '2:15'): 631800,
                              (29700, '2:00'): 617750,
                              (29700, '1:45'): 547100,
                              (29700, '1:30'): 469600},
                             'CallLTP': {(29500, '3:30'): 343.7,
                              (29500, '3:15'): 357.15,
                              (29500, '2:59'): 337.85,
                              (29500, '2:45'): 360.0,
                              (29500, '2:30'): 336.5,
                              (29500, '2:15'): 308.55,
                              (29500, '2:00'): 389.8,
                              (29500, '1:45'): 262.55,
                              (29500, '1:30'): 206.85,
                              (29600, '3:30'): 343.7,
                              (29600, '3:15'): 357.15,
                              (29600, '2:59'): 337.85,
                              (29600, '2:45'): 360.0,
                              (29600, '2:30'): 336.5,
                              (29600, '2:15'): 308.55,
                              (29600, '2:00'): 389.8,
                              (29600, '1:45'): 262.55,
                              (29600, '1:30'): 206.85,
                              (29700, '3:30'): 343.7,
                              (29700, '3:15'): 357.15,
                              (29700, '2:59'): 337.85,
                              (29700, '2:45'): 360.0,
                              (29700, '2:30'): 336.5,
                              (29700, '2:15'): 308.55,
                              (29700, '2:00'): 389.8,
                              (29700, '1:45'): 262.55,
                              (29700, '1:30'): 206.85},
                             'PutLTP': {(29500, '3:30'): 85.5,
                              (29500, '3:15'): 81.7,
                              (29500, '2:59'): 95.45,
                              (29500, '2:45'): 108.35,
                              (29500, '2:30'): 127.8,
                              (29500, '2:15'): 143.0,
                              (29500, '2:00'): 120.0,
                              (29500, '1:45'): 186.85,
                              (29500, '1:30'): 232.0,
                              (29600, '3:30'): 85.5,
                              (29600, '3:15'): 81.7,
                              (29600, '2:59'): 95.45,
                              (29600, '2:45'): 108.35,
                              (29600, '2:30'): 127.8,
                              (29600, '2:15'): 143.0,
                              (29600, '2:00'): 120.0,
                              (29600, '1:45'): 186.85,
                              (29600, '1:30'): 232.0,
                              (29700, '3:30'): 85.5,
                              (29700, '3:15'): 81.7,
                              (29700, '2:59'): 95.45,
                              (29700, '2:45'): 108.35,
                              (29700, '2:30'): 127.8,
                              (29700, '2:15'): 143.0,
                              (29700, '2:00'): 120.0,
                              (29700, '1:45'): 186.85,
                              (29700, '1:30'): 232.0}})

df = df.reset_index()
idx = list(df['level_0'].unique())

app = JupyterDash()

app.layout = html.Div([
    dcc.Store(id='memory-output'),
    dcc.Dropdown(id='memory-countries', options=[
        {'value': x, 'label': x} for x in idx
    ], multi=False, value=idx[0]), 
        dcc.Dropdown(id='memory-field', options=[
        {'value': 'default', 'label': 'default'},
        {'value': 'reverse', 'label': 'reverse'},
    ], value='default'),
    
    html.Div([
        dcc.Graph(id='memory-graph'),
    ])
])


@app.callback(Output('memory-output', 'data'),
              [Input('memory-countries', 'value')])
def filter_countries(idx_selected):
    if not idx_selected:
        # Return all the rows on initial load/no country selected.
        return(idx_selected)
    return(idx_selected)

@app.callback(Output('memory-graph', 'figure'),
              [Input('memory-output', 'data'),
              Input('memory-field', 'value')])
def on_data_set_graph(data, field):
#     print(data)
    if data is None:
        raise PreventUpdate
    
    # figure setup
    fig = make_subplots(specs=[[{"secondary_y": True}]])

    dff = df[df['level_0']==data]
    fig.add_trace(go.Scatter(x=dff.level_1, y = dff.CallOI, name = 'Call'), secondary_y=True)
    fig.add_trace(go.Scatter(x=dff.level_1, y = dff.PutOI, name = 'Put'), secondary_y=False)
    
    # flip axis
    if field != 'default':
        fig.update_layout(xaxis = dict(autorange='reversed'))
    
    return(fig)

app.run_server(mode='inline', port = 8072, dev_tools_ui=True,
          dev_tools_hot_reload =True, threaded=True, debug=True)


Suggestion 1


You haven't specified how you're using your figures. But assuming it's in JupyterLab, I would higlhy reccommend using JupyterDash. I find that much more felxible than incorporating dropdown features directly in the figure as r-beginners pointed to in the link in the comments.

The code snippet below will let you select which index to show data from in the followin app which is set to produce the figure 'inline' which means in the notebook itself. If you're interested in using an approach like this, I can see if I can implement a button to flip the x-axis as well.

App:

Complete code

import numpy as np
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
from jupyter_dash import JupyterDash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
from plotly.subplots import make_subplots
from dash.dependencies import Input, Output, State

# data
df = pd.DataFrame({'Time': {(29500, '3:30'): 'PM',
                              (29500, '3:15'): 'PM',
                              (29500, '2:59'): 'PM',
                              (29500, '2:45'): 'PM',
                              (29500, '2:30'): 'PM',
                              (29500, '2:15'): 'PM',
                              (29500, '2:00'): 'PM',
                              (29500, '1:45'): 'PM',
                              (29500, '1:30'): 'PM',
                              (29600, '3:30'): 'PM',
                              (29600, '3:15'): 'PM',
                              (29600, '2:59'): 'PM',
                              (29600, '2:45'): 'PM',
                              (29600, '2:30'): 'PM',
                              (29600, '2:15'): 'PM',
                              (29600, '2:00'): 'PM',
                              (29600, '1:45'): 'PM',
                              (29600, '1:30'): 'PM',
                              (29700, '3:30'): 'PM',
                              (29700, '3:15'): 'PM',
                              (29700, '2:59'): 'PM',
                              (29700, '2:45'): 'PM',
                              (29700, '2:30'): 'PM',
                              (29700, '2:15'): 'PM',
                              (29700, '2:00'): 'PM',
                              (29700, '1:45'): 'PM',
                              (29700, '1:30'): 'PM'},
                             'CallOI': {(29500, '3:30'): 502725,
                              (29500, '3:15'): 568725,
                              (29500, '2:59'): 719350,
                              (29500, '2:45'): 786975,
                              (29500, '2:30'): 823500,
                              (29500, '2:15'): 812450,
                              (29500, '2:00'): 974700,
                              (29500, '1:45'): 1072675,
                              (29500, '1:30'): 1272300,
                              (29600, '3:30'): 502725,
                              (29600, '3:15'): 568725,
                              (29600, '2:59'): 719350,
                              (29600, '2:45'): 786975,
                              (29600, '2:30'): 823500,
                              (29600, '2:15'): 812450,
                              (29600, '2:00'): 974700,
                              (29600, '1:45'): 1000000,
                              (29600, '1:30'): 1272300,
                              (29700, '3:30'): 502725,
                              (29700, '3:15'): 568725,
                              (29700, '2:59'): 719350,
                              (29700, '2:45'): 786975,
                              (29700, '2:30'): 823500,
                              (29700, '2:15'): 812450,
                              (29700, '2:00'): 974700,
                              (29700, '1:45'): 1172675,
                              (29700, '1:30'): 1272300},
                             'PutOI': {(29500, '3:30'): 554775,
                              (29500, '3:15'): 629700,
                              (29500, '2:59'): 689850,
                              (29500, '2:45'): 641575,
                              (29500, '2:30'): 626875,
                              (29500, '2:15'): 631800,
                              (29500, '2:00'): 617750,
                              (29500, '1:45'): 547100,
                              (29500, '1:30'): 469600,
                              (29600, '3:30'): 554775,
                              (29600, '3:15'): 629700,
                              (29600, '2:59'): 689850,
                              (29600, '2:45'): 641575,
                              (29600, '2:30'): 626875,
                              (29600, '2:15'): 631800,
                              (29600, '2:00'): 617750,
                              (29600, '1:45'): 547100,
                              (29600, '1:30'): 469600,
                              (29700, '3:30'): 554775,
                              (29700, '3:15'): 629700,
                              (29700, '2:59'): 689850,
                              (29700, '2:45'): 641575,
                              (29700, '2:30'): 626875,
                              (29700, '2:15'): 631800,
                              (29700, '2:00'): 617750,
                              (29700, '1:45'): 547100,
                              (29700, '1:30'): 469600},
                             'CallLTP': {(29500, '3:30'): 343.7,
                              (29500, '3:15'): 357.15,
                              (29500, '2:59'): 337.85,
                              (29500, '2:45'): 360.0,
                              (29500, '2:30'): 336.5,
                              (29500, '2:15'): 308.55,
                              (29500, '2:00'): 389.8,
                              (29500, '1:45'): 262.55,
                              (29500, '1:30'): 206.85,
                              (29600, '3:30'): 343.7,
                              (29600, '3:15'): 357.15,
                              (29600, '2:59'): 337.85,
                              (29600, '2:45'): 360.0,
                              (29600, '2:30'): 336.5,
                              (29600, '2:15'): 308.55,
                              (29600, '2:00'): 389.8,
                              (29600, '1:45'): 262.55,
                              (29600, '1:30'): 206.85,
                              (29700, '3:30'): 343.7,
                              (29700, '3:15'): 357.15,
                              (29700, '2:59'): 337.85,
                              (29700, '2:45'): 360.0,
                              (29700, '2:30'): 336.5,
                              (29700, '2:15'): 308.55,
                              (29700, '2:00'): 389.8,
                              (29700, '1:45'): 262.55,
                              (29700, '1:30'): 206.85},
                             'PutLTP': {(29500, '3:30'): 85.5,
                              (29500, '3:15'): 81.7,
                              (29500, '2:59'): 95.45,
                              (29500, '2:45'): 108.35,
                              (29500, '2:30'): 127.8,
                              (29500, '2:15'): 143.0,
                              (29500, '2:00'): 120.0,
                              (29500, '1:45'): 186.85,
                              (29500, '1:30'): 232.0,
                              (29600, '3:30'): 85.5,
                              (29600, '3:15'): 81.7,
                              (29600, '2:59'): 95.45,
                              (29600, '2:45'): 108.35,
                              (29600, '2:30'): 127.8,
                              (29600, '2:15'): 143.0,
                              (29600, '2:00'): 120.0,
                              (29600, '1:45'): 186.85,
                              (29600, '1:30'): 232.0,
                              (29700, '3:30'): 85.5,
                              (29700, '3:15'): 81.7,
                              (29700, '2:59'): 95.45,
                              (29700, '2:45'): 108.35,
                              (29700, '2:30'): 127.8,
                              (29700, '2:15'): 143.0,
                              (29700, '2:00'): 120.0,
                              (29700, '1:45'): 186.85,
                              (29700, '1:30'): 232.0}})

df = df.reset_index()

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = JupyterDash(__name__, external_stylesheets=external_stylesheets)

# options for dropdown
criteria = list(df['level_0'].unique())
options = [{'label': i, 'value': i} for i in criteria]
options.append

# app layout
app.layout = html.Div([
                    html.Div([
                        html.Div([
                                  dcc.Dropdown(id='linedropdown',
                                               options=options,                    
                                               value=options[0]['value'],),
                                 ],
                                ),
                                ],className='row'),

                    html.Div([
                        html.Div([
                                  dcc.Graph(id='linechart'),
                                 ],
                                ),
                             ],
                            ),
])

@app.callback(
    [Output('linechart', 'figure')],
    [Input('linedropdown', 'value')]
)

def update_graph(linedropdown):

    # selection using linedropdown
    dff = df[df['level_0']==linedropdown]

    # Create figure with secondary y-axis
    fig = make_subplots(specs=[[{"secondary_y": True}]])

    # Add trace 1
    fig.add_trace(
        go.Scatter(x=dff['level_1'], y=dff['CallOI'], name="Call OI"),
        secondary_y=True,
    )

    # Add trace 2
    fig.add_trace(
        go.Scatter(x=dff['level_1'], y=dff['CallLTP'], name="Call LTP"),
        secondary_y=False,
    )
    fig.update_layout(title = 'Index: ' + str(linedropdown))
    
    return ([fig])

# Run app and display result inline in the notebook
app.run_server(mode='inline', port = 8040, dev_tools_ui=True, debug=True,
              dev_tools_hot_reload =True, threaded=True)

这篇关于Plotly:如何制作多索引下拉选项?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆