简体   繁体   English

如何在 Jupyter notebook 或 JupyterLab 中使用破折号?

[英]How to use dash within Jupyter notebook or JupyterLab?

Is it possible to have a dash app within a Jupyter Notebook, rather than served up and viewed in a browser?是否可以在 Jupyter Notebook 中使用 dash 应用程序,而不是在浏览器中提供和查看?

My intention is to link graphs within a Jupyter notebook so that hovering over one graph generates the input required for another graph.我的目的是在 Jupyter 笔记本中链接图表,以便将鼠标悬停在一个图表上生成另一个图表所需的输入。

(Disclaimer, I help maintain Dash) (免责声明,我帮助维护 Dash)

See https://github.com/plotly/jupyterlab-dash .请参阅https://github.com/plotly/jupyterlab-dash This is a JupyterLab extension that embeds Dash within Jupyter.这是一个 JupyterLab 扩展,它在 Jupyter 中嵌入了 Dash。

Jupyter 中的 Dash 应用程序

Also see alternative solutions in the Dash Community Forum like the Can I run dash app in jupyter topic .另请参阅Dash 社区论坛中的替代解决方案,例如Can I run dash app in jupyter 主题

There's already a great answer to this question, but this contribution will focus directly on:这个问题已经有一个很好的答案,但这个贡献将直接集中在:

1. How to use Dash within Jupyterlab , and 1.如何在 Jupyterlab 中使用 Dash,以及

2. how to select graphing input by hovering over another graph 2.如何通过将鼠标悬停在另一个图形上来选择图形输入


Following these steps will unleash Plotly Dash directly in JupyterLab:遵循这些步骤将直接在 JupyterLab 中释放 Plotly Dash:

1. Install the latest Plotly version 1.安装最新的Plotly版本

2. Installl JupyterLab Dash with conda install -c plotly jupyterlab-dash 2. 使用conda conda install -c plotly jupyterlab-dash JupyterLab Dash

3. Using the snippet provided a bit further down launch a Dash app that contains an animation built on a pandas dataframe that expands every second. 3.使用提供的代码片段进一步启动一个 Dash 应用程序,其中包含一个建立在每秒扩展的 Pandas 数据帧上的动画。

Screenshot of the Dash in JupyterLab (code in snippet below) JupyterLab 中 Dash 的屏幕截图(以下代码段中的代码)

在此处输入图片说明

This image shows Dash literally fired up inside JupyterLab.这张图片显示了 Dash 在 JupyterLab 内部真的被激发了。 The four highlighted sections are:突出显示的四个部分是:

1 - Cell. 1 - 细胞。 A cell in a .ipynb that you're already probably very familiar with您可能已经非常熟悉的.ipynb中的单元格

2 - Dash. 2 - 破折号。 A "live" dash app that expands all three traces with a random number and shows the updated figure every second.一个“实时”破折号应用程序,它用一个随机数扩展所有三个轨迹,并每秒显示更新的数字。

3 - Console. 3 - 控制台。 An console where you can inspect available elements in your script using, for example, fig.show一个控制台,您可以在其中使用例如fig.show检查脚本中的可用元素

4 - mode . 4 mode This shows where some true magic resides:这显示了一些真正的魔法所在:

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

You can choose to fire up the dash app in:您可以选择在以下位置启动 dash 应用程序:

  1. Jupyterlab, like in the screenshot with mode='jupyterlab' , Jupyterlab,就像截图中的mode='jupyterlab'
  2. or in a cell, using mode='inline' :或在单元格中,使用mode='inline'

在此处输入图片说明

  1. or in your default browser using mode='external'或在您的默认浏览器中使用mode='external'

在此处输入图片说明

Code 1:代码 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)

But the good news does not end there, regarding:但好消息并不止于此,关于:

My intention is to link graphs within a Jupyter notebook so that hovering over one graph generates the input required for another graph.我的目的是在 Jupyter 笔记本中链接图形,以便将鼠标悬停在一个图形上会生成另一个图形所需的输入。

There's a perfect example on dash.plotly.com that will do exactly that for you under the paragraph Update Graphs on Hover :dash.plotly.com上有一个完美的例子,它可以Update Graphs on Hover段落下为您做到这一点:

在此处输入图片说明

I've made the few necessary changes in the original setup to make it possible to run it in JupyterLab.我对原始设置进行了一些必要的更改,以便可以在 JupyterLab 中运行它。

Code snippet 2 - Select graph source by hovering:代码片段 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)

My intention is to link graphs within a Jupter notebook so that hovering over one graph generates the input required for another graph. 我的意图是在Jupter笔记本中链接图形,以便将鼠标悬停在一个图形上可以生成另一图形所需的输入。

Similar functionality already exists in Bokeh . 散景中已经存在类似的功能。

Also, look at this question. 另外,看看这个问题。

I am not sure dash apps can be displayed within a Jupyter notebook.我不确定是否可以在 Jupyter 笔记本中显示dash应用程序。 But if what you're looking for is using sliders, combo boxes and other buttons, you may be interested in ipywidgets that come from Jupyter directly.但是,如果你正在寻找什么用滑块,组合框和其他按钮是,你可能有兴趣在ipywidgets直接来自Jupyter。

These may be used with plotly, as shown here .这些可以与plotly被使用,如所示在这里


EDIT编辑

Eventually it seems that there are solutions to embed dash apps inside Jupyter by using an iframe and IPython.display.display_html() .最终似乎有解决方案可以使用 iframe 和IPython.display.display_html()在 Jupyter 中嵌入dash应用程序。 See this function and this GitHub repo for details.有关详细信息,请参阅此函数此 GitHub 存储库

You can install jupyter-plotly-dash so that you can run the dash apps on Jupyter Notebook. 您可以安装jupyter-plotly-dash,以便可以在Jupyter Notebook上运行破折号应用程序。 You might need to think about the offline-component of plotly, but I'm not too sure how that will work. 您可能需要考虑plotly的离线组件,但是我不太确定它如何工作。 Hope this helps! 希望这可以帮助!

See https://medium.com/plotly/introducing-jupyterdash-811f1f57c02ehttps://medium.com/plotly/introducing-jupyterdash-811f1f57c02e

$ pip install jupyter-dash

from jupyter_dash import JupyterDash
app = JupyterDash(__name__)
<your code>
app.run_server(mode='inline')

Look for plotly offline.寻找 plotly 离线。

Say you have a figure (eg fig = {'data': data, 'layout':layout} )假设你有一个数字(例如 fig = {'data': data, 'layout':layout} )

Then, inside a jupyter notebook cell,然后,在 jupyter notebook 单元中,

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

This will plot the plotly inside your jupyter.这将在您的 jupyter 中绘制 plotly。 You dont even have to run the flask server.您甚至不必运行 Flask 服务器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM