-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
/
datatable_intro_and_sort.py
171 lines (147 loc) · 7.87 KB
/
datatable_intro_and_sort.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
import dash #(version 1.12.0)
from dash.dependencies import Input, Output
import dash_table
import dash_core_components as dcc
import dash_html_components as html
import plotly.express as px
import pandas as pd
# -------------------------------------------------------------------------------------
# Import the cleaned data (importing csv into pandas)
df = pd.read_csv("internet_cleaned.csv")
df = df[df['year'] == 2019]
# Creating an ID column name gives us more interactive capabilities
df['id'] = df['iso_alpha3']
df.set_index('id', inplace=True, drop=False)
print(df.columns)
# -------------------------------------------------------------------------------------
# App layout
app = dash.Dash(__name__, prevent_initial_callbacks=True) # this was introduced in Dash version 1.12.0
# Sorting operators (https://dash.plotly.com/datatable/filtering)
app.layout = html.Div([
dash_table.DataTable(
id='datatable-interactivity',
columns=[
{"name": i, "id": i, "deletable": True, "selectable": True, "hideable": True}
if i == "iso_alpha3" or i == "year" or i == "id"
else {"name": i, "id": i, "deletable": True, "selectable": True}
for i in df.columns
],
data=df.to_dict('records'), # the contents of the table
editable=True, # allow editing of data inside all cells
filter_action="native", # allow filtering of data by user ('native') or not ('none')
sort_action="native", # enables data to be sorted per-column by user or not ('none')
sort_mode="single", # sort across 'multi' or 'single' columns
column_selectable="multi", # allow users to select 'multi' or 'single' columns
row_selectable="multi", # allow users to select 'multi' or 'single' rows
row_deletable=True, # choose if user can delete a row (True) or not (False)
selected_columns=[], # ids of columns that user selects
selected_rows=[], # indices of rows that user selects
page_action="native", # all data is passed to the table up-front or not ('none')
page_current=0, # page number that user is on
page_size=6, # number of rows visible per page
style_cell={ # ensure adequate header width when text is shorter than cell's text
'minWidth': 95, 'maxWidth': 95, 'width': 95
},
style_cell_conditional=[ # align text columns to left. By default they are aligned to right
{
'if': {'column_id': c},
'textAlign': 'left'
} for c in ['country', 'iso_alpha3']
],
style_data={ # overflow cells' content into multiple lines
'whiteSpace': 'normal',
'height': 'auto'
}
),
html.Br(),
html.Br(),
html.Div(id='bar-container'),
html.Div(id='choromap-container')
])
# -------------------------------------------------------------------------------------
# Create bar chart
@app.callback(
Output(component_id='bar-container', component_property='children'),
[Input(component_id='datatable-interactivity', component_property="derived_virtual_data"),
Input(component_id='datatable-interactivity', component_property='derived_virtual_selected_rows'),
Input(component_id='datatable-interactivity', component_property='derived_virtual_selected_row_ids'),
Input(component_id='datatable-interactivity', component_property='selected_rows'),
Input(component_id='datatable-interactivity', component_property='derived_virtual_indices'),
Input(component_id='datatable-interactivity', component_property='derived_virtual_row_ids'),
Input(component_id='datatable-interactivity', component_property='active_cell'),
Input(component_id='datatable-interactivity', component_property='selected_cells')]
)
def update_bar(all_rows_data, slctd_row_indices, slct_rows_names, slctd_rows,
order_of_rows_indices, order_of_rows_names, actv_cell, slctd_cell):
print('***************************************************************************')
print('Data across all pages pre or post filtering: {}'.format(all_rows_data))
print('---------------------------------------------')
print("Indices of selected rows if part of table after filtering:{}".format(slctd_row_indices))
print("Names of selected rows if part of table after filtering: {}".format(slct_rows_names))
print("Indices of selected rows regardless of filtering results: {}".format(slctd_rows))
print('---------------------------------------------')
print("Indices of all rows pre or post filtering: {}".format(order_of_rows_indices))
print("Names of all rows pre or post filtering: {}".format(order_of_rows_names))
print("---------------------------------------------")
print("Complete data of active cell: {}".format(actv_cell))
print("Complete data of all selected cells: {}".format(slctd_cell))
dff = pd.DataFrame(all_rows_data)
# used to highlight selected countries on bar chart
colors = ['#7FDBFF' if i in slctd_row_indices else '#0074D9'
for i in range(len(dff))]
if "country" in dff and "did online course" in dff:
return [
dcc.Graph(id='bar-chart',
figure=px.bar(
data_frame=dff,
x="country",
y='did online course',
labels={"did online course": "% of Pop took online course"}
).update_layout(showlegend=False, xaxis={'categoryorder': 'total ascending'})
.update_traces(marker_color=colors, hovertemplate="<b>%{y}%</b><extra></extra>")
)
]
# -------------------------------------------------------------------------------------
# Create choropleth map
@app.callback(
Output(component_id='choromap-container', component_property='children'),
[Input(component_id='datatable-interactivity', component_property="derived_virtual_data"),
Input(component_id='datatable-interactivity', component_property='derived_virtual_selected_rows')]
)
def update_map(all_rows_data, slctd_row_indices):
dff = pd.DataFrame(all_rows_data)
# highlight selected countries on map
borders = [5 if i in slctd_row_indices else 1
for i in range(len(dff))]
if "iso_alpha3" in dff and "internet daily" in dff and "country" in dff:
return [
dcc.Graph(id='choropleth',
style={'height': 700},
figure=px.choropleth(
data_frame=dff,
locations="iso_alpha3",
scope="europe",
color="internet daily",
title="% of Pop that Uses Internet Daily",
template='plotly_dark',
hover_data=['country', 'internet daily'],
).update_layout(showlegend=False, title=dict(font=dict(size=28), x=0.5, xanchor='center'))
.update_traces(marker_line_width=borders, hovertemplate="<b>%{customdata[0]}</b><br><br>" +
"%{customdata[1]}" + "%")
)
]
# -------------------------------------------------------------------------------------
# Highlight selected column
@app.callback(
Output('datatable-interactivity', 'style_data_conditional'),
[Input('datatable-interactivity', 'selected_columns')]
)
def update_styles(selected_columns):
return [{
'if': {'column_id': i},
'background_color': '#D2F3FF'
} for i in selected_columns]
# -------------------------------------------------------------------------------------
if __name__ == '__main__':
app.run_server(debug=True)
# https://youtu.be/USTqY4gH_VM