Spaces:
Sleeping
Sleeping
app modif buffer4
Browse files
app.py
CHANGED
|
@@ -58,6 +58,9 @@ st.header("❌ Analyse des annulations liées aux retards")
|
|
| 58 |
mask = df['previous_ended_rental_id'] > 0
|
| 59 |
df_nan = df[mask]
|
| 60 |
st.metric("Le nombre d'annulations du au retard du véhicule liées à un location précendente est de", (df_nan["state"] == "canceled").sum())
|
|
|
|
|
|
|
|
|
|
| 61 |
|
| 62 |
# On crée un dataframe locations annulées
|
| 63 |
canceled = df[df["state"] == "canceled"][["rental_id", "car_id", "previous_ended_rental_id", "checkin_type","time_delta_with_previous_rental_in_minutes"]]
|
|
@@ -111,7 +114,7 @@ df_conflicts = pd.DataFrame(results)
|
|
| 111 |
df_conflicts['lost_value'] = df_conflicts["Conflits"]*loc_moyenne
|
| 112 |
st.dataframe(df_conflicts)
|
| 113 |
|
| 114 |
-
st.markdown("""Si on
|
| 115 |
Avec un buffer de 60 minutes, seulement 3 cas en plus → ce sont donc des situations rares mais critiques.
|
| 116 |
En élargissant à 90 minutes, on ajoute encore 7 cas.""")
|
| 117 |
|
|
@@ -229,7 +232,7 @@ Ces locations sont celle qui risquent d'etre impacté """)
|
|
| 229 |
loc_moyenne = df_pricing["rental_price_per_day"].mean()
|
| 230 |
CA_total = (df['state'] == 'ended').sum() * loc_moyenne
|
| 231 |
|
| 232 |
-
|
| 233 |
df_valid = df[df["state"] == "ended"].copy()
|
| 234 |
df_valid["ecart"] = df_valid["time_delta_with_previous_rental_in_minutes"] - df_valid["delay_at_checkout_in_minutes"]
|
| 235 |
|
|
@@ -245,6 +248,44 @@ for b in [30, 60, 90, 180]:
|
|
| 245 |
df_results = pd.DataFrame(results)
|
| 246 |
st.dataframe(df_results)
|
| 247 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 248 |
st.markdown("""
|
| 249 |
👉 Un buffer **de 30 min bloque ~340 locations** → pertes supérieures aux gains.
|
| 250 |
👉 Un buffer de **180 min réduit beaucoup les annulations** mais fait perdre trop de CA.
|
|
|
|
| 58 |
mask = df['previous_ended_rental_id'] > 0
|
| 59 |
df_nan = df[mask]
|
| 60 |
st.metric("Le nombre d'annulations du au retard du véhicule liées à un location précendente est de", (df_nan["state"] == "canceled").sum())
|
| 61 |
+
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"]]
|
|
|
|
| 114 |
df_conflicts['lost_value'] = df_conflicts["Conflits"]*loc_moyenne
|
| 115 |
st.dataframe(df_conflicts)
|
| 116 |
|
| 117 |
+
st.markdown("""Si on regarde 30 miniutes avant le début de la location du véhicule combien ont été annulé (buffer de 30 minutes), on détecte 10 annulations supplémentaires : ces cas correspondent à des locations rendues trop proches de la suivante (<30 min de marge).
|
| 118 |
Avec un buffer de 60 minutes, seulement 3 cas en plus → ce sont donc des situations rares mais critiques.
|
| 119 |
En élargissant à 90 minutes, on ajoute encore 7 cas.""")
|
| 120 |
|
|
|
|
| 232 |
loc_moyenne = df_pricing["rental_price_per_day"].mean()
|
| 233 |
CA_total = (df['state'] == 'ended').sum() * loc_moyenne
|
| 234 |
|
| 235 |
+
|
| 236 |
df_valid = df[df["state"] == "ended"].copy()
|
| 237 |
df_valid["ecart"] = df_valid["time_delta_with_previous_rental_in_minutes"] - df_valid["delay_at_checkout_in_minutes"]
|
| 238 |
|
|
|
|
| 248 |
df_results = pd.DataFrame(results)
|
| 249 |
st.dataframe(df_results)
|
| 250 |
|
| 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):
|
| 258 |
+
return (df["ecart"] < buffer).sum()
|
| 259 |
+
|
| 260 |
+
results2 = []
|
| 261 |
+
for b in [30, 60, 90, 180]:
|
| 262 |
+
blocked = count_blocked(df_valid_mob, b)
|
| 263 |
+
perte_estimee = blocked * loc_moyenne
|
| 264 |
+
results.append({"Buffer (min)": b, "Locations bloquées": blocked, "Perte estimée ($)": round(perte_estimee, 2)})
|
| 265 |
+
|
| 266 |
+
df_results_mob = pd.DataFrame(results2)
|
| 267 |
+
st.dataframe(df_results_mob)
|
| 268 |
+
|
| 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):
|
| 276 |
+
return (df["ecart"] < buffer).sum()
|
| 277 |
+
|
| 278 |
+
results3 = []
|
| 279 |
+
for b in [30, 60, 90, 180]:
|
| 280 |
+
blocked = count_blocked(df_valid_con, b)
|
| 281 |
+
perte_estimee = blocked * loc_moyenne
|
| 282 |
+
results.append({"Buffer (min)": b, "Locations bloquées": blocked, "Perte estimée ($)": round(perte_estimee, 2)})
|
| 283 |
+
|
| 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.
|