gdleds commited on
Commit
5706836
·
1 Parent(s): 23b783a

app modif buffer5

Browse files
Files changed (1) hide show
  1. app.py +55 -34
app.py CHANGED
@@ -2,7 +2,7 @@ import streamlit as st
2
  import pandas as pd
3
  import plotly.express as px
4
 
5
- # === CONFIG STREAMLIT ===
6
  st.set_page_config(page_title="Getaround – Dashboard Analyse", layout="wide")
7
 
8
  st.title("🚗 Dashboard Analyse – Getaround")
@@ -15,16 +15,16 @@ Nous allons explorer :
15
  4. La conclusion business
16
  """)
17
 
18
- # === CHARGEMENT DES DONNÉES ===
19
  df = pd.read_csv("data/get_around_delay_analysis.csv")
20
  df_pricing = pd.read_csv("data/pricing_clean.csv")
21
 
22
  loc_moyenne = df_pricing["rental_price_per_day"].mean()
23
 
24
- # === SECTION 1 : EDA SUR LES RETARDS ===
25
  st.header("📊 Analyse des retards et annulations")
26
 
27
- # Pie chart état
28
  fig_state = px.pie(df, names="state", title="Répartition par état des locations")
29
  st.plotly_chart(fig_state, use_container_width=True)
30
 
@@ -36,7 +36,7 @@ st.markdown("""
36
  La proportion est légèrement plus élevée via **Connect** que via Mobile.
37
  """)
38
 
39
- # Histogramme retards
40
  fig_delay = px.histogram(
41
  df.query("-150 <= delay_at_checkout_in_minutes <= 150"),
42
  x="delay_at_checkout_in_minutes",
@@ -52,7 +52,7 @@ st.markdown("""
52
  Mais certains cas extrêmes dépassent plusieurs jours.
53
  """)
54
 
55
- # === SECTION 2 : ANALYSE DES ANNULATIONS ===
56
  st.header("❌ Analyse des annulations liées aux retards")
57
 
58
  mask = df['previous_ended_rental_id'] > 0
@@ -62,17 +62,15 @@ annulation = (df_nan["state"] == "canceled").sum()
62
  st.metric("La location moyenne d'un véhicule par jour est de ", df_pricing['rental_price_per_day'].mean())
63
  st.metric("La perte du aux annulations s'élève a :", (annulation * loc_moyenne).round(2),"$")
64
 
65
- # On crée un dataframe locations annulées
66
  canceled = df[df["state"] == "canceled"][["rental_id", "car_id", "previous_ended_rental_id", "checkin_type","time_delta_with_previous_rental_in_minutes"]]
67
 
68
- # On rattache la location annulée à la précédente
69
  merged = canceled.merge(
70
  df[["rental_id", "car_id", "delay_at_checkout_in_minutes", "checkin_type"]],
71
- left_on="previous_ended_rental_id", # clé : location précédente
72
  right_on="rental_id",
73
  suffixes=("_canceled", "_previous")
74
  )
75
- # Regardons les conflits direct c'est à dire que la restitution est supérieur au delay entre location prévu
76
  conflict_strict = merged[
77
  merged["delay_at_checkout_in_minutes"] > merged["time_delta_with_previous_rental_in_minutes"]
78
  ]
@@ -85,12 +83,10 @@ st.markdown("""
85
  Ces retards sont très longs (~4h15 en moyenne).
86
  """)
87
 
88
- # Cas "conflit -30min"
89
  conflict_minus30 = merged[
90
  merged["delay_at_checkout_in_minutes"] > merged["time_delta_with_previous_rental_in_minutes"] - 30
91
  ]
92
 
93
- # Cas "conflit -60min"
94
  conflict_minus60 = merged[
95
  merged["delay_at_checkout_in_minutes"] > merged["time_delta_with_previous_rental_in_minutes"] - 60
96
  ]
@@ -103,7 +99,7 @@ conflict_minus180 = merged[
103
  merged["delay_at_checkout_in_minutes"] > merged["time_delta_with_previous_rental_in_minutes"] - 180
104
  ]
105
 
106
- # Création d'une liste de résultats
107
  results = [
108
  {"Buffer": "-30 min", "Conflits": (len(conflict_minus30)-len(conflict_strict)), "Moyenne retard (min)": conflict_minus30["delay_at_checkout_in_minutes"].mean()},
109
  {"Buffer": "-60 min", "Conflits": (len(conflict_minus60)-len(conflict_strict)), "Moyenne retard (min)": conflict_minus60["delay_at_checkout_in_minutes"].mean()},
@@ -138,7 +134,6 @@ st.plotly_chart(fig_type, use_container_width=True)
138
 
139
  st.markdown(""" ANALYSE SUR MOBILE """)
140
 
141
- # Dans le cas de l'application mobile
142
  mask = merged["checkin_type_canceled"] == "mobile"
143
  merged_mob = merged[mask]
144
  conflict_strict1= merged_mob[
@@ -147,12 +142,10 @@ conflict_strict1= merged_mob[
147
  st.metric("Conflits stricts :", len(conflict_strict1))
148
  st.metric("Moyenne retard précédent (conflits seulement) :", conflict_strict1["delay_at_checkout_in_minutes"].mean().round(2))
149
 
150
- # Cas "conflit -30min"
151
  conflict_1minus30 = merged_mob[
152
  merged_mob["delay_at_checkout_in_minutes"] > merged_mob["time_delta_with_previous_rental_in_minutes"] - 30
153
  ]
154
 
155
- # Cas "conflit -60min"
156
  conflict_1minus60 = merged_mob[
157
  merged_mob["delay_at_checkout_in_minutes"] > merged_mob["time_delta_with_previous_rental_in_minutes"] - 60
158
  ]
@@ -165,7 +158,7 @@ conflict_1minus180 = merged_mob[
165
  merged_mob["delay_at_checkout_in_minutes"] > merged_mob["time_delta_with_previous_rental_in_minutes"] - 180
166
  ]
167
 
168
- # Création d'une liste de résultats
169
  results = [
170
  {"Buffer": "-30 min", "Conflits": (len(conflict_1minus30)-len(conflict_strict1)), "Moyenne retard (min)": conflict_1minus30["delay_at_checkout_in_minutes"].mean()},
171
  {"Buffer": "-60 min", "Conflits": (len(conflict_1minus60)-len(conflict_strict1)), "Moyenne retard (min)": conflict_1minus60["delay_at_checkout_in_minutes"].mean()},
@@ -177,7 +170,7 @@ df_conflicts_mob['lost_value'] = df_conflicts_mob["Conflits"]*loc_moyenne
177
  st.dataframe(df_conflicts_mob)
178
 
179
  st.markdown(""" ANALYSE SUR CONNECT """)
180
- # Dans le cas de l'utilisation de connect
181
  mask = merged["checkin_type_canceled"] == "connect"
182
  merged_connect = merged[mask]
183
  conflict_strict2 = merged_connect[
@@ -186,12 +179,12 @@ conflict_strict2 = merged_connect[
186
  st.metric("Conflits stricts :", len(conflict_strict2))
187
  st.metric("Moyenne retard précédent (conflits seulement) :", conflict_strict2["delay_at_checkout_in_minutes"].mean().round(2))
188
 
189
- # Cas "conflit -30min"
190
  conflict_2minus30 = merged_connect[
191
  merged_connect["delay_at_checkout_in_minutes"] > merged_connect["time_delta_with_previous_rental_in_minutes"] - 30
192
  ]
193
 
194
- # Cas "conflit -60min"
195
  conflict_2minus60 = merged_connect[
196
  merged_connect["delay_at_checkout_in_minutes"] > merged_connect["time_delta_with_previous_rental_in_minutes"] - 60
197
  ]
@@ -204,7 +197,7 @@ conflict_2minus180 = merged_connect[
204
  merged_connect["delay_at_checkout_in_minutes"] > merged_connect["time_delta_with_previous_rental_in_minutes"] - 180
205
  ]
206
 
207
- # Création d'une liste de résultats
208
  results = [
209
  {"Buffer": "-30 min", "Conflits": (len(conflict_2minus30)-len(conflict_strict2)), "Moyenne retard (min)": conflict_2minus30["delay_at_checkout_in_minutes"].mean()},
210
  {"Buffer": "-60 min", "Conflits": (len(conflict_2minus60)-len(conflict_strict2)), "Moyenne retard (min)": conflict_2minus60["delay_at_checkout_in_minutes"].mean()},
@@ -224,10 +217,10 @@ Les deux méthodes sont exposées aux retards, mais Connect encaisse plus de cas
224
  Un buffer opérationnel de 30 minutes permettrai un gain rapide sans trop affecté le CA global.
225
  """ )
226
 
227
- # === SECTION 3 : IMPACT DES BUFFERS ===
228
  st.header("⏳ Simulation de buffer entre locations")
229
- st.markdown(""" Afin d'analyser l'impact d'un buffer nous prenons cette fois ci que les location qui a eu lieu et filtrons toutes les location ayant débuté dans les 30 minutes qui suit la précéddentes.
230
- Ces locations sont celle qui risquent d'etre impacté """)
231
 
232
  loc_moyenne = df_pricing["rental_price_per_day"].mean()
233
  CA_total = (df['state'] == 'ended').sum() * loc_moyenne
@@ -251,7 +244,7 @@ st.dataframe(df_results)
251
 
252
  st.markdown(""" MOBILE UNIQUEMENT""")
253
 
254
- df_valid_mob = df[(df["state"] == "ended") & (df["checkin_type_canceled"] == "mobile")].copy()
255
  df_valid_mob["ecart"] = df_valid_mob["time_delta_with_previous_rental_in_minutes"] - df_valid_mob["delay_at_checkout_in_minutes"]
256
 
257
  def count_blocked(df, buffer):
@@ -269,7 +262,7 @@ st.dataframe(df_results_mob)
269
 
270
  st.markdown(""" CONNECT UNIQUEMENT""")
271
 
272
- df_valid_con = df[(df["state"] == "ended") & (df["checkin_type_canceled"] == "connect")].copy()
273
  df_valid_con["ecart"] = df_valid_con["time_delta_with_previous_rental_in_minutes"] - df_valid_con["delay_at_checkout_in_minutes"]
274
 
275
  def count_blocked(df, buffer):
@@ -284,33 +277,61 @@ for b in [30, 60, 90, 180]:
284
  df_results_con = pd.DataFrame(results3)
285
  st.dataframe(df_results_con)
286
 
287
-
288
-
289
  st.markdown("""
290
  👉 Un buffer **de 30 min bloque ~340 locations** → pertes supérieures aux gains.
291
  👉 Un buffer de **180 min réduit beaucoup les annulations** mais fait perdre trop de CA.
292
  **Conclusion : un buffer global n’est pas viable.**
293
  """)
294
 
295
- # === SECTION 4 : ANALYSE DU PRICING ===
296
  st.header("💰 Analyse des prix de location")
297
 
298
  fig_price = px.histogram(df_pricing, x="rental_price_per_day", nbins=50,
299
  title="Distribution des prix de location par jour")
300
  st.plotly_chart(fig_price, use_container_width=True)
301
 
 
 
 
 
 
 
302
  st.markdown("""
303
  👉 Le marché est concentré autour de **100–140 $/jour**.
304
  Les **SUV, coupés, cabriolets** sont plus chers.
305
  Les **citadines** et **hatchbacks** moins chers.
306
  """)
307
 
308
- # Boxplot prix par fuel
309
- fig_fuel = px.box(df_pricing, x="fuel", y="rental_price_per_day",
310
- title="Prix selon le type de carburant")
311
- st.plotly_chart(fig_fuel, use_container_width=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
312
 
313
- # === SECTION 5 : CONCLUSION BUSINESS ===
314
  st.header("📌 Conclusion business")
315
 
316
  st.markdown("""
 
2
  import pandas as pd
3
  import plotly.express as px
4
 
5
+
6
  st.set_page_config(page_title="Getaround – Dashboard Analyse", layout="wide")
7
 
8
  st.title("🚗 Dashboard Analyse – Getaround")
 
15
  4. La conclusion business
16
  """)
17
 
18
+
19
  df = pd.read_csv("data/get_around_delay_analysis.csv")
20
  df_pricing = pd.read_csv("data/pricing_clean.csv")
21
 
22
  loc_moyenne = df_pricing["rental_price_per_day"].mean()
23
 
24
+ # EDA SUR LES RETARDS
25
  st.header("📊 Analyse des retards et annulations")
26
 
27
+
28
  fig_state = px.pie(df, names="state", title="Répartition par état des locations")
29
  st.plotly_chart(fig_state, use_container_width=True)
30
 
 
36
  La proportion est légèrement plus élevée via **Connect** que via Mobile.
37
  """)
38
 
39
+
40
  fig_delay = px.histogram(
41
  df.query("-150 <= delay_at_checkout_in_minutes <= 150"),
42
  x="delay_at_checkout_in_minutes",
 
52
  Mais certains cas extrêmes dépassent plusieurs jours.
53
  """)
54
 
55
+ # ANALYSE DES ANNULATIONS
56
  st.header("❌ Analyse des annulations liées aux retards")
57
 
58
  mask = df['previous_ended_rental_id'] > 0
 
62
  st.metric("La location moyenne d'un véhicule par jour est de ", df_pricing['rental_price_per_day'].mean())
63
  st.metric("La perte du aux annulations s'élève a :", (annulation * loc_moyenne).round(2),"$")
64
 
 
65
  canceled = df[df["state"] == "canceled"][["rental_id", "car_id", "previous_ended_rental_id", "checkin_type","time_delta_with_previous_rental_in_minutes"]]
66
 
 
67
  merged = canceled.merge(
68
  df[["rental_id", "car_id", "delay_at_checkout_in_minutes", "checkin_type"]],
69
+ left_on="previous_ended_rental_id",
70
  right_on="rental_id",
71
  suffixes=("_canceled", "_previous")
72
  )
73
+
74
  conflict_strict = merged[
75
  merged["delay_at_checkout_in_minutes"] > merged["time_delta_with_previous_rental_in_minutes"]
76
  ]
 
83
  Ces retards sont très longs (~4h15 en moyenne).
84
  """)
85
 
 
86
  conflict_minus30 = merged[
87
  merged["delay_at_checkout_in_minutes"] > merged["time_delta_with_previous_rental_in_minutes"] - 30
88
  ]
89
 
 
90
  conflict_minus60 = merged[
91
  merged["delay_at_checkout_in_minutes"] > merged["time_delta_with_previous_rental_in_minutes"] - 60
92
  ]
 
99
  merged["delay_at_checkout_in_minutes"] > merged["time_delta_with_previous_rental_in_minutes"] - 180
100
  ]
101
 
102
+
103
  results = [
104
  {"Buffer": "-30 min", "Conflits": (len(conflict_minus30)-len(conflict_strict)), "Moyenne retard (min)": conflict_minus30["delay_at_checkout_in_minutes"].mean()},
105
  {"Buffer": "-60 min", "Conflits": (len(conflict_minus60)-len(conflict_strict)), "Moyenne retard (min)": conflict_minus60["delay_at_checkout_in_minutes"].mean()},
 
134
 
135
  st.markdown(""" ANALYSE SUR MOBILE """)
136
 
 
137
  mask = merged["checkin_type_canceled"] == "mobile"
138
  merged_mob = merged[mask]
139
  conflict_strict1= merged_mob[
 
142
  st.metric("Conflits stricts :", len(conflict_strict1))
143
  st.metric("Moyenne retard précédent (conflits seulement) :", conflict_strict1["delay_at_checkout_in_minutes"].mean().round(2))
144
 
 
145
  conflict_1minus30 = merged_mob[
146
  merged_mob["delay_at_checkout_in_minutes"] > merged_mob["time_delta_with_previous_rental_in_minutes"] - 30
147
  ]
148
 
 
149
  conflict_1minus60 = merged_mob[
150
  merged_mob["delay_at_checkout_in_minutes"] > merged_mob["time_delta_with_previous_rental_in_minutes"] - 60
151
  ]
 
158
  merged_mob["delay_at_checkout_in_minutes"] > merged_mob["time_delta_with_previous_rental_in_minutes"] - 180
159
  ]
160
 
161
+
162
  results = [
163
  {"Buffer": "-30 min", "Conflits": (len(conflict_1minus30)-len(conflict_strict1)), "Moyenne retard (min)": conflict_1minus30["delay_at_checkout_in_minutes"].mean()},
164
  {"Buffer": "-60 min", "Conflits": (len(conflict_1minus60)-len(conflict_strict1)), "Moyenne retard (min)": conflict_1minus60["delay_at_checkout_in_minutes"].mean()},
 
170
  st.dataframe(df_conflicts_mob)
171
 
172
  st.markdown(""" ANALYSE SUR CONNECT """)
173
+
174
  mask = merged["checkin_type_canceled"] == "connect"
175
  merged_connect = merged[mask]
176
  conflict_strict2 = merged_connect[
 
179
  st.metric("Conflits stricts :", len(conflict_strict2))
180
  st.metric("Moyenne retard précédent (conflits seulement) :", conflict_strict2["delay_at_checkout_in_minutes"].mean().round(2))
181
 
182
+
183
  conflict_2minus30 = merged_connect[
184
  merged_connect["delay_at_checkout_in_minutes"] > merged_connect["time_delta_with_previous_rental_in_minutes"] - 30
185
  ]
186
 
187
+
188
  conflict_2minus60 = merged_connect[
189
  merged_connect["delay_at_checkout_in_minutes"] > merged_connect["time_delta_with_previous_rental_in_minutes"] - 60
190
  ]
 
197
  merged_connect["delay_at_checkout_in_minutes"] > merged_connect["time_delta_with_previous_rental_in_minutes"] - 180
198
  ]
199
 
200
+
201
  results = [
202
  {"Buffer": "-30 min", "Conflits": (len(conflict_2minus30)-len(conflict_strict2)), "Moyenne retard (min)": conflict_2minus30["delay_at_checkout_in_minutes"].mean()},
203
  {"Buffer": "-60 min", "Conflits": (len(conflict_2minus60)-len(conflict_strict2)), "Moyenne retard (min)": conflict_2minus60["delay_at_checkout_in_minutes"].mean()},
 
217
  Un buffer opérationnel de 30 minutes permettrai un gain rapide sans trop affecté le CA global.
218
  """ )
219
 
220
+ # IMPACT DES BUFFERS
221
  st.header("⏳ Simulation de buffer entre locations")
222
+ st.markdown(""" Afin d'analyser l'impact d'un buffer nous prenons cette fois ci que les locations qui ont eu lieu et filtrons toutes les locations ayant débutées dans les 30 minutes qui suit la précéddentes.
223
+ Ces locations sont celle qui risquent d'etre impactées par ce delai """)
224
 
225
  loc_moyenne = df_pricing["rental_price_per_day"].mean()
226
  CA_total = (df['state'] == 'ended').sum() * loc_moyenne
 
244
 
245
  st.markdown(""" MOBILE UNIQUEMENT""")
246
 
247
+ df_valid_mob = df[(df["state"] == "ended") & (df["checkin_type"] == "mobile")].copy()
248
  df_valid_mob["ecart"] = df_valid_mob["time_delta_with_previous_rental_in_minutes"] - df_valid_mob["delay_at_checkout_in_minutes"]
249
 
250
  def count_blocked(df, buffer):
 
262
 
263
  st.markdown(""" CONNECT UNIQUEMENT""")
264
 
265
+ df_valid_con = df[(df["state"] == "ended") & (df["checkin_type"] == "connect")].copy()
266
  df_valid_con["ecart"] = df_valid_con["time_delta_with_previous_rental_in_minutes"] - df_valid_con["delay_at_checkout_in_minutes"]
267
 
268
  def count_blocked(df, buffer):
 
277
  df_results_con = pd.DataFrame(results3)
278
  st.dataframe(df_results_con)
279
 
 
 
280
  st.markdown("""
281
  👉 Un buffer **de 30 min bloque ~340 locations** → pertes supérieures aux gains.
282
  👉 Un buffer de **180 min réduit beaucoup les annulations** mais fait perdre trop de CA.
283
  **Conclusion : un buffer global n’est pas viable.**
284
  """)
285
 
286
+ # ANALYSE DU PRICING
287
  st.header("💰 Analyse des prix de location")
288
 
289
  fig_price = px.histogram(df_pricing, x="rental_price_per_day", nbins=50,
290
  title="Distribution des prix de location par jour")
291
  st.plotly_chart(fig_price, use_container_width=True)
292
 
293
+
294
+ fig_car_typ = px.box(df_pricing, x="car_type", y="rental_price_per_day",
295
+ title="Prix par type de véhicule")
296
+ st.plotly_chart(fig_car_typ, use_container_width=True)
297
+
298
+
299
  st.markdown("""
300
  👉 Le marché est concentré autour de **100–140 $/jour**.
301
  Les **SUV, coupés, cabriolets** sont plus chers.
302
  Les **citadines** et **hatchbacks** moins chers.
303
  """)
304
 
305
+ st.markdown(""" **Indice de correlation** """)
306
+ df_corr = df_pricing.copy()
307
+ bool_cols = df_corr.select_dtypes(include="bool").columns
308
+ df_corr[bool_cols] = df_corr[bool_cols].astype(int)
309
+
310
+ num_df = df_corr.select_dtypes(include=["int64", "float64"])
311
+
312
+ corr = num_df.corr()
313
+
314
+ fig_cor = px.imshow(
315
+ corr,
316
+ text_auto=True,
317
+ color_continuous_scale="RdBu_r",
318
+ title="Matrice de corrélation",
319
+ height=800,
320
+ width=1000
321
+ )
322
+ st.plotly_chart(fig_cor, use_container_width=True)
323
+
324
+ st.markdown(""" + corrélation prix ↔ puissance moteur
325
+
326
+ – corrélation prix ↔ kilométrage
327
+
328
+ Transmission automatique = + valeur
329
+
330
+ Présence de GPS = + valeur ajoutée """)
331
+
332
+
333
 
334
+ # CONCLUSION BUSINESS
335
  st.header("📌 Conclusion business")
336
 
337
  st.markdown("""