Last active
November 5, 2020 16:43
-
-
Save xhluca/6a6ced8abf4fa5c2eb14738cba4a75f3 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import dash | |
import dash_core_components as dcc | |
import dash_html_components as html | |
from dash.dependencies import Input, Output | |
import plotly.express as px | |
import pandas as pd | |
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css'] | |
app = dash.Dash(__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='xaxis-column', | |
options=[{'label': i, 'value': i} for i in available_indicators], | |
value='Fertility rate, total (births per woman)' | |
), | |
dcc.RadioItems( | |
id='xaxis-type', | |
options=[{'label': i, 'value': i} for i in ['Linear', 'Log']], | |
value='Linear', | |
labelStyle={'display': 'inline-block'} | |
) | |
], | |
style={'width': '48%', 'display': 'inline-block'}), | |
html.Div([ | |
dcc.Dropdown( | |
id='yaxis-column', | |
options=[{'label': i, 'value': i} for i in available_indicators], | |
value='Life expectancy at birth, total (years)' | |
), | |
dcc.RadioItems( | |
id='yaxis-type', | |
options=[{'label': i, 'value': i} for i in ['Linear', 'Log']], | |
value='Linear', | |
labelStyle={'display': 'inline-block'} | |
) | |
],style={'width': '48%', 'float': 'right', 'display': 'inline-block'}) | |
]), | |
dcc.Graph(id='indicator-graphic'), | |
dcc.Slider( | |
id='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 | |
) | |
]) | |
@app.callback( | |
Output('indicator-graphic', 'figure'), | |
[Input('xaxis-column', 'value'), | |
Input('yaxis-column', 'value'), | |
Input('xaxis-type', 'value'), | |
Input('yaxis-type', 'value'), | |
Input('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_layout(margin={'l': 40, 'b': 40, 't': 10, 'r': 0}, hovermode='closest') | |
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') | |
return fig | |
if __name__ == '__main__': | |
app.run_server(debug=True) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import inspect | |
import types | |
import sys | |
import dash_html_components as html | |
import dash_core_components as dcc | |
import dash_bootstrap_components as dbc | |
import dash | |
from dash.dependencies import Input, Output, State | |
class Row(dbc.Row): | |
def add(*components): | |
""" | |
Add one or more components as new column to this row. | |
""" | |
new_cols = [dbc.Col(c) for c in components] | |
self.children.extend(new_cols) | |
def append(component): | |
""" | |
Directly append single new component to the list of children | |
""" | |
self.children.append(component) | |
class UserInterface: | |
def __init__(self, bootstrap=True, external_stylesheets=[]): | |
if bootstrap: | |
external_stylesheets.append(dbc.themes.BOOTSTRAP) | |
# Define the app and layout | |
self.app = dash.Dash(external_stylesheets=external_stylesheets) | |
self.layout = dbc.Container([], fluid=True) | |
self.app.layout = self.layout | |
self.ids = [] | |
def __check_id(self, component): | |
if not hasattr(component, 'id'): | |
component.id = f"component-{len(self.ids)}" | |
if component.id in self.ids: | |
raise Exception("This component already exists. Please add a new component.") | |
self.ids.append(component.id) | |
if hasattr(component, 'children') and type(component.children) is list: | |
for child in component.children: | |
if type(child) is not str: | |
self.__check_id(child) | |
def add(self, *components): | |
""" | |
Add a component to the current layout | |
""" | |
for c in components: | |
self.__check_id(c) | |
self.layout.children.extend(components) | |
return self.layout.children | |
def add_row(self, *components): | |
""" | |
Add a new row with all the components specified. | |
""" | |
for c in components: | |
self.__check_id(c) | |
row = Row([dbc.Col(c) for c in components]) | |
self.layout.children.append(row) | |
return row | |
def add_func(self, fn): | |
""" | |
Add an interaction between various components | |
""" | |
inputs = [] | |
states = [] | |
sig = inspect.signature(fn) | |
mode = 'input' | |
for param in sig.parameters.values(): | |
annot = param.annotation | |
# Convert string into Inputs | |
if type(annot) is str: | |
annot = I(annot) | |
# If it's an input, then we add it to the inputs list | |
if type(annot) is Input: | |
if mode == 'state': | |
raise Exception("Inputs and States need to be separate") | |
inputs.append(annot) | |
elif type(annot) is State: | |
states.append(annot) | |
mode = 'state' | |
else: | |
raise Exception("The function annotation can only be an Input or State. Please use I and S.") | |
if type(sig.return_annotation) is str: | |
outputs = O(sig.return_annotation) | |
elif type(sig.return_annotation) is O: | |
outputs = sig.return_annotation | |
else: | |
outputs = [O(annot) for annot in sig.return_annotation] | |
self.app.callback(outputs, inputs)(fn) | |
def run(self, **kwargs): | |
self.app.run_server(**kwargs) | |
def __extract_content(st): | |
var, attr = st.split(".") | |
component = getattr(sys.modules['__main__'], var) | |
return component.id, attr | |
def I(st): | |
return Input(*__extract_content(st)) | |
def S(st): | |
return State(*__extract_content(st)) | |
def O(st): | |
return Output(*__extract_content(st)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import dash | |
import dash_core_components as dcc | |
import dash_html_components as html | |
import dash_bootstrap_components as dbc | |
import dash_express as dx | |
from dash_express import S | |
import plotly.express as px | |
import pandas as pd | |
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css'] | |
ui = dx.UserInterface(bootstrap=True) | |
df = pd.read_csv('https://plotly.github.io/datasets/country_indicators.csv') | |
available_indicators = df['Indicator Name'].unique() | |
# Define the components | |
xaxis_column = dcc.Dropdown( | |
options=[{'label': i, 'value': i} for i in available_indicators], | |
value='Fertility rate, total (births per woman)' | |
) | |
xaxis_type = dcc.RadioItems( | |
options=[{'label': i, 'value': i} for i in ['Linear', 'Log']], | |
value='Linear', | |
labelStyle={'display': 'inline-block'} | |
) | |
yaxis_column = dcc.Dropdown( | |
options=[{'label': i, 'value': i} for i in available_indicators], | |
value='Life expectancy at birth, total (years)' | |
) | |
yaxis_type = dcc.RadioItems( | |
options=[{'label': i, 'value': i} for i in ['Linear', 'Log']], | |
value='Linear', | |
labelStyle={'display': 'inline-block'} | |
) | |
year_slider = dcc.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 | |
) | |
indicator_graphic = dcc.Graph() | |
ui.add_row(xaxis_column, yaxis_column) | |
ui.add_row(xaxis_type, yaxis_type) | |
ui.add(indicator_graphic) | |
ui.add(year_slider) | |
def update_graph( | |
xaxis_column_name: 'xaxis_column.value', | |
yaxis_column_name: 'yaxis_column.value', | |
xaxis_type: 'xaxis_type.value', | |
yaxis_type: 'yaxis_type.value', | |
year_value: 'year_slider.value' | |
) -> 'indicator_graphic.figure': | |
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_layout(margin={'l': 40, 'b': 40, 't': 10, 'r': 0}, hovermode='closest') | |
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') | |
return fig | |
ui.add_func(update_graph) | |
if __name__ == '__main__': | |
ui.run(debug=True) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment