Kenzabad commited on
Commit
c34dc73
1 Parent(s): ece1ea2

Upload my_dashboard.py

Browse files
Files changed (1) hide show
  1. my_dashboard.py +307 -0
my_dashboard.py ADDED
@@ -0,0 +1,307 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+ # coding: utf-8
3
+
4
+ # In[13]:
5
+
6
+
7
+ import altair as alt
8
+ import pandas as pd
9
+ import panel as pn
10
+
11
+ # Load the Panel extension
12
+
13
+ pn.extension('vega')
14
+
15
+
16
+ # Load the dataset
17
+ data = pd.read_csv("/Users/kenzabaddou/Downloads/archive/marketing_campaign.csv", sep=";")
18
+
19
+ # Data cleaning
20
+ data = data.rename(columns=lambda x: x.strip()) # Remove leading and trailing spaces from column names
21
+ data = data.dropna(subset=['Income'])
22
+ mean_income = data['Income'].mean()
23
+ data['Income'] = data['Income'].fillna(mean_income)
24
+ data['total_spent'] = data[['MntWines', 'MntFruits', 'MntMeatProducts', 'MntFishProducts', 'MntSweetProducts', 'MntGoldProds']].sum(axis=1)
25
+
26
+ # Define widgets
27
+ education_dropdown = alt.binding_select(options=sorted(data['Education'].unique()), name='Education Level:')
28
+ education_select = alt.selection_single(fields=['Education'], bind=education_dropdown, name='Select')
29
+
30
+ # New widget: marital status dropdown
31
+ marital_status_dropdown = alt.binding_select(options=sorted(data['Marital_Status'].unique()), name='Marital Status:')
32
+ marital_status_select = alt.selection_single(fields=['Marital_Status'], bind=marital_status_dropdown, name='Select')
33
+
34
+ # New widget: range slider for number of web visits
35
+ num_web_visits_slider = alt.binding_range(min=0, max=data['NumWebVisitsMonth'].max(), step=1, name='Web Visits per Month:')
36
+ num_web_visits_select = alt.selection_single(fields=['NumWebVisitsMonth'], bind=num_web_visits_slider, name='Select')
37
+
38
+ # Add new widgets for product selection
39
+ products = ['MntWines', 'MntFruits', 'MntMeatProducts', 'MntFishProducts', 'MntSweetProducts', 'MntGoldProds']
40
+ product_x_dropdown = alt.binding_select(options=products, name='Product X:')
41
+ product_x_select = alt.selection_single(fields=['x_product'], bind=product_x_dropdown, init={'x_product': 'MntWines'})
42
+ product_y_dropdown = alt.binding_select(options=products, name='Product Y:')
43
+ product_y_select = alt.selection_single(fields=['y_product'], bind=product_y_dropdown, init={'y_product': 'MntMeatProducts'})
44
+
45
+
46
+ # Define views
47
+
48
+ # View 1: Bar chart of customer distribution by education level
49
+ education_chart = alt.Chart(data).mark_bar().encode(
50
+ x=alt.X('Education:N', title='Education Level'),
51
+ y=alt.Y('count():Q', title='Number of Customers'),
52
+ color='Education:N'
53
+ ).properties(title='Customer Distribution by Education Level')
54
+
55
+
56
+ # Define widgets
57
+ education_dropdown = alt.binding_select(options=sorted(data['Education'].unique()), name='Education Level:')
58
+ education_select = alt.selection_single(fields=['Education'], bind=education_dropdown, name='Select')
59
+ income_slider = alt.binding_range(min=0, max=data['Income'].max(), step=1000, name='Annual Income:')
60
+ income_select = alt.selection_single(fields=['Income'], bind=income_slider, name='Select')
61
+
62
+ # View 2: Scatter plot of customer annual income and total amount spent on products (with interaction)
63
+ scatter_chart = alt.Chart(data).mark_circle().encode(
64
+ x=alt.X('Income:Q', title='Annual Income'),
65
+ y=alt.Y('total_spent:Q', title='Total Amount Spent on Products'),
66
+ color='Education:N',
67
+ tooltip=[
68
+ alt.Tooltip('Education'),
69
+ alt.Tooltip('Marital_Status'),
70
+ alt.Tooltip('Income', format='$,.0f'),
71
+ alt.Tooltip('total_spent', format='$,.0f')
72
+ ]
73
+ ).properties(title='Customer Annual Income vs Amount Spent on Products').add_selection(
74
+ education_select, income_select, marital_status_select, num_web_visits_select
75
+ ).transform_filter(
76
+ education_select
77
+ ).transform_filter(
78
+ income_select
79
+ ).transform_filter(
80
+ marital_status_select
81
+ ).transform_filter(
82
+ num_web_visits_select
83
+ )
84
+
85
+
86
+ # Define linked selection
87
+ brush = alt.selection(type='interval')
88
+
89
+ # View 5: Bar chart - Average Total Spending per Education Level (linked to scatter chart)
90
+ avg_spending_by_education = alt.Chart(data).mark_bar().encode(
91
+ x=alt.X('Education:N', title='Education Level'),
92
+ y=alt.Y('mean(total_spent):Q', title='Average Total Spending'),
93
+ tooltip=['Education', 'mean(total_spent):Q']
94
+ ).properties(title='Average Total Spending per Education Level').add_selection(
95
+ brush
96
+ ).transform_filter(
97
+ education_select
98
+ )
99
+
100
+ # View 6: Yearly Total Amount Spent on Products (linked to enrollment chart)
101
+ yearly_total_spent_chart = alt.Chart(data).mark_line().encode(
102
+ x=alt.X('year(Dt_Customer):O', title='Year'),
103
+ y=alt.Y('sum(total_spent):Q', title='Total Amount Spent'),
104
+ tooltip=['year(Dt_Customer):O', 'sum(total_spent):Q']
105
+ ).transform_filter(
106
+ education_select
107
+ )
108
+
109
+ # View 3: Timeline chart of new customer enrollments (with linked highlighting)
110
+ enrollment_chart = alt.Chart(data).mark_line().encode(
111
+ x=alt.X('year(Dt_Customer):T', title='Year of Enrollment'),
112
+ y=alt.Y('count():Q', title='Number of New Enrollments'),
113
+ color='Marital_Status:N').properties(title='New Customer Enrollments Over Time').add_selection(
114
+ brush, education_select, income_select, marital_status_select, num_web_visits_select).transform_filter(
115
+ education_select).transform_filter(income_select).transform_filter(marital_status_select).transform_filter(
116
+ num_web_visits_select)
117
+
118
+ # New View: Average spending per marital status (with linked highlighting)
119
+
120
+ avg_spending_by_marital_status = alt.Chart(data).mark_bar().encode(
121
+ x=alt.X('Marital_Status:N', title='Marital Status'),
122
+ y=alt.Y('mean(total_spent):Q', title='Average Total Spending'),
123
+ color='Marital_Status:N',
124
+ tooltip=['Marital_Status', 'mean(total_spent):Q']).properties(title='Average Total Spending per Marital Status').add_selection(brush)
125
+
126
+ import pandas as pd
127
+ import altair as alt
128
+
129
+
130
+ # Convert the 'Dt_Customer' column to datetime format
131
+ data['Dt_Customer'] = pd.to_datetime(data['Dt_Customer'])
132
+
133
+ # Create 'total_spent' column by summing up spending in different product categories
134
+ data['total_spent'] = data[['MntWines', 'MntFruits', 'MntMeatProducts', 'MntFishProducts', 'MntSweetProducts', 'MntGoldProds']].sum(axis=1)
135
+
136
+ # Calculate the average spending for each combination of Teenhome, Kidhome, and Marital_Status
137
+ avg_spending = data.groupby(['Teenhome', 'Kidhome', 'Marital_Status'])['total_spent'].mean().reset_index()
138
+
139
+ # Create a hover selection
140
+ hover = alt.selection_single(on='mouseover', nearest=True, empty='none')
141
+
142
+ # Create a selection for the dropdown
143
+ marital_status_dropdown = alt.binding_select(options=sorted(data['Marital_Status'].unique()), name='Marital Status:')
144
+ marital_status_select = alt.selection_single(fields=['Marital_Status'], bind=marital_status_dropdown, init={'Marital_Status': 'Married'})
145
+
146
+ # Create a grouped bar chart for kids
147
+ chart_kids = alt.Chart(avg_spending).mark_bar().encode(
148
+ x=alt.X('Kidhome:O', title='Number of Kids at Home'),
149
+ y=alt.Y('total_spent:Q', title='Average Spending'),
150
+ color=alt.condition(hover, 'Kidhome:O', alt.value('lightgray'), legend=alt.Legend(title='Number of Kids at Home')),
151
+ tooltip=['Teenhome', 'Kidhome', 'total_spent', 'Marital_Status']
152
+ ).properties(title='Average Spending by Number of Kids at Home (Filtered by Marital Status)').add_selection(
153
+ hover
154
+ )
155
+
156
+ # Create a grouped bar chart for teens
157
+ chart_teens = alt.Chart(avg_spending).mark_bar().encode(
158
+ x=alt.X('Teenhome:O', title='Number of Teens at Home'),
159
+ y=alt.Y('total_spent:Q', title='Average Spending'),
160
+ color=alt.condition(hover, 'Teenhome:O', alt.value('lightgray'), legend=alt.Legend(title='Number of Teens at Home')),
161
+ tooltip=['Teenhome', 'Kidhome', 'total_spent', 'Marital_Status']
162
+ ).properties(title='Average Spending by Number of Teens at Home (Filtered by Marital Status)').add_selection(
163
+ hover
164
+ )
165
+
166
+ # Combine the charts
167
+ concat_chart = alt.hconcat(chart_kids, chart_teens).add_selection(
168
+ marital_status_select
169
+ ).transform_filter(
170
+ marital_status_select
171
+ )
172
+
173
+
174
+ """scatter_plot = alt.Chart(data).mark_circle().encode(
175
+ x=alt.X('NumWebVisitsMonth:Q', title='Number of Web Visits per Month'),
176
+ y=alt.Y('NumWebPurchases:Q', title='Number of Web Purchases'),
177
+ size=alt.Size('count():Q', scale=alt.Scale(range=[50, 500]), legend=alt.Legend(title='Number of Customers')),
178
+ color=alt.Color('count():Q', scale=alt.Scale(scheme='viridis'), legend=None),
179
+ tooltip=['NumWebVisitsMonth', 'NumWebPurchases', 'count()']
180
+ ).properties(title='Scatter Plot of Web Visits per Month vs. Web Purchases')
181
+
182
+ scatter_plot.interactive()"""
183
+
184
+ # Define dropdown selection for marital status
185
+ marital_status_dropdown = alt.binding_select(options=data['Marital_Status'].unique().tolist(), name='Marital Status: ')
186
+ marital_status_selection = alt.selection_single(fields=['Marital_Status'], bind=marital_status_dropdown, name='Marital_Status', init={'Marital_Status': data['Marital_Status'].iloc[0]})
187
+
188
+ # Add a scatter plot and filter by marital status
189
+ scatter_plot_filtered = alt.Chart(data).mark_circle().encode(
190
+ x=alt.X('NumWebVisitsMonth:Q', title='Number of Web Visits per Month'),
191
+ y=alt.Y('NumWebPurchases:Q', title='Number of Web Purchases'),
192
+ size=alt.Size('count():Q', scale=alt.Scale(range=[50, 500]), legend=alt.Legend(title='Number of Customers')),
193
+ color=alt.Color('count():Q', scale=alt.Scale(scheme='viridis'), legend=None),
194
+ tooltip=['NumWebVisitsMonth', 'NumWebPurchases', 'count()']
195
+ ).properties(title='Scatter Plot of Web Visits per Month vs. Web Purchases Filtered by Marital Status').transform_filter(
196
+ marital_status_selection
197
+ )
198
+
199
+ # Add interactivity and the marital status selection to the scatter plot
200
+ interactive_scatter_plot_filtered = scatter_plot_filtered.interactive().add_selection(marital_status_selection)
201
+ interactive_scatter_plot_filtered
202
+
203
+
204
+ # Group by 'Dt_Customer' and calculate average spending for new and returning customers
205
+ new_customers = data[data['NumWebPurchases'] == 0].groupby('Dt_Customer')['total_spent'].mean().reset_index()
206
+ returning_customers = data[data['NumWebPurchases'] > 0].groupby('Dt_Customer')['total_spent'].mean().reset_index()
207
+
208
+
209
+ # new_customers and returning_customers DataFrames
210
+ # Create line charts for new and returning customers without filtering
211
+ new_line = alt.Chart(new_customers).mark_line().encode(
212
+ x=alt.X('Dt_Customer:T', title='Date'),
213
+ y=alt.Y('total_spent:Q', title='Average Spending'),
214
+ color=alt.value('blue'),
215
+ tooltip=['Dt_Customer', 'total_spent']
216
+ ).properties(title='New Customers')
217
+
218
+ returning_line = alt.Chart(returning_customers).mark_line().encode(
219
+ x=alt.X('Dt_Customer:T', title='Date'),
220
+ y=alt.Y('total_spent:Q', title='Average Spending'),
221
+ color=alt.value('green'),
222
+ tooltip=['Dt_Customer', 'total_spent']
223
+ ).properties(title='Returning Customers')
224
+
225
+ # Display the charts side by side
226
+ combined_chart = alt.hconcat(new_line, returning_line)
227
+ combined_chart
228
+
229
+ # Merge Marital_Status to new_customers and returning_customers DataFrames
230
+
231
+ new_customers = new_customers.merge(data[['Dt_Customer', 'Marital_Status']], on='Dt_Customer', how='left')
232
+ returning_customers = returning_customers.merge(data[['Dt_Customer', 'Marital_Status']], on='Dt_Customer', how='left')
233
+
234
+ # Filter data by marital status using transform_filter within the charts
235
+ new_line_filtered = alt.Chart(new_customers).mark_line().encode(
236
+ x=alt.X('Dt_Customer:T', title='Date'),
237
+ y=alt.Y('total_spent:Q', title='Average Spending'),
238
+ color=alt.value('blue'),
239
+ tooltip=['Dt_Customer', 'total_spent']
240
+ ).properties(title='New Customers').transform_filter(
241
+ marital_status_selection
242
+ )
243
+
244
+ returning_line_filtered = alt.Chart(returning_customers).mark_line().encode(
245
+ x=alt.X('Dt_Customer:T', title='Date'),
246
+ y=alt.Y('total_spent:Q', title='Average Spending'),
247
+ color=alt.value('green'),
248
+ tooltip=['Dt_Customer', 'total_spent']
249
+ ).properties(title='Returning Customers').transform_filter(
250
+ marital_status_selection
251
+ )
252
+
253
+ # Add interactivity for panning and zooming
254
+ interactive_chart_filtered = alt.layer(new_line_filtered, returning_line_filtered).resolve_scale(y='shared').interactive().add_selection(marital_status_selection)
255
+
256
+ # Combine the interactive chart, the legend, and the marital status selection
257
+ # Create legend
258
+ legend = alt.Chart(pd.DataFrame({'legend': ['New Customers', 'Returning Customers'], 'color': ['blue', 'green']})).mark_point().encode(
259
+ x=alt.value(20),
260
+ y=alt.Y('legend', title=None),
261
+ color=alt.Color('color', scale=None),
262
+ tooltip=['legend']
263
+ )
264
+
265
+ # Combine the interactive chart, the legend, and the marital status selection
266
+ final_chart_filtered = alt.hconcat(interactive_chart_filtered, legend).properties(title='Average Spending of New vs Returning Customers by Marital Status')
267
+ final_chart_filtered
268
+
269
+ import panel as pn
270
+ pn.extension('vega')
271
+
272
+
273
+ # Define dashboard layout
274
+ dashboard = pn.Column(
275
+ pn.Row(
276
+ pn.Column(
277
+ education_chart,
278
+ avg_spending_by_education,
279
+ avg_spending_by_marital_status,
280
+ width=350
281
+ ),
282
+ pn.Column(
283
+ scatter_chart,
284
+ enrollment_chart,
285
+ width=700
286
+ ),
287
+ ),
288
+ pn.Row(
289
+ concat_chart,
290
+ width=1000
291
+ ),
292
+ pn.Row(
293
+ final_chart_filtered,
294
+ width=1000
295
+ ),
296
+ )
297
+
298
+
299
+ # Display dashboard
300
+ dashboard.servable()
301
+
302
+
303
+ # In[ ]:
304
+
305
+
306
+
307
+