【问题标题】:How to use dash within Jupyter notebook or JupyterLab?如何在 Jupyter notebook 或 JupyterLab 中使用破折号?
【发布时间】:2018-01-11 09:36:58
【问题描述】:

是否可以在 Jupyter Notebook 中使用仪表板应用程序,而不是在浏览器中提供和查看?

我的目的是在 Jupyter 笔记本中链接图表,以便将鼠标悬停在一个图表上生成另一个图表所需的输入。

【问题讨论】:

    标签: python jupyter-notebook plotly plotly-dash


    【解决方案1】:

    (免责声明,我帮助维护 Dash)

    https://github.com/plotly/jupyterlab-dash。这是在 Jupyter 中嵌入 Dash 的 JupyterLab 扩展。

    另请参阅Dash Community Forum 中的替代解决方案,例如Can I run dash app in jupyter topic

    【讨论】:

    • 注意:目前还不支持Windows。
    • 我使用 %%file <scriptname> 魔术字将脚本保存到文件中。然后我使用!python -I <scriptname> 运行脚本。我在 Windows 10 中使用 Jupyter Lab。
    • 请注意,现在有一个官方的JupyterDash 库,它也适用于 Jupyter notebooks 和 Google colab。
    【解决方案2】:

    这个问题已经有了很好的答案,但本文将直接关注:

    1.如何在 Jupyterlab中使用 Dash,以及

    2.如何将鼠标悬停在另一个图表上选择图表输入


    按照这些步骤将直接在 JupyterLab 中释放 Plotly Dash:

    1.安装最新的Plotly版本

    2. 使用 conda install -c plotly jupyterlab-dash 安装 JupyterLab Dash

    3. 使用 sn-p 提供的进一步向下启动一个 Dash 应用程序,该应用程序包含一个基于 Pandas 数据帧构建的动画,每秒扩展一次。

    JupyterLab 中 Dash 的屏幕截图(下面的 sn-p 中的代码)

    这张图片显示了 Dash 字面意思在 JupyterLab 中被激发。四个突出显示的部分是:

    1 - 单元格。.ipynb 中您可能已经非常熟悉的单元格

    2 - Dash。一个“实时”的 dash 应用程序,它使用随机数扩展所有三个轨迹,并每秒显示更新的数字。

    3 - 控制台。一个控制台,您可以在其中检查脚本中的可用元素,例如,fig.show

    4 - mode. 这显示了一些真正的魔力所在:

    app.run_server(mode='jupyterlab', port = 8090, dev_tools_ui=True, #debug=True,
                  dev_tools_hot_reload =True, threaded=True)
    

    您可以选择在以下位置启动 dash 应用程序:

    1. Jupyterlab,就像截图中的mode='jupyterlab'一样,
    2. 或在单元格中,使用mode='inline'

    1. 或在默认浏览器中使用mode='external'

    代码1:

    import pandas as pd
    import numpy as np
    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
    
    # code and plot setup
    # settings
    pd.options.plotting.backend = "plotly"
    
    # sample dataframe of a wide format
    np.random.seed(4); cols = list('abc')
    X = np.random.randn(50,len(cols))  
    df=pd.DataFrame(X, columns=cols)
    df.iloc[0]=0;
    
    # plotly figure
    fig = df.plot(template = 'plotly_dark')
    
    app = JupyterDash(__name__)
    app.layout = html.Div([
        html.H1("Random datastream"),
                dcc.Interval(
                id='interval-component',
                interval=1*1000, # in milliseconds
                n_intervals=0
            ),
        dcc.Graph(id='graph'),
    ])
    
    # Define callback to update graph
    @app.callback(
        Output('graph', 'figure'),
        [Input('interval-component', "n_intervals")]
    )
    def streamFig(value):
        
        global df
        
        Y = np.random.randn(1,len(cols))  
        df2 = pd.DataFrame(Y, columns = cols)
        df = df.append(df2, ignore_index=True)#.reset_index()
        df.tail()
        df3=df.copy()
        df3 = df3.cumsum()
        fig = df3.plot(template = 'plotly_dark')
        #fig.show()
        return(fig)
    
    app.run_server(mode='jupyterlab', port = 8090, dev_tools_ui=True, #debug=True,
                  dev_tools_hot_reload =True, threaded=True)
    

    但好消息还不止于此,关于:

    我的目的是在 Jupyter 笔记本中链接图表,以便 将鼠标悬停在一个图形上会生成另一个图形所需的输入 图表。

    dash.plotly.com 上有一个完美的例子,可以在 Update Graphs on Hover 段落下为您做到这一点:

    我已经对原始设置进行了一些必要的更改,以便可以在 JupyterLab 中运行它。

    代码 sn-p 2 - 通过悬停选择图形源:

    import pandas as pd
    import numpy as np
    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
    import dash.dependencies
    
    # code and plot setup
    # settings
    pd.options.plotting.backend = "plotly"
    
    
    external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
    
    app = JupyterDash(__name__, external_stylesheets=external_stylesheets)
    
    df = pd.read_csv('https://plotly.github.io/datasets/country_indicators.csv')
    
    available_indicators = df['Indicator Name'].unique()
    
    app.layout = html.Div([
        html.Div([
    
            html.Div([
                dcc.Dropdown(
                    id='crossfilter-xaxis-column',
                    options=[{'label': i, 'value': i} for i in available_indicators],
                    value='Fertility rate, total (births per woman)'
                ),
                dcc.RadioItems(
                    id='crossfilter-xaxis-type',
                    options=[{'label': i, 'value': i} for i in ['Linear', 'Log']],
                    value='Linear',
                    labelStyle={'display': 'inline-block'}
                )
            ],
            style={'width': '49%', 'display': 'inline-block'}),
    
            html.Div([
                dcc.Dropdown(
                    id='crossfilter-yaxis-column',
                    options=[{'label': i, 'value': i} for i in available_indicators],
                    value='Life expectancy at birth, total (years)'
                ),
                dcc.RadioItems(
                    id='crossfilter-yaxis-type',
                    options=[{'label': i, 'value': i} for i in ['Linear', 'Log']],
                    value='Linear',
                    labelStyle={'display': 'inline-block'}
                )
            ], style={'width': '49%', 'float': 'right', 'display': 'inline-block'})
        ], style={
            'borderBottom': 'thin lightgrey solid',
            'backgroundColor': 'rgb(250, 250, 250)',
            'padding': '10px 5px'
        }),
    
        html.Div([
            dcc.Graph(
                id='crossfilter-indicator-scatter',
                hoverData={'points': [{'customdata': 'Japan'}]}
            )
        ], style={'width': '49%', 'display': 'inline-block', 'padding': '0 20'}),
        html.Div([
            dcc.Graph(id='x-time-series'),
            dcc.Graph(id='y-time-series'),
        ], style={'display': 'inline-block', 'width': '49%'}),
    
        html.Div(dcc.Slider(
            id='crossfilter-year--slider',
            min=df['Year'].min(),
            max=df['Year'].max(),
            value=df['Year'].max(),
            marks={str(year): str(year) for year in df['Year'].unique()},
            step=None
        ), style={'width': '49%', 'padding': '0px 20px 20px 20px'})
    ])
    
    
    @app.callback(
        dash.dependencies.Output('crossfilter-indicator-scatter', 'figure'),
        [dash.dependencies.Input('crossfilter-xaxis-column', 'value'),
         dash.dependencies.Input('crossfilter-yaxis-column', 'value'),
         dash.dependencies.Input('crossfilter-xaxis-type', 'value'),
         dash.dependencies.Input('crossfilter-yaxis-type', 'value'),
         dash.dependencies.Input('crossfilter-year--slider', 'value')])
    def update_graph(xaxis_column_name, yaxis_column_name,
                     xaxis_type, yaxis_type,
                     year_value):
        dff = df[df['Year'] == year_value]
    
        fig = px.scatter(x=dff[dff['Indicator Name'] == xaxis_column_name]['Value'],
                y=dff[dff['Indicator Name'] == yaxis_column_name]['Value'],
                hover_name=dff[dff['Indicator Name'] == yaxis_column_name]['Country Name']
                )
    
        fig.update_traces(customdata=dff[dff['Indicator Name'] == yaxis_column_name]['Country Name'])
    
        fig.update_xaxes(title=xaxis_column_name, type='linear' if xaxis_type == 'Linear' else 'log')
    
        fig.update_yaxes(title=yaxis_column_name, type='linear' if yaxis_type == 'Linear' else 'log')
    
        fig.update_layout(margin={'l': 40, 'b': 40, 't': 10, 'r': 0}, hovermode='closest')
    
        return fig
    
    
    def create_time_series(dff, axis_type, title):
    
        fig = px.scatter(dff, x='Year', y='Value')
    
        fig.update_traces(mode='lines+markers')
    
        fig.update_xaxes(showgrid=False)
    
        fig.update_yaxes(type='linear' if axis_type == 'Linear' else 'log')
    
        fig.add_annotation(x=0, y=0.85, xanchor='left', yanchor='bottom',
                           xref='paper', yref='paper', showarrow=False, align='left',
                           bgcolor='rgba(255, 255, 255, 0.5)', text=title)
    
        fig.update_layout(height=225, margin={'l': 20, 'b': 30, 'r': 10, 't': 10})
    
        return fig
    
    
    @app.callback(
        dash.dependencies.Output('x-time-series', 'figure'),
        [dash.dependencies.Input('crossfilter-indicator-scatter', 'hoverData'),
         dash.dependencies.Input('crossfilter-xaxis-column', 'value'),
         dash.dependencies.Input('crossfilter-xaxis-type', 'value')])
    def update_y_timeseries(hoverData, xaxis_column_name, axis_type):
        country_name = hoverData['points'][0]['customdata']
        dff = df[df['Country Name'] == country_name]
        dff = dff[dff['Indicator Name'] == xaxis_column_name]
        title = '<b>{}</b><br>{}'.format(country_name, xaxis_column_name)
        return create_time_series(dff, axis_type, title)
    
    
    @app.callback(
        dash.dependencies.Output('y-time-series', 'figure'),
        [dash.dependencies.Input('crossfilter-indicator-scatter', 'hoverData'),
         dash.dependencies.Input('crossfilter-yaxis-column', 'value'),
         dash.dependencies.Input('crossfilter-yaxis-type', 'value')])
    def update_x_timeseries(hoverData, yaxis_column_name, axis_type):
        dff = df[df['Country Name'] == hoverData['points'][0]['customdata']]
        dff = dff[dff['Indicator Name'] == yaxis_column_name]
        return create_time_series(dff, axis_type, yaxis_column_name)
    
    
    app.run_server(mode='jupyterlab', port = 8090, dev_tools_ui=True, #debug=True,
                  dev_tools_hot_reload =True, threaded=True)
    

    【讨论】:

      【解决方案3】:

      我不确定 dash 应用程序是否可以显示在 Jupyter 笔记本中。但如果您正在寻找的是使用滑块、组合框和其他按钮,您可能会对直接来自 Jupyter 的 ipywidgets 感兴趣。

      这些可以和plotly一起使用,如图here


      编辑

      最终似乎有解决方案可以通过使用 iframe 和 IPython.display.display_html() 在 Jupyter 中嵌入 dash 应用程序。 详情请参阅this functionthis GitHub repo

      【讨论】:

      • 我有兴趣将 dash 应用程序放入 Jupyter 中,让一个图表上的悬停位置成为另一个图表的输入 - 据我所知,只有 Dash 才有可能。
      • @bluprince13 好的,因此我同意需要 Dash。当我通过将 Dash 应用程序嵌入 Jupyter 的可能解决方案时更新了我的答案。现在无法测试它,但让我知道它是否有效:)。
      【解决方案4】:

      寻找情节离线。

      假设你有一个图(例如 fig = {'data': data, 'layout':layout} )

      那么, 在 jupyter 笔记本单元内,

      from plotly.offline import iplot, init_notebook_mode
      init_notebook_mode()
      # plot it
      iplot(fig)
      

      这将在你的 jupyter 中绘制情节。您甚至不必运行烧瓶服务器。

      【讨论】:

      • 我知道 plotly 离线,但我特别想要笔记本中的滑块、组合框、单选按钮等,即仪表板应用程序。
      • 我知道如何在 Jupyter 中制作内联图。我特别想问是否有可能拥有内联仪表板应用程序。
      猜你喜欢
      • 2020-03-12
      • 2019-10-20
      • 1970-01-01
      • 2018-12-01
      • 1970-01-01
      • 2020-03-22
      • 1970-01-01
      • 2018-11-02
      • 1970-01-01
      相关资源
      最近更新 更多