├── 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 | 
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 |
--------------------------------------------------------------------------------