Spaces:
Sleeping
Sleeping
app modif buffer
Browse files- app.py +60 -3
- data/get_around_pricing_project.csv +0 -0
app.py
CHANGED
|
@@ -26,6 +26,9 @@ st.header("📊 Analyse des retards et annulations")
|
|
| 26 |
fig_state = px.pie(df, names="state", title="Répartition par état des locations")
|
| 27 |
st.plotly_chart(fig_state, use_container_width=True)
|
| 28 |
|
|
|
|
|
|
|
|
|
|
| 29 |
st.markdown("""
|
| 30 |
👉 Environ **15 % des transactions sont annulées**.
|
| 31 |
La proportion est légèrement plus élevée via **Connect** que via Mobile.
|
|
@@ -50,15 +53,69 @@ Mais certains cas extrêmes dépassent plusieurs jours.
|
|
| 50 |
# === SECTION 2 : ANALYSE DES ANNULATIONS ===
|
| 51 |
st.header("❌ Analyse des annulations liées aux retards")
|
| 52 |
|
| 53 |
-
|
| 54 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
|
| 56 |
st.markdown("""
|
| 57 |
👉 Parmi les **229 annulations liées à une location précédente**,
|
| 58 |
-
|
| 59 |
Ces retards sont très longs (~4h15 en moyenne).
|
| 60 |
""")
|
| 61 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
# === SECTION 3 : IMPACT DES BUFFERS ===
|
| 63 |
st.header("⏳ Simulation de buffer entre locations")
|
| 64 |
|
|
|
|
| 26 |
fig_state = px.pie(df, names="state", title="Répartition par état des locations")
|
| 27 |
st.plotly_chart(fig_state, use_container_width=True)
|
| 28 |
|
| 29 |
+
annulation = (df["state"] == "canceled").sum()
|
| 30 |
+
st.metric("Nombre total d'annulations", annulation)
|
| 31 |
+
|
| 32 |
st.markdown("""
|
| 33 |
👉 Environ **15 % des transactions sont annulées**.
|
| 34 |
La proportion est légèrement plus élevée via **Connect** que via Mobile.
|
|
|
|
| 53 |
# === SECTION 2 : ANALYSE DES ANNULATIONS ===
|
| 54 |
st.header("❌ Analyse des annulations liées aux retards")
|
| 55 |
|
| 56 |
+
mask = df['previous_ended_rental_id'] > 0
|
| 57 |
+
df_nan = df[mask]
|
| 58 |
+
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())
|
| 59 |
+
|
| 60 |
+
# On crée un dataframe locations annulées
|
| 61 |
+
canceled = df[df["state"] == "canceled"][["rental_id", "car_id", "previous_ended_rental_id", "checkin_type","time_delta_with_previous_rental_in_minutes"]]
|
| 62 |
+
|
| 63 |
+
# On rattache la location annulée à la précédente
|
| 64 |
+
merged = canceled.merge(
|
| 65 |
+
df[["rental_id", "car_id", "delay_at_checkout_in_minutes", "checkin_type"]],
|
| 66 |
+
left_on="previous_ended_rental_id", # clé : location précédente
|
| 67 |
+
right_on="rental_id",
|
| 68 |
+
suffixes=("_canceled", "_previous")
|
| 69 |
+
)
|
| 70 |
+
# Regardons les conflits direct c'est à dire que la restitution est supérieur au delay entre location prévu
|
| 71 |
+
conflict_strict = merged[
|
| 72 |
+
merged["delay_at_checkout_in_minutes"] > merged["time_delta_with_previous_rental_in_minutes"]
|
| 73 |
+
]
|
| 74 |
+
st.metric("Conflits stricts :", len(conflict_strict))
|
| 75 |
+
st.metric("Moyenne retard précédent (conflits seulement) :", conflict_strict["delay_at_checkout_in_minutes"].mean().round(2))
|
| 76 |
|
| 77 |
st.markdown("""
|
| 78 |
👉 Parmi les **229 annulations liées à une location précédente**,
|
| 79 |
+
**37** sont dues à un **retard allant au delà de l'heure de début de la prochaine location.
|
| 80 |
Ces retards sont très longs (~4h15 en moyenne).
|
| 81 |
""")
|
| 82 |
|
| 83 |
+
# Cas "conflit -30min"
|
| 84 |
+
conflict_minus30 = merged[
|
| 85 |
+
merged["delay_at_checkout_in_minutes"] > merged["time_delta_with_previous_rental_in_minutes"] - 30
|
| 86 |
+
]
|
| 87 |
+
|
| 88 |
+
# Cas "conflit -60min"
|
| 89 |
+
conflict_minus60 = merged[
|
| 90 |
+
merged["delay_at_checkout_in_minutes"] > merged["time_delta_with_previous_rental_in_minutes"] - 60
|
| 91 |
+
]
|
| 92 |
+
|
| 93 |
+
conflict_minus90 = merged[
|
| 94 |
+
merged["delay_at_checkout_in_minutes"] > merged["time_delta_with_previous_rental_in_minutes"] - 90
|
| 95 |
+
]
|
| 96 |
+
|
| 97 |
+
conflict_minus180 = merged[
|
| 98 |
+
merged["delay_at_checkout_in_minutes"] > merged["time_delta_with_previous_rental_in_minutes"] - 180
|
| 99 |
+
]
|
| 100 |
+
|
| 101 |
+
# Création d'une liste de résultats
|
| 102 |
+
results = [
|
| 103 |
+
{"Buffer": "-30 min", "Conflits": len(conflict_minus30), "Moyenne retard (min)": conflict_minus30["delay_at_checkout_in_minutes"].mean()},
|
| 104 |
+
{"Buffer": "-60 min", "Conflits": len(conflict_minus60), "Moyenne retard (min)": conflict_minus60["delay_at_checkout_in_minutes"].mean()},
|
| 105 |
+
{"Buffer": "-90 min", "Conflits": len(conflict_minus90), "Moyenne retard (min)": conflict_minus90["delay_at_checkout_in_minutes"].mean()},
|
| 106 |
+
{"Buffer": "-180 min", "Conflits": len(conflict_minus180), "Moyenne retard (min)": conflict_minus180["delay_at_checkout_in_minutes"].mean()},
|
| 107 |
+
]
|
| 108 |
+
df_conflicts = pd.DataFrame(results)
|
| 109 |
+
|
| 110 |
+
st.dataframe(df_conflicts)
|
| 111 |
+
|
| 112 |
+
st.markdown("""Si on ajoute un 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).
|
| 113 |
+
Avec un buffer de 60 minutes, seulement 3 cas en plus → ce sont donc des situations rares mais critiques.
|
| 114 |
+
En élargissant à 90 minutes, on ajoute encore 7 cas.""")
|
| 115 |
+
|
| 116 |
+
|
| 117 |
+
|
| 118 |
+
|
| 119 |
# === SECTION 3 : IMPACT DES BUFFERS ===
|
| 120 |
st.header("⏳ Simulation de buffer entre locations")
|
| 121 |
|
data/get_around_pricing_project.csv
DELETED
|
The diff for this file is too large to render.
See raw diff
|
|
|