├── Bootstrap-css.pptx ├── Table_Drill_Down ├── Brands.csv ├── dash_demo.gif ├── Models.csv ├── README.md ├── Sales.csv └── app_table.py ├── README.md ├── ex1a.py ├── ex1b.py ├── ex2.py ├── ex3.py ├── app.py ├── ex3b.py └── ex4.py /Bootstrap-css.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amyoshino/Dash_Tutorial_Series/HEAD/Bootstrap-css.pptx -------------------------------------------------------------------------------- /Table_Drill_Down/Brands.csv: -------------------------------------------------------------------------------- 1 | Brand,Models,Average Price 2 | Ford,2,25990 3 | Honda,3,23435 4 | Toyota,4,24228 5 | BMW,2,35920 -------------------------------------------------------------------------------- /Table_Drill_Down/dash_demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amyoshino/Dash_Tutorial_Series/HEAD/Table_Drill_Down/dash_demo.gif -------------------------------------------------------------------------------- /Table_Drill_Down/Models.csv: -------------------------------------------------------------------------------- 1 | Brand,Model,Price,Sales 2 | Ford,EcoSport,20990,20 3 | Ford,Edge,30990,15 4 | Honda,Accord,24640,23 5 | Honda,Civic,20370,23 6 | Honda,CRV,25295,21 7 | Toyota,CHR,21990,26 8 | Toyota,Camry,24765,16 9 | Toyota,Prius,24405,37 10 | Toyota,RAv4,25755,43 11 | BMW,2 Series,35945,45 12 | BMW,3 Series,35895,14 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dash_Tutorial_Series 2 | Series of videos to cover important topics in Plotly Dash framework for Fulcrum Analytics team. 3 | 4 | The source code for the YouTube video series is in this repo. 5 | - Video 01-Creating your first app: https://youtu.be/yPSbJSblrvw 6 | - Video 02 - Styling your app with Bootstrap: https://youtu.be/f2qUWgq7fb8 7 | - Video 03 - Making your app interactive by adding @callbacks: https://youtu.be/o5fgj1AIq4s 8 | - Video 04 - Plotly Dash Tutorial - Working with table and map: https://youtu.be/lu0PtsMor4E 9 | -------------------------------------------------------------------------------- /Table_Drill_Down/README.md: -------------------------------------------------------------------------------- 1 | ## Table Drill Down 2 | 3 | To drill down the information levels, click on the table cells. 3 levels are available in this mock up. 4 | 5 | Dependencies: 6 | - Pandas, Numpy 7 | - Dash: pip install dash==0.35.1 8 | - Dash Core Components: pip install dash-html-components==0.13.4 9 | - Dash html components: pip install dash-core-components==0.42.1 10 | - Dash tables: pip install dash-table==3.1.11 11 | 12 | more info on: https://dash.plot.ly/installation 13 | 14 | ![Alt Text](dash_demo.gif) 15 | -------------------------------------------------------------------------------- /Table_Drill_Down/Sales.csv: -------------------------------------------------------------------------------- 1 | Model,Date,x,y 2 | EcoSport,1/1/19,20,10 3 | EcoSport,1/2/19,1,11 4 | Edge,1/3/19,9,7 5 | Edge,1/4/19,17,9 6 | Edge,1/5/19,12,14 7 | Accord,1/6/19,14,7 8 | Accord,1/7/19,10,14 9 | Accord,1/8/19,5,13 10 | Accord,1/9/19,3,7 11 | Civic,1/10/19,5,5 12 | CRV,1/11/19,14,11 13 | CRV,1/12/19,14,9 14 | CHR,1/13/19,10,11 15 | CHR,1/14/19,20,10 16 | CHR,1/15/19,4,10 17 | Camry,1/16/19,3,12 18 | Camry,1/17/19,5,9 19 | Camry,1/18/19,1,7 20 | Prius,1/19/19,6,7 21 | Prius,1/20/19,15,10 22 | RAv4,1/21/19,1,6 23 | 2 Series,1/22/19,5,10 24 | 3 Series,1/23/19,14,7 25 | 3 Series,1/24/19,10,9 26 | 3 Series,1/25/19,8,9 27 | 3 Series,1/26/19,9,5 -------------------------------------------------------------------------------- /ex1a.py: -------------------------------------------------------------------------------- 1 | ## First Example 2 | 3 | # -*- coding: utf-8 -*- 4 | import dash 5 | import dash_core_components as dcc 6 | import dash_html_components as html 7 | 8 | app = dash.Dash() 9 | 10 | app.layout = html.Div( 11 | html.Div([ 12 | html.H1(children='Hello World'), 13 | 14 | html.Div(children=''' 15 | Dash: A web application framework for Python. 16 | '''), 17 | 18 | dcc.Graph( 19 | id='example-graph', 20 | figure={ 21 | 'data': [ 22 | {'x': [1, 2, 3], 'y': [4, 1, 2], 'type': 'bar', 'name': 'SF'}, 23 | {'x': [1, 2, 3], 'y': [2, 4, 5], 'type': 'bar', 'name': u'Montréal'}, 24 | ], 25 | 'layout': { 26 | 'title': 'Dash Data Visualization' 27 | } 28 | } 29 | ), 30 | 31 | ]) 32 | ) 33 | 34 | if __name__ == '__main__': 35 | app.run_server(debug=True) 36 | -------------------------------------------------------------------------------- /ex1b.py: -------------------------------------------------------------------------------- 1 | ## Adding one more component, no style yet 2 | 3 | # -*- coding: utf-8 -*- 4 | import dash 5 | import dash_core_components as dcc 6 | import dash_html_components as html 7 | 8 | app = dash.Dash() 9 | 10 | app.layout = html.Div( 11 | html.Div([ 12 | html.H1(children='Hello World'), 13 | 14 | html.Div(children=''' 15 | Dash: A web application framework for Python. 16 | '''), 17 | 18 | dcc.Graph( 19 | id='example-graph', 20 | figure={ 21 | 'data': [ 22 | {'x': [1, 2, 3], 'y': [4, 1, 2], 'type': 'bar', 'name': 'SF'}, 23 | {'x': [1, 2, 3], 'y': [2, 4, 5], 'type': 'bar', 'name': u'Montréal'}, 24 | ], 25 | 'layout': { 26 | 'title': 'Dash Data Visualization', 27 | 'xaxis' : dict( 28 | title='x Axis', 29 | titlefont=dict( 30 | family='Courier New, monospace', 31 | size=20, 32 | color='#7f7f7f' 33 | )), 34 | 'yaxis' : dict( 35 | title='y Axis', 36 | titlefont=dict( 37 | family='Helvetica, monospace', 38 | size=20, 39 | color='#7f7f7f' 40 | )) 41 | } 42 | } 43 | ), 44 | 45 | dcc.Graph( 46 | id='example-graph-2', 47 | figure={ 48 | 'data': [ 49 | {'x': [1, 2, 3], 'y': [4, 1, 2], 'type': 'line', 'name': 'SF'}, 50 | {'x': [1, 2, 3], 'y': [2, 9, 8], 'type': 'line', 'name': u'Montréal'}, 51 | ], 52 | 'layout': { 53 | 'title': 'Dash Data Visualization' 54 | } 55 | } 56 | ) 57 | 58 | ]) 59 | ) 60 | 61 | if __name__ == '__main__': 62 | app.run_server(debug=True) 63 | -------------------------------------------------------------------------------- /ex2.py: -------------------------------------------------------------------------------- 1 | ## Bootstrap Grid tutorial - adding style to the app 2 | 3 | # -*- coding: utf-8 -*- 4 | import dash 5 | import dash_core_components as dcc 6 | import dash_html_components as html 7 | 8 | app = dash.Dash() 9 | 10 | # Boostrap CSS. 11 | app.css.append_css({'external_url': 'https://codepen.io/amyoshino/pen/jzXypZ.css'}) # noqa: E501 12 | 13 | app.layout = html.Div( 14 | html.Div([ 15 | html.Div( 16 | [ 17 | html.H1(children='Hello World', 18 | className='nine columns'), 19 | html.Img( 20 | src="http://test.fulcrumanalytics.com/wp-content/uploads/2015/10/Fulcrum-logo_840X144.png", 21 | className='three columns', 22 | style={ 23 | 'height': '15%', 24 | 'width': '15%', 25 | 'float': 'right', 26 | 'position': 'relative', 27 | 'margin-top': 10, 28 | }, 29 | ), 30 | html.Div(children=''' 31 | Dash: A web application framework for Python. 32 | ''', 33 | className='nine columns' 34 | ) 35 | ], className="row" 36 | ), 37 | 38 | html.Div( 39 | [ 40 | html.Div([ 41 | dcc.Graph( 42 | id='example-graph', 43 | figure={ 44 | 'data': [ 45 | {'x': [1, 2, 3], 'y': [4, 1, 2], 'type': 'bar', 'name': 'SF'}, 46 | {'x': [1, 2, 3], 'y': [2, 4, 5], 'type': 'bar', 'name': u'Montréal'}, 47 | ], 48 | 'layout': { 49 | 'title': 'Graph 1', 50 | 'xaxis' : dict( 51 | title='x Axis', 52 | titlefont=dict( 53 | family='Courier New, monospace', 54 | size=20, 55 | color='#7f7f7f' 56 | )), 57 | 'yaxis' : dict( 58 | title='y Axis', 59 | titlefont=dict( 60 | family='Helvetica, monospace', 61 | size=20, 62 | color='#7f7f7f' 63 | )) 64 | } 65 | } 66 | ) 67 | ], className= 'six columns' 68 | ), 69 | 70 | html.Div([ 71 | dcc.Graph( 72 | id='example-graph-2', 73 | figure={ 74 | 'data': [ 75 | {'x': [1, 2, 3], 'y': [4, 1, 2], 'type': 'line', 'name': 'SF'}, 76 | {'x': [1, 2, 3], 'y': [2, 9, 8], 'type': 'line', 'name': u'Montréal'}, 77 | ], 78 | 'layout': { 79 | 'title': 'Graph 2' 80 | } 81 | } 82 | ) 83 | ], className= 'six columns' 84 | ) 85 | ], className="row" 86 | ) 87 | ], className='ten columns offset-by-one') 88 | ) 89 | 90 | if __name__ == '__main__': 91 | app.run_server(debug=True) 92 | -------------------------------------------------------------------------------- /ex3.py: -------------------------------------------------------------------------------- 1 | ## Introducing callbacks 2 | 3 | # -*- coding: utf-8 -*- 4 | import dash 5 | import dash_core_components as dcc 6 | import dash_html_components as html 7 | 8 | app = dash.Dash() 9 | 10 | # Boostrap CSS. 11 | app.css.append_css({'external_url': 'https://codepen.io/amyoshino/pen/jzXypZ.css'}) # noqa: E501 12 | 13 | app.layout = html.Div( 14 | html.Div([ 15 | html.Div( 16 | [ 17 | html.H1(children='Hello World', 18 | className='nine columns'), 19 | html.Img( 20 | src="http://test.fulcrumanalytics.com/wp-content/uploads/2015/10/Fulcrum-logo_840X144.png", 21 | className='three columns', 22 | style={ 23 | 'height': '9%', 24 | 'width': '9%', 25 | 'float': 'right', 26 | 'position': 'relative', 27 | 'margin-top': 10, 28 | }, 29 | ), 30 | html.Div(children=''' 31 | Dash: A web application framework for Python. 32 | ''', 33 | className='nine columns' 34 | ) 35 | ], className="row" 36 | ), 37 | 38 | html.Div( 39 | [ 40 | html.Div( 41 | [ 42 | html.P('Choose City:'), 43 | dcc.Checklist( 44 | id = 'Cities', 45 | options=[ 46 | {'label': 'San Francisco', 'value': 'SF'}, 47 | {'label': 'Montreal', 'value': 'MT'} 48 | ], 49 | values=['SF', 'MT'], 50 | labelStyle={'display': 'inline-block'} 51 | ), 52 | ], 53 | className='six columns', 54 | style={'margin-top': '10'} 55 | ), 56 | ], className="row" 57 | ), 58 | 59 | html.Div( 60 | [ 61 | html.Div([ 62 | dcc.Graph( 63 | id='example-graph' 64 | ) 65 | ], className= 'six columns' 66 | ), 67 | 68 | html.Div([ 69 | dcc.Graph( 70 | id='example-graph-2', 71 | figure={ 72 | 'data': [ 73 | {'x': [1, 2, 3], 'y': [4, 1, 2], 'type': 'line', 'name': 'SF'}, 74 | {'x': [1, 2, 3], 'y': [2, 9, 8], 'type': 'line', 'name': u'Montréal'}, 75 | ], 76 | 'layout': { 77 | 'title': 'Graph 2' 78 | } 79 | } 80 | ) 81 | ], className= 'six columns' 82 | ) 83 | ], className="row" 84 | ) 85 | ], className='ten columns offset-by-one') 86 | ) 87 | 88 | @app.callback( 89 | dash.dependencies.Output('example-graph', 'figure'), 90 | [dash.dependencies.Input('Cities', 'values')]) 91 | def update_image_src(selector): 92 | data = [] 93 | if 'SF' in selector: 94 | data.append({'x': [1, 2, 3], 'y': [4, 1, 2], 'type': 'bar', 'name': 'SF'}) 95 | if 'MT' in selector: 96 | data.append({'x': [1, 2, 3], 'y': [2, 4, 5], 'type': 'bar', 'name': u'Montréal'}) 97 | figure = { 98 | 'data': data, 99 | 'layout': { 100 | 'title': 'Graph 1', 101 | 'xaxis' : dict( 102 | title='x Axis', 103 | titlefont=dict( 104 | family='Courier New, monospace', 105 | size=20, 106 | color='#7f7f7f' 107 | )), 108 | 'yaxis' : dict( 109 | title='y Axis', 110 | titlefont=dict( 111 | family='Helvetica, monospace', 112 | size=20, 113 | color='#7f7f7f' 114 | )) 115 | } 116 | } 117 | return figure 118 | 119 | @app.callback( 120 | dash.dependencies.Output('example-graph-2', 'figure'), 121 | [dash.dependencies.Input('Cities', 'values')]) 122 | def update_image_src(selector): 123 | data = [] 124 | if 'SF' in selector: 125 | data.append({'x': [1, 2, 3], 'y': [4, 1, 2], 'type': 'line', 'name': 'SF'}) 126 | if 'MT' in selector: 127 | data.append({'x': [1, 2, 3], 'y': [2, 4, 5], 'type': 'line', 'name': u'Montréal'}) 128 | figure = { 129 | 'data': data, 130 | 'layout': { 131 | 'title': 'Graph 2', 132 | 'xaxis' : dict( 133 | title='x Axis', 134 | titlefont=dict( 135 | family='Courier New, monospace', 136 | size=20, 137 | color='#7f7f7f' 138 | )), 139 | 'yaxis' : dict( 140 | title='y Axis', 141 | titlefont=dict( 142 | family='Helvetica, monospace', 143 | size=20, 144 | color='#7f7f7f' 145 | )) 146 | } 147 | } 148 | return figure 149 | 150 | if __name__ == '__main__': 151 | app.run_server(debug=True) 152 | -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | ## Plotly Dash Tutorial 2 | 3 | # -*- coding: utf-8 -*- 4 | import dash 5 | import dash_core_components as dcc 6 | import dash_html_components as html 7 | 8 | app = dash.Dash() 9 | 10 | all_options = { 11 | 'America': ['New York City', 'San Francisco', 'Cincinnati'], 12 | 'Canada': [u'Montreal', 'Toronto', 'Ottawa'], 13 | 'All': ['New York City', 'San Francisco', 'Cincinnati', u'Montreal', 'Toronto', 'Ottawa'] 14 | } 15 | 16 | city_data = { 17 | 'San Francisco': {'x': [1, 2, 3], 'y': [4, 1, 2]}, 18 | 'Montreal': {'x': [1, 2, 3], 'y': [2, 4, 5]}, 19 | 'New York City': {'x': [1, 2, 3], 'y': [2, 2, 7]}, 20 | 'Cincinnati': {'x': [1, 2, 3], 'y': [1, 0, 2]}, 21 | 'Toronto': {'x': [1, 2, 3], 'y': [4, 7, 3]}, 22 | 'Ottawa': {'x': [1, 2, 3], 'y': [2, 3, 3]} 23 | } 24 | 25 | app.title = 'Dash Tutorial' 26 | 27 | # Boostrap CSS. 28 | app.css.append_css({'external_url': 'https://codepen.io/amyoshino/pen/jzXypZ.css'}) 29 | 30 | app.layout = html.Div( 31 | html.Div([ 32 | html.Div([ 33 | html.H1(children='Hello World', 34 | className = "nine columns"), 35 | html.Img( 36 | src="http://test.fulcrumanalytics.com/wp-content/uploads/2015/10/Fulcrum-logo_840X144.png", 37 | className='three columns', 38 | style={ 39 | 'height': '14%', 40 | 'width': '14%', 41 | 'float': 'right', 42 | 'position': 'relative', 43 | 'margin-top': 20, 44 | 'margin-right': 20 45 | }, 46 | ), 47 | html.Div(children=''' 48 | Dash: A web application framework for Python. 49 | ''', 50 | className = 'nine columns') 51 | ], className = "row"), 52 | 53 | html.Div( 54 | [ 55 | html.Div( 56 | [ 57 | html.P('Choose City:'), 58 | dcc.Checklist( 59 | id = 'Cities', 60 | values=['San Francisco'], 61 | labelStyle={'display': 'inline-block'} 62 | ), 63 | ], 64 | className='six columns', 65 | style={'margin-top': '10'} 66 | ), 67 | html.Div( 68 | [ 69 | html.P('Choose Country:'), 70 | dcc.RadioItems( 71 | id = 'Country', 72 | options=[{'label': k, 'value': k} for k in all_options.keys()], 73 | value='All', 74 | labelStyle={'display': 'inline-block'} 75 | ), 76 | ], 77 | className='six columns', 78 | style={'margin-top': '10'} 79 | ) 80 | ], className="row" 81 | ), 82 | 83 | html.Div([ 84 | html.Div([ 85 | dcc.Graph( 86 | id='example-graph' 87 | ) 88 | ], className = 'six columns'), 89 | html.Div([ 90 | dcc.Graph( 91 | id='example-graph-2' 92 | ) 93 | ], className = "six columns") 94 | ], className = "row") 95 | ], className='ten columns offset-by-one') 96 | ) 97 | 98 | @app.callback( 99 | dash.dependencies.Output('Cities', 'options'), 100 | [dash.dependencies.Input('Country', 'value')]) 101 | def set_cities_options(selected_country): 102 | return [{'label': i, 'value': i} for i in all_options[selected_country]] 103 | 104 | @app.callback( 105 | dash.dependencies.Output('example-graph', 'figure'), 106 | [dash.dependencies.Input('Cities', 'values')]) 107 | def update_graph_src(selector): 108 | data = [] 109 | for city in selector: 110 | data.append({'x': city_data[city]['x'], 'y': city_data[city]['y'], 111 | 'type': 'bar', 'name': city}) 112 | figure = { 113 | 'data': data, 114 | 'layout': { 115 | 'title': 'Graph 1', 116 | 'xaxis' : dict( 117 | title='x Axis', 118 | titlefont=dict( 119 | family='Courier New, monospace', 120 | size=20, 121 | color='#7f7f7f' 122 | )), 123 | 'yaxis' : dict( 124 | title='y Axis', 125 | titlefont=dict( 126 | family='Helvetica, monospace', 127 | size=20, 128 | color='#7f7f7f' 129 | )) 130 | } 131 | } 132 | return figure 133 | 134 | @app.callback( 135 | dash.dependencies.Output('example-graph-2', 'figure'), 136 | [dash.dependencies.Input('Cities', 'values')]) 137 | def update_graph_src(selector): 138 | data = [] 139 | for city in selector: 140 | data.append({'x': city_data[city]['x'], 'y': city_data[city]['y'], 141 | 'type': 'line', 'name': city}) 142 | figure = { 143 | 'data': data, 144 | 'layout': { 145 | 'title': 'Graph 1', 146 | 'xaxis' : dict( 147 | title='x Axis', 148 | titlefont=dict( 149 | family='Courier New, monospace', 150 | size=20, 151 | color='#7f7f7f' 152 | )), 153 | 'yaxis' : dict( 154 | title='y Axis', 155 | titlefont=dict( 156 | family='Helvetica, monospace', 157 | size=20, 158 | color='#7f7f7f' 159 | )) 160 | } 161 | } 162 | return figure 163 | 164 | if __name__ == '__main__': 165 | app.run_server(debug=True) 166 | -------------------------------------------------------------------------------- /ex3b.py: -------------------------------------------------------------------------------- 1 | ## Evolving from the basics 2 | 3 | # -*- coding: utf-8 -*- 4 | import dash 5 | import dash_core_components as dcc 6 | import dash_html_components as html 7 | 8 | app = dash.Dash() 9 | 10 | all_options = { 11 | 'America': ['New York City', 'San Francisco', 'Cincinnati'], 12 | 'Canada': [u'Montreal', 'Toronto', 'Ottawa'], 13 | 'All': ['New York City', 'San Francisco', 'Cincinnati', u'Montreal', 'Toronto', 'Ottawa'] 14 | } 15 | 16 | city_data = { 17 | 'San Francisco': {'x': [1, 2, 3], 'y': [4, 1, 2]}, 18 | 'Montreal': {'x': [1, 2, 3], 'y': [2, 4, 5]}, 19 | 'New York City': {'x': [1, 2, 3], 'y': [2, 2, 7]}, 20 | 'Cincinnati': {'x': [1, 2, 3], 'y': [1, 0, 2]}, 21 | 'Toronto': {'x': [1, 2, 3], 'y': [4, 7, 3]}, 22 | 'Ottawa': {'x': [1, 2, 3], 'y': [2, 3, 3]} 23 | } 24 | 25 | # Boostrap CSS. 26 | app.css.append_css({'external_url': 'https://codepen.io/amyoshino/pen/jzXypZ.css'}) # noqa: E501 27 | 28 | app.layout = html.Div( 29 | html.Div([ 30 | html.Div( 31 | [ 32 | html.H1(children='Hello World', 33 | className='nine columns'), 34 | html.Img( 35 | src="http://test.fulcrumanalytics.com/wp-content/uploads/2015/10/Fulcrum-logo_840X144.png", 36 | className='three columns', 37 | style={ 38 | 'height': '9%', 39 | 'width': '9%', 40 | 'float': 'right', 41 | 'position': 'relative', 42 | 'padding-top': 0, 43 | 'padding-right': 0 44 | }, 45 | ), 46 | html.Div(children=''' 47 | Dash: A web application framework for Python. 48 | ''', 49 | className='nine columns' 50 | ) 51 | ], className="row" 52 | ), 53 | 54 | html.Div( 55 | [ 56 | html.Div( 57 | [ 58 | html.P('Choose City:'), 59 | dcc.Checklist( 60 | id = 'Cities', 61 | options=[ 62 | {'label': 'San Francisco', 'value': 'San Francisco'}, 63 | {'label': 'Montreal', 'value': 'Montreal'} 64 | ], 65 | values=['San Francisco', 'Montreal'], 66 | labelStyle={'display': 'inline-block'} 67 | ), 68 | ], 69 | className='six columns', 70 | style={'margin-top': '10'} 71 | ), 72 | html.Div( 73 | [ 74 | html.P('Choose Country:'), 75 | dcc.RadioItems( 76 | id = 'Country', 77 | options=[{'label': k, 'value': k} for k in all_options.keys()], 78 | value='All', 79 | labelStyle={'display': 'inline-block'} 80 | ), 81 | ], 82 | className='six columns', 83 | style={'margin-top': '10'} 84 | ) 85 | ], className="row" 86 | ), 87 | 88 | html.Div( 89 | [ 90 | html.Div([ 91 | dcc.Graph( 92 | id='example-graph' 93 | ) 94 | ], className= 'six columns' 95 | ), 96 | 97 | html.Div([ 98 | dcc.Graph( 99 | id='example-graph-2' 100 | ) 101 | ], className= 'six columns' 102 | ) 103 | ], className="row" 104 | ) 105 | ], className='ten columns offset-by-one') 106 | ) 107 | @app.callback( 108 | dash.dependencies.Output('Cities', 'options'), 109 | [dash.dependencies.Input('Country', 'value')]) 110 | def set_cities_options(selected_country): 111 | return [{'label': i, 'value': i} for i in all_options[selected_country]] 112 | 113 | @app.callback( 114 | dash.dependencies.Output('example-graph', 'figure'), 115 | [dash.dependencies.Input('Cities', 'values')]) 116 | def update_image_src(selector): 117 | data = [] 118 | for city in selector: 119 | data.append({'x': city_data[city]['x'], 'y': city_data[city]['y'], 120 | 'type': 'bar', 'name': city}) 121 | figure = { 122 | 'data': data, 123 | 'layout': { 124 | 'title': 'Graph 1', 125 | 'xaxis' : dict( 126 | title='x Axis', 127 | titlefont=dict( 128 | family='Courier New, monospace', 129 | size=20, 130 | color='#7f7f7f' 131 | )), 132 | 'yaxis' : dict( 133 | title='y Axis', 134 | titlefont=dict( 135 | family='Helvetica, monospace', 136 | size=20, 137 | color='#7f7f7f' 138 | )) 139 | } 140 | } 141 | return figure 142 | 143 | @app.callback( 144 | dash.dependencies.Output('example-graph-2', 'figure'), 145 | [dash.dependencies.Input('Cities', 'values')]) 146 | def update_image_src(selector): 147 | data = [] 148 | for city in selector: 149 | data.append({'x': city_data[city]['x'], 'y': city_data[city]['y'], 150 | 'type': 'line', 'name': city}) 151 | figure = { 152 | 'data': data, 153 | 'layout': { 154 | 'title': 'Graph 2', 155 | 'xaxis' : dict( 156 | title='x Axis', 157 | titlefont=dict( 158 | family='Courier New, monospace', 159 | size=20, 160 | color='#7f7f7f' 161 | )), 162 | 'yaxis' : dict( 163 | title='y Axis', 164 | titlefont=dict( 165 | family='Helvetica, monospace', 166 | size=20, 167 | color='#7f7f7f' 168 | )) 169 | } 170 | } 171 | return figure 172 | 173 | if __name__ == '__main__': 174 | app.run_server(debug=True) 175 | -------------------------------------------------------------------------------- /ex4.py: -------------------------------------------------------------------------------- 1 | ## Evolving from the basics 2 | 3 | # -*- coding: utf-8 -*- 4 | import dash 5 | import dash_core_components as dcc 6 | import dash_html_components as html 7 | import dash_table_experiments as dt 8 | import pandas as pd 9 | 10 | from plotly import graph_objs as go 11 | from plotly.graph_objs import * 12 | from dash.dependencies import Input, Output, State, Event 13 | 14 | app = dash.Dash(__name__) 15 | server = app.server 16 | app.title = 'NYC Wi-Fi Hotspots' 17 | 18 | # API keys and datasets 19 | mapbox_access_token = 'USE YOUR MAPBOX KEY HERE' 20 | map_data = pd.read_csv("nyc-wi-fi-hotspot-locations.csv") 21 | 22 | # Selecting only required columns 23 | map_data = map_data[["Borough", "Type", "Provider", "Name", "Location", "Latitude", "Longitude"]].drop_duplicates() 24 | 25 | # Boostrap CSS. 26 | app.css.append_css({'external_url': 'https://codepen.io/amyoshino/pen/jzXypZ.css'}) 27 | 28 | # Layouts 29 | layout_table = dict( 30 | autosize=True, 31 | height=500, 32 | font=dict(color="#191A1A"), 33 | titlefont=dict(color="#191A1A", size='14'), 34 | margin=dict( 35 | l=35, 36 | r=35, 37 | b=35, 38 | t=45 39 | ), 40 | hovermode="closest", 41 | plot_bgcolor='#fffcfc', 42 | paper_bgcolor='#fffcfc', 43 | legend=dict(font=dict(size=10), orientation='h'), 44 | ) 45 | layout_table['font-size'] = '12' 46 | layout_table['margin-top'] = '20' 47 | 48 | layout_map = dict( 49 | autosize=True, 50 | height=500, 51 | font=dict(color="#191A1A"), 52 | titlefont=dict(color="#191A1A", size='14'), 53 | margin=dict( 54 | l=35, 55 | r=35, 56 | b=35, 57 | t=45 58 | ), 59 | hovermode="closest", 60 | plot_bgcolor='#fffcfc', 61 | paper_bgcolor='#fffcfc', 62 | legend=dict(font=dict(size=10), orientation='h'), 63 | title='WiFi Hotspots in NYC', 64 | mapbox=dict( 65 | accesstoken=mapbox_access_token, 66 | style="light", 67 | center=dict( 68 | lon=-73.91251, 69 | lat=40.7342 70 | ), 71 | zoom=10, 72 | ) 73 | ) 74 | 75 | # functions 76 | def gen_map(map_data): 77 | # groupby returns a dictionary mapping the values of the first field 78 | # 'classification' onto a list of record dictionaries with that 79 | # classification value. 80 | return { 81 | "data": [{ 82 | "type": "scattermapbox", 83 | "lat": list(map_data['Latitude']), 84 | "lon": list(map_data['Longitude']), 85 | "hoverinfo": "text", 86 | "hovertext": [["Name: {}
Type: {}
Provider: {}".format(i,j,k)] 87 | for i,j,k in zip(map_data['Name'], map_data['Type'],map_data['Provider'])], 88 | "mode": "markers", 89 | "name": list(map_data['Name']), 90 | "marker": { 91 | "size": 6, 92 | "opacity": 0.7 93 | } 94 | }], 95 | "layout": layout_map 96 | } 97 | 98 | app.layout = html.Div( 99 | html.Div([ 100 | html.Div( 101 | [ 102 | html.H1(children='Maps and Tables', 103 | className='nine columns'), 104 | html.Img( 105 | src="https://www.fulcrumanalytics.com/wp-content/uploads/2017/12/cropped-site-logo-1.png", 106 | className='three columns', 107 | style={ 108 | 'height': '16%', 109 | 'width': '16%', 110 | 'float': 'right', 111 | 'position': 'relative', 112 | 'padding-top': 12, 113 | 'padding-right': 0 114 | }, 115 | ), 116 | html.Div(children=''' 117 | Dash Tutorial video 04: Working with tables and maps. 118 | ''', 119 | className='nine columns' 120 | ) 121 | ], className="row" 122 | ), 123 | 124 | # Selectors 125 | html.Div( 126 | [ 127 | html.Div( 128 | [ 129 | html.P('Choose Borroughs:'), 130 | dcc.Checklist( 131 | id = 'boroughs', 132 | options=[ 133 | {'label': 'Manhattan', 'value': 'MN'}, 134 | {'label': 'Bronx', 'value': 'BX'}, 135 | {'label': 'Queens', 'value': 'QU'}, 136 | {'label': 'Brooklyn', 'value': 'BK'}, 137 | {'label': 'Staten Island', 'value': 'SI'} 138 | ], 139 | values=['MN', 'BX', "QU", 'BK', 'SI'], 140 | labelStyle={'display': 'inline-block'} 141 | ), 142 | ], 143 | className='six columns', 144 | style={'margin-top': '10'} 145 | ), 146 | html.Div( 147 | [ 148 | html.P('Type:'), 149 | dcc.Dropdown( 150 | id='type', 151 | options= [{'label': str(item), 152 | 'value': str(item)} 153 | for item in set(map_data['Type'])], 154 | multi=True, 155 | value=list(set(map_data['Type'])) 156 | ) 157 | ], 158 | className='six columns', 159 | style={'margin-top': '10'} 160 | ) 161 | ], 162 | className='row' 163 | ), 164 | 165 | # Map + table + Histogram 166 | html.Div( 167 | [ 168 | html.Div( 169 | [ 170 | dcc.Graph(id='map-graph', 171 | animate=True, 172 | style={'margin-top': '20'}) 173 | ], className = "six columns" 174 | ), 175 | html.Div( 176 | [ 177 | dt.DataTable( 178 | rows=map_data.to_dict('records'), 179 | columns=map_data.columns, 180 | row_selectable=True, 181 | filterable=True, 182 | sortable=True, 183 | selected_row_indices=[], 184 | id='datatable'), 185 | ], 186 | style = layout_table, 187 | className="six columns" 188 | ), 189 | html.Div([ 190 | dcc.Graph( 191 | id='bar-graph' 192 | ) 193 | ], className= 'twelve columns' 194 | ), 195 | html.Div( 196 | [ 197 | html.P('Developed by Adriano M. Yoshino - ', style = {'display': 'inline'}), 198 | html.A('amyoshino@nyu.edu', href = 'mailto:amyoshino@nyu.edu') 199 | ], className = "twelve columns", 200 | style = {'fontSize': 18, 'padding-top': 20} 201 | ) 202 | ], className="row" 203 | ) 204 | ], className='ten columns offset-by-one')) 205 | 206 | @app.callback( 207 | Output('map-graph', 'figure'), 208 | [Input('datatable', 'rows'), 209 | Input('datatable', 'selected_row_indices')]) 210 | def map_selection(rows, selected_row_indices): 211 | aux = pd.DataFrame(rows) 212 | temp_df = aux.ix[selected_row_indices, :] 213 | if len(selected_row_indices) == 0: 214 | return gen_map(aux) 215 | return gen_map(temp_df) 216 | 217 | @app.callback( 218 | Output('datatable', 'rows'), 219 | [Input('type', 'value'), 220 | Input('boroughs', 'values')]) 221 | def update_selected_row_indices(type, borough): 222 | map_aux = map_data.copy() 223 | 224 | # Type filter 225 | map_aux = map_aux[map_aux['Type'].isin(type)] 226 | # Boroughs filter 227 | map_aux = map_aux[map_aux["Borough"].isin(borough)] 228 | 229 | rows = map_aux.to_dict('records') 230 | return rows 231 | 232 | @app.callback( 233 | Output('bar-graph', 'figure'), 234 | [Input('datatable', 'rows'), 235 | Input('datatable', 'selected_row_indices')]) 236 | def update_figure(rows, selected_row_indices): 237 | dff = pd.DataFrame(rows) 238 | 239 | layout = go.Layout( 240 | bargap=0.05, 241 | bargroupgap=0, 242 | barmode='group', 243 | showlegend=False, 244 | dragmode="select", 245 | xaxis=dict( 246 | showgrid=False, 247 | nticks=50, 248 | fixedrange=False 249 | ), 250 | yaxis=dict( 251 | showticklabels=True, 252 | showgrid=False, 253 | fixedrange=False, 254 | rangemode='nonnegative', 255 | zeroline='hidden' 256 | ) 257 | ) 258 | 259 | data = Data([ 260 | go.Bar( 261 | x=dff.groupby('Borough', as_index = False).count()['Borough'], 262 | y=dff.groupby('Borough', as_index = False).count()['Type'] 263 | ) 264 | ]) 265 | 266 | return go.Figure(data=data, layout=layout) 267 | 268 | if __name__ == '__main__': 269 | app.run_server(debug=True) 270 | -------------------------------------------------------------------------------- /Table_Drill_Down/app_table.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import copy 3 | import dash 4 | import dash_core_components as dcc 5 | import dash_html_components as html 6 | import dash_table as dt 7 | import numpy as np 8 | import os 9 | import pandas as pd 10 | import plotly 11 | import time 12 | 13 | from dash.exceptions import PreventUpdate 14 | from dash.dependencies import Input, Output, State, Event 15 | from flask import Flask 16 | from plotly import graph_objs as go 17 | from plotly.graph_objs import * 18 | 19 | 20 | app = dash.Dash(__name__) 21 | server = app.server 22 | 23 | # Datasets 24 | brands = pd.read_csv('Brands.csv') 25 | models = pd.read_csv('Models.csv') 26 | sales = pd.read_csv('Sales.csv') 27 | 28 | # Boostrap CSS. 29 | app.css.append_css({'external_url': 'https://codepen.io/amyoshino/pen/jzXypZ.css'}) 30 | 31 | layout = dict( 32 | autosize=True, 33 | height=450, 34 | font=dict(color="#191A1A"), 35 | titlefont=dict(color="#191A1A", size='14'), 36 | margin=dict( 37 | l=45, 38 | r=15, 39 | b=45, 40 | t=35 41 | ) 42 | ) 43 | 44 | # Layout 45 | app.layout = html.Div([ 46 | # Title - Row 47 | html.Div( 48 | [ 49 | html.H1( 50 | 'Test App', 51 | style={'font-family': 'Helvetica', 52 | "margin-left": "20", 53 | "margin-bottom": "0"}, 54 | className='eight columns', 55 | ) 56 | ], 57 | className='row' 58 | ), 59 | 60 | #block 2 61 | html.Div([ 62 | dcc.Store(id = 'memory'), 63 | html.H3('Cars'), 64 | html.Div( 65 | [ 66 | html.Div( 67 | [ 68 | html.P('Models:'), 69 | dcc.Dropdown( 70 | id = 'filter_x', 71 | options=[ 72 | {'label': 'No filter', 'value': 0}, 73 | {'label': '2', 'value': 1}, 74 | {'label': '3', 'value': 2}, 75 | {'label': '4', 'value': 3} 76 | ], 77 | value='0' 78 | ), 79 | ], 80 | className='three columns', 81 | style={'margin-top': '10'} 82 | ), 83 | html.Div( 84 | [ 85 | html.P('Price:'), 86 | dcc.Dropdown( 87 | id = 'filter_y', 88 | options=[ 89 | {'label': 'No filter', 'value': 0}, 90 | {'label': '1 to 20k', 'value': 1}, 91 | {'label': '20k to 30k', 'value': 2}, 92 | {'label': '30k+', 'value': 3} 93 | ], 94 | value='0' 95 | ) 96 | ], 97 | className='three columns', 98 | style={'margin-top': '10'} 99 | ), 100 | html.Div( 101 | [ 102 | html.Button('Reset Chart', id='button_chart') 103 | ], 104 | className='one columns', 105 | style={'margin-top': '40'} 106 | ), 107 | html.Div( 108 | [ 109 | html.Button('Previous Level', id='back_button') 110 | ], 111 | className='one columns', 112 | style={'margin-top': '40', 'margin-left':'50'} 113 | ) 114 | ], 115 | className='row' 116 | ), 117 | 118 | html.Div( 119 | [ 120 | html.Div( 121 | [ 122 | dcc.Graph(id='chart-2') 123 | ], className = "four columns", style = {'margin-top': 35, 124 | 'padding': '15', 125 | 'border': '1px solid #C6CCD5'} 126 | ), 127 | html.Div(id = 'table-box'), 128 | html.Div(dt.DataTable(id = 'table', data=[{}]), style={'display': 'none'}) 129 | ], className = 'row' 130 | ) 131 | ], className = 'row', style = {'margin-top': 20, 'border': 132 | '1px solid #C6CCD5', 'padding': 15, 133 | 'border-radius': '5px'}) 134 | ], style = {'padding': '25px'}) 135 | 136 | #Table function 137 | def make_table(data, output): 138 | return html.Div( 139 | [ 140 | dt.DataTable( 141 | id = output, 142 | data=data.to_dict('rows'), 143 | columns=[{'id': c, 'name': c} for c in data.columns], 144 | style_as_list_view=True, 145 | filtering=False, 146 | selected_rows=[], 147 | style_cell={'padding': '5px', 148 | 'whiteSpace': 'no-wrap', 149 | 'overflow': 'hidden', 150 | 'textOverflow': 'ellipsis', 151 | 'maxWidth': 0, 152 | 'height': 30, 153 | 'textAlign': 'left'}, 154 | style_header={ 155 | 'backgroundColor': 'white', 156 | 'fontWeight': 'bold', 157 | 'color': 'black' 158 | }, 159 | style_cell_conditional=[], 160 | virtualization=True, 161 | pagination_mode=False, 162 | n_fixed_rows=1 163 | ), 164 | ], className="seven columns", style = {'margin-top': '35', 165 | 'margin-left': '15', 166 | 'border': '1px solid #C6CCD5'} 167 | ) 168 | 169 | def make_chart(df, x, y, label = 'Author', size = 'Size'): 170 | graph = [] 171 | if size == '': 172 | s = 15 173 | else: 174 | s = df[size] 175 | graph.append(go.Scatter( 176 | x=df[x], 177 | y=df[y], 178 | mode='markers', 179 | text = ['{}: {}'.format(label, a) for a in df[label]], 180 | opacity=0.7, 181 | marker={ 182 | 'size': s, 183 | 'line': {'width': 0.5, 'color': 'white'} 184 | }, 185 | name='X' 186 | )) 187 | 188 | return graph 189 | 190 | # Callbacks and functions 191 | @app.callback(dash.dependencies.Output('memory', 'data'), 192 | [dash.dependencies.Input('table', 'selected_cells'), 193 | dash.dependencies.Input('table', 'derived_virtual_data')], 194 | [dash.dependencies.State('memory', 'data')]) 195 | def tab(sel, table, state): 196 | # to initialize variables when it is None 197 | if state is None: 198 | state = {} 199 | if table is None: 200 | state['data'] = brands.to_dict('records') 201 | table = [{}] 202 | else: 203 | state['data'] = table #save current table value afer it gets initialized 204 | 205 | # store information of selected rows to retrieve them when back button is clicked 206 | # information is stored in json format 207 | # 208 | if sel: 209 | if 'Brand' in table[0].keys(): 210 | state['Brand'] = table[0]['Brand'] 211 | if 'Model' in table[0].keys() and table is not None: 212 | state['Model'] = table[0]['Model'] 213 | 214 | return state 215 | 216 | @app.callback( 217 | dash.dependencies.Output('table-box', 'children'), 218 | [dash.dependencies.Input('filter_x', 'value'), 219 | dash.dependencies.Input('filter_y', 'value'), 220 | dash.dependencies.Input('button_chart', 'n_clicks_timestamp'), 221 | dash.dependencies.Input('back_button', 'n_clicks_timestamp'), 222 | dash.dependencies.Input('table', 'selected_cells')], 223 | [dash.dependencies.State('memory', 'data')]) 224 | def update_image_src(fx, fy, button, back, selected_cell, current_table): 225 | res = brands.copy() 226 | if fx == 1: 227 | res = res[res['Models'] == 2] 228 | if fx == 2: 229 | res = res[res['Models'] == 3] 230 | if fx == 3: 231 | res = res[res['Models'] == 4] 232 | if fy == 1: 233 | res = res[(res['Average Price'] >= 1) & (res['Average Price'] <= 20000)] 234 | if fy == 2: 235 | res = res[(res['Average Price'] >= 20001) & (res['Average Price'] <= 30000)] 236 | if fy == 3: 237 | res = res[res['Average Price'] >= 30001] 238 | 239 | # Reset Chart Button conditionals 240 | # stamp: actual timestamp 241 | # button: timestamp of button click 242 | # if stamp == button then there's a new click. The str transformation was 243 | # necessary as time.time() returns 10 digits and button 13 digits 244 | # ex.: time.time() --> 1548657188 button -->1548657188440 245 | if button is None: 246 | button = 0 247 | stamp = str(time.time())[:10] 248 | if stamp == str(button)[:10]: 249 | return make_table(res, 'table') 250 | 251 | # Retrieves data saved in browser memory to remember previous level selection 252 | # then apply to previous level dataset 253 | # ex.: if select Honda --> Civic --> back button, when back button is clicked 254 | # it will remember to show only Honda cars 255 | if back is None: 256 | back = 0 257 | stamp = str(time.time())[:10] 258 | if stamp == str(back)[:10]: 259 | if 'Price' in current_table['data'][0].keys(): 260 | return make_table(res, 'table') 261 | if 'Date' in current_table['data'][0].keys(): 262 | return make_table(models[models['Brand'] == current_table['Brand']], 'table') 263 | 264 | # When selection occurs, the code looks for the current table and based on a 265 | # differentiator column (unique among all datasets) it decides the next level table 266 | # ex.: if Average Price is in current table columns, then current table is "brands" 267 | # and next table is "models" 268 | if selected_cell: 269 | print(current_table) 270 | if 'Average Price' in current_table['data'][0].keys(): 271 | res = models[models['Brand'] == current_table['data'][list(selected_cell)[0][0]]['Brand']] 272 | if 'Price' in current_table['data'][0].keys(): 273 | res = sales[sales['Model'] == current_table['data'][list(selected_cell)[0][0]]['Model']] 274 | if 'Date' in current_table['data'][0].keys(): 275 | raise PreventUpdate 276 | 277 | return make_table(res, 'table') 278 | 279 | @app.callback( 280 | dash.dependencies.Output('chart-2', 'figure'), 281 | [dash.dependencies.Input('table', 'data')]) 282 | def update_image_src(data): 283 | layout_individual = copy.deepcopy(layout) 284 | layout_individual['legend'] = legend=dict(x=0.05, y=1) 285 | 286 | df = pd.DataFrame(data) 287 | graph = [] 288 | 289 | # The callback retrieve the new data after click and based on its columns, 290 | # we decide the x axis, y axis, label and size of dots to pass to make_chart() 291 | if 'Average Price' in data[0].keys(): 292 | layout_individual['title'] = 'Chart XYZ' 293 | layout_individual['xaxis'] = dict(title='Models') 294 | layout_individual['yaxis'] = dict(title='Average Price') 295 | graph = make_chart(pd.DataFrame(data), 'Models', 'Average Price', 'Brand', '') 296 | 297 | if 'Price' in data[0].keys(): 298 | layout_individual['title'] = 'Chart XYZ 2' 299 | layout_individual['xaxis'] = dict(title='Price') 300 | layout_individual['yaxis'] = dict(title='Sales') 301 | graph = make_chart(pd.DataFrame(data), 'Price', 'Sales', 'Model', 'Sales') 302 | 303 | if 'Date' in data[0].keys(): 304 | layout_individual['title'] = 'Chart XYZ 3' 305 | layout_individual['xaxis'] = dict(title='X') 306 | layout_individual['yaxis'] = dict(title='Y') 307 | graph = make_chart(pd.DataFrame(data), 'x', 'y', 'Model', '') 308 | 309 | figure = { 310 | 'data': graph, 311 | 'layout': layout_individual 312 | } 313 | 314 | return figure 315 | 316 | if __name__ == '__main__': 317 | app.run_server(debug=True) 318 | --------------------------------------------------------------------------------