Difference between revisions of "Dash - Plotly"
Adelo Vieira (talk | contribs) (→Gunicorn) |
Adelo Vieira (talk | contribs) (→Flask Deployment) |
||
Line 152: | Line 152: | ||
<br /> | <br /> | ||
<blockquote> | <blockquote> | ||
− | '''Installation | + | '''Installation:''' |
https://anaconda.org/conda-forge/gunicorn | https://anaconda.org/conda-forge/gunicorn | ||
<syntaxhighlight> | <syntaxhighlight> | ||
conda install -c conda-forge gunicorn | conda install -c conda-forge gunicorn | ||
+ | </syntaxhighlight> | ||
+ | or | ||
+ | <syntaxhighlight> | ||
+ | pip install gunicorn | ||
</syntaxhighlight> | </syntaxhighlight> | ||
</blockquote> | </blockquote> | ||
Line 174: | Line 178: | ||
The <code>gunicorn</code> command expects the names of your application module or package and the application instance within the module. If you use the application factory pattern, you can pass a call to that: | The <code>gunicorn</code> command expects the names of your application module or package and the application instance within the module. If you use the application factory pattern, you can pass a call to that: | ||
− | + | gunicorn "myproject:create_app()" | |
Revision as of 22:48, 18 November 2019
Contents
Word cloud
https://github.com/amueller/word_cloud
In Dash:
Installation
Using pip:
pip install wordcloud
Using conda:
https://anaconda.org/conda-forge/wordcloud
conda install -c conda-forge wordcloud
Installation notes:
wordcloud
depends on numpy
and pillow
.
To save the wordcloud
into a file, matplotlib
can also be installed.
Minimal example
Can be run in jupyter-notebook:
"""
Minimal Example
===============
Generating a square wordcloud from the US constitution using default arguments.
"""
import os
from os import path
from wordcloud import WordCloud
# get data directory (using getcwd() is needed to support running example in generated IPython notebook)
d = path.dirname(__file__) if "__file__" in locals() else os.getcwd()
# Read the whole text.
text = open(path.join(d, 'constitution.txt')).read()
# Generate a word cloud image
wordcloud = WordCloud().generate(text)
# Display the generated image:
# the matplotlib way:
import matplotlib.pyplot as plt
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis("off")
# lower max_font_size
wordcloud = WordCloud(max_font_size=40).generate(text)
plt.figure()
plt.imshow(wordcloud, interpolation="bilinear")
plt.axis("off")
plt.show()
# The pil way (if you don't have matplotlib)
# image = wordcloud.to_image()
# image.show()
Dash
https://dash.plot.ly/?_ga=2.87536863.631018149.1572391590-265914126.1570370926
Material from the Udemy's course I'm doing: https://www.udemy.com/course/interactive-python-dashboards-with-plotly-and-dash/
- https://docs.google.com/document/d/1DjWL2DxLiRaBrlD3ELyQlCBRu7UQuuWfgjv9LncNp_M/edit#heading=h.6kzspbaklmdx
- https://docs.google.com/document/d/1vI84_EpRTh4xfcFkTunFzZT0RWMcRSqdkPueVNBcLx8/edit
- https://github.com/Pierian-Data/Plotly-Dashboards-with-Dash
Dash apps consist of a Flask server that communicates with front-end React components using JSON packets over HTTP requests. https://www.tutorialspoint.com/python_web_development_libraries/python_web_development_libraries_dash_framework.htm
Installation
https://dash.plot.ly/installation
pip install dash==1.4.1 # The core dash backend
pip install dash-daq==0.2.1 # DAQ components (newly open-sourced!)
# Note: starting with dash 0.37.0, dash automatically installs dash-renderer, dash-core-components, dash-html-components, and dash-table, using known-compatible versions of each. You need not and should not install these separately any longer, only dash itself.
A quick note on checking your versions and on upgrading. These docs are run using the versions listed above and these versions should be the latest versions available. To check which version that you have installed, you can run e.g:
>>> import dash_core_components
>>> print(dash_core_components.__version__)
To see the latest changes of any package, check the GitHub repo's CHANGELOG.md file:
- dash & dash-renderer changelog
dash-renderer
is a separate package installed automatically with dash but its updates are included in the main dash changelog. These docs are using dash-renderer==1.1.2.
- dash-core-components changelog
- dash-html-components changelog
- dash-table changelog
- plotly changelog
- the
plotly
package is also installed automatically with dash. It is the Python interface to the plotly.js graphing library, so is mainly used by dash-core-components, but it's also used by dash itself. These docs are using plotly==3.3.0.
- the
All of these packages adhere to semver.
Deploying Dash Apps
https://dash.plot.ly/deployment
Dash uses Flask under the hood. This makes deployment easy: you can deploy a Dash app just like you would deploy a Flask app. Almost every cloud server provider has a guide for deploying Flask apps. There is also a Dash Deployment Server, but is not free (commercial).
- Flask Deployment
- Dash Deployment Server (commercial)
Flask Deployment
https://flask.palletsprojects.com/en/1.1.x/deploying/
Gunicorn
https://flask.palletsprojects.com/en/1.1.x/deploying/wsgi-standalone/
Installation:
https://anaconda.org/conda-forge/gunicorn
conda install -c conda-forge gunicornor
pip install gunicorn
Gunicorn
«Green Unicorn» is a WSGI HTTP Server for UNIX. It's a pre-fork worker model ported from Ruby's Unicorn project. It supports both eventlet
and greenlet
. Running a Flask application on this server is quite simple:
gunicorn myproject:app
Gunicorn provides many command-line options (see gunicorn -h
). For example, to run a Flask application with 4 worker processes (-w 4
) binding to localhost port 4000 (-b 127.0.0.1:4000
):
gunicorn -w 4 -b 127.0.0.1:4000 myproject:app
The gunicorn
command expects the names of your application module or package and the application instance within the module. If you use the application factory pattern, you can pass a call to that:
gunicorn "myproject:create_app()"
Dash Layout
https://dash.plot.ly/getting-started
Dash apps are composed of two parts:
- The first part is' the "layout" of the app and it describes what the application looks like.
- The second part describes the interactivity of the application and will be covered in the next chapter.
Dash provides Python classes for all of the visual components of the application. We maintain a set of components in the dash_core_components
and the dash_html_components
library but you can also build your own with JavaScript
and React.js
.
To get started, create a file named `app.py` with the following code:
# -*- coding: utf-8 -*-
import dash
import dash_core_components as dcc
import dash_html_components as html
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div(children=[
html.H1(children='Hello Dash'),
html.Div(children='''
Dash: A web application framework for Python.
'''),
dcc.Graph(
id='example-graph',
figure={
'data': [
{'x': [1, 2, 3], 'y': [4, 1, 2], 'type': 'bar', 'name': 'SF'},
{'x': [1, 2, 3], 'y': [2, 4, 5], 'type': 'bar', 'name': u'Montréal'},
],
'layout': {
'title': 'Dash Data Visualization'
}
}
)
])
if __name__ == '__main__':
app.run_server(debug=True, port=8051)
Es importante utilizar un port que no esté ocupado por otro proceso.
Examples
Example 2
import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import plotly.graph_objs as go
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
df = pd.read_csv(
'https://gist.githubusercontent.com/chriddyp/'
'cb5392c35661370d95f300086accea51/raw/'
'8e0768211f6b747c0db42a9ce9a0937dafcbd8b2/'
'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()}
), 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]
return {
'data': [go.Scatter(
x=dff[dff['Indicator Name'] == xaxis_column_name]['Value'],
y=dff[dff['Indicator Name'] == yaxis_column_name]['Value'],
text=dff[dff['Indicator Name'] == yaxis_column_name]['Country Name'],
customdata=dff[dff['Indicator Name'] == yaxis_column_name]['Country Name'],
mode='markers',
marker={
'size': 15,
'opacity': 0.5,
'line': {'width': 0.5, 'color': 'white'}
}
)],
'layout': go.Layout(
xaxis={
'title': xaxis_column_name,
'type': 'linear' if xaxis_type == 'Linear' else 'log'
},
yaxis={
'title': yaxis_column_name,
'type': 'linear' if yaxis_type == 'Linear' else 'log'
},
margin={'l': 40, 'b': 30, 't': 10, 'r': 0},
height=450,
hovermode='closest'
)
}
def create_time_series(dff, axis_type, title):
return {
'data': [go.Scatter(
x=dff['Year'],
y=dff['Value'],
mode='lines+markers'
)],
'layout': {
'height': 225,
'margin': {'l': 20, 'b': 30, 'r': 10, 't': 10},
'annotations': [{
'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
}],
'yaxis': {'type': 'linear' if axis_type == 'Linear' else 'log'},
'xaxis': {'showgrid': False}
}
}
@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)
if __name__ == '__main__':
app.run_server(debug=True, port=8051)