import streamlit as st import pandas as pd import numpy as np import plotly.express as px import matplotlib.pyplot as plt import joblib import os st.set_page_config( page_title="Tableau de bord", layout="wide" ) # Chemin vers le dossier de ton script app.py BASE_DIR = os.path.dirname(__file__) # Chemin vers le CSV des prix DATA_URL_PRICE = os.path.join(BASE_DIR, "data", "get_around_pricing_project.csv") # Chemin vers le CSV des retards DATA_URL_DELAY = os.path.join(BASE_DIR, "data", "get_around_delay_analysis.csv") # Charger les CSVs df_price = pd.read_csv(DATA_URL_PRICE) df_delay = pd.read_csv(DATA_URL_DELAY) # DATA_URL_DELAY = ("../data/get_around_delay_analysis.csv") # DATA_URL_PRICE = ("../data/get_around_pricing_project.csv") st.title("TABLEAU DE BORD") # logo getaround st.image("https://upload.wikimedia.org/wikipedia/commons/8/8e/Getaround_%28Europe%29.png", width=300) st.text("Getaround, est une plateforme de location de voitures entre particuliers") # # Fonction pour charger les données avec cache # @st.cache_data # def load_delay_data(nrows=None): # return pd.read_csv(DATA_URL_DELAY, nrows=nrows) # @st.cache_data # def load_price_data(nrows=None): # return pd.read_csv(DATA_URL_PRICE, nrows=nrows) # # Chargement des données # df_delay = load_delay_data() # df_price = load_price_data() # # Charger les données # data = load_data() # Paramétre des titres def st_titre(text): st.markdown(f"""
{text}
""", unsafe_allow_html=True) # Informations generale delay st_titre("Informations générales Jeu de données 'Retards'") total_locations = df_delay.shape[0] # Toutes les locations ended = df_delay[df_delay['state'] == 'ended'] canceled = df_delay[df_delay['state'] == 'canceled'] ended_count = ended.shape[0] # Locations terminées canceled_count = canceled.shape[0] # Locations annulées type=df_delay['checkin_type'].value_counts().reset_index() type.columns=['Type','Count'] # Initialiser à 0 mobile_count = 0 connect_count = 0 # Parcourir le DataFrame 'type' for i, row in type.iterrows(): if row['Type'] == 'mobile': mobile_count = row['Count'] elif row['Type'] == 'connect': connect_count = row['Count'] # Affichage des KPI côte à côte col1, col2, col3, col4, col5 = st.columns(5) col1.metric("Total locations", total_locations) col2.metric("Locations terminées", ended_count) col3.metric("Locations annulées", canceled_count) col4.metric("Locations sur mobile", mobile_count) col5.metric("Locations connectées", connect_count ) # Informations generale price st_titre("Informations générales Jeu de données 'Prix'") # Calcul des KPI pour le jeu de données Prix voiture_plus_louee = df_price['model_key'].mode()[0] carburant_plus_loue = df_price['fuel'].mode()[0] puissance_mediane = int(df_price['engine_power'].median()) prix_median = int(df_price['rental_price_per_day'].median()) modele_plus_loue = df_price['car_type'].mode()[0] # Traduction des types si nécessaire translation = { 'estate': 'Break', 'sedan': 'Berline', 'suv': 'SUV', 'hatchback': 'Compacte', 'subcompact': 'Sous-compacte', 'coupe': 'Coupé', 'convertible': 'Cabriolet', 'van': 'Van' } modele_plus_loue_fr = translation.get(modele_plus_loue, modele_plus_loue) # Affichage des KPI côte à côte col1, col2, col3, col4, col5 = st.columns(5) col1.metric("Voiture la plus louée", voiture_plus_louee) col2.metric("Carburant le plus utilisé", carburant_plus_loue.capitalize()) col3.metric("Puissance médiane (ch)", puissance_mediane) col4.metric("Prix médian (€)", prix_median) col5.metric("Type de véhicule le plus loué", modele_plus_loue_fr) # Analyse des retards st_titre("Analyse des retards en minutes") delay_real = ended[ended["delay_at_checkout_in_minutes"] > 0] q95 = delay_real["delay_at_checkout_in_minutes"].quantile(0.95) filtered = delay_real[delay_real["delay_at_checkout_in_minutes"] <= q95] num_delay= delay_real.shape[0] mean_delay = filtered["delay_at_checkout_in_minutes"].mean().round(0) median_delay = filtered["delay_at_checkout_in_minutes"].median() std_delay = round(filtered["delay_at_checkout_in_minutes"].std(),0) # Affichage des KPI côte à côte col1, col2, col3 = st.columns(3) col1.metric("Locations avec retards", num_delay) col2.metric("Retards moy", mean_delay) col3.metric("Retards médian", median_delay) # Analyse des seuils st_titre("Analyse interactive du seuil") seuil=[30, 60, 90, 120, 150, 180, 210, 240] resultat=[] nbr_car_delay_2_loc = len(ended.dropna(subset=['time_delta_with_previous_rental_in_minutes'])) for i in seuil: nbr_loc_bloquee = (ended['time_delta_with_previous_rental_in_minutes']=i).sum() pct_nbr_loc_ok = ((nbr_loc_ok / nbr_car_delay_2_loc) * 100).round(2) # Retards réels couverts (seulement pour les retards > 0) retards_reels = ended[ended['delay_at_checkout_in_minutes'] > 0] pct_retards_couverts = ((retards_reels['delay_at_checkout_in_minutes'] <= i).mean() * 100).round(2) # Ajouter les résultats à la liste resultat.append({ 'Seuil (min)': i, 'Locations bloquées': nbr_loc_bloquee, '% Locations bloquées': pct_nbr_loc_bloquee, 'Locations possibles' : nbr_loc_ok, '% Locations possibles': pct_nbr_loc_ok, '% Retards couverts': pct_retards_couverts, }) df_resultat = pd.DataFrame(resultat) # Calcul des seuils nbr_car_delay_2_loc = len(ended.dropna(subset=['time_delta_with_previous_rental_in_minutes'])) seuils = [30, 60, 90, 120, 150, 180, 210, 240] resultat = [] for s in seuils: nbr_loc_bloquee = (ended['time_delta_with_previous_rental_in_minutes'] < s).sum() nbr_loc_ok = (ended['time_delta_with_previous_rental_in_minutes'] >= s).sum() retards_reels = ended[ended['delay_at_checkout_in_minutes'] > 0] pct_retards_couverts = ((retards_reels['delay_at_checkout_in_minutes'] <= s).mean() * 100).round(2) pct_loc_bloquees = ((nbr_loc_bloquee / nbr_car_delay_2_loc) * 100).round(2) resultat.append({ 'Seuil (min)': s, 'Locations bloquées (%)': pct_loc_bloquees, 'Locations possibles': nbr_loc_ok, 'Retards couverts (%)': pct_retards_couverts }) df_resultat = pd.DataFrame(resultat) # Slider pour seuil seuil = st.slider( "Sélectionnez le seuil en minutes :", min_value=int(df_resultat['Seuil (min)'].min()), max_value=int(df_resultat['Seuil (min)'].max()), value=60, step=30 ) # Récupérer la ligne correspondant au seuil row = df_resultat[df_resultat['Seuil (min)'] == seuil].iloc[0] # Calcul du nombre réel de retards couverts num_retards = len(ended[ended["delay_at_checkout_in_minutes"] > 0]) retards_couverts_nb = int((row['Retards couverts (%)'] / 100) * num_retards) loc_bloquees_nb = int((row['Locations bloquées (%)'] / 100) * nbr_car_delay_2_loc) # KPI avec style kpi_style = """
{title}

{value}

""" col1, col2, col3, col4, col5 = st.columns(5) col1.markdown(kpi_style.format(title="Seuil sélectionné (min)", value=seuil), unsafe_allow_html=True) col2.markdown(kpi_style.format(title="Retards couverts (%)", value=f"{row['Retards couverts (%)']:.2f}"), unsafe_allow_html=True) col3.markdown(kpi_style.format(title="Retards couverts (nb)", value=retards_couverts_nb), unsafe_allow_html=True) col4.markdown(kpi_style.format(title="Locations bloquées (%)", value=f"{row['Locations bloquées (%)']:.2f}"), unsafe_allow_html=True) col5.markdown(kpi_style.format(title="Locations bloquées (nb)", value=loc_bloquees_nb), unsafe_allow_html=True) # Graphique interactif fig = px.line( df_resultat, x='Seuil (min)', y=['Retards couverts (%)', 'Locations bloquées (%)'], title='Compromis entre retards couverts et locations bloquées' ) fig.add_vline(x=seuil, line_dash="dash", line_color="green", annotation_text=f"Seuil {seuil} min") st.plotly_chart(fig, use_container_width=True) # Prédiction du prix # # Chargement du modèle # model = joblib.load("../model/modele_xgb_getaround.pkl") # Chemin vers le dossier de ton script app.py BASE_DIR = os.path.dirname(__file__) # Chemin vers le dossier du modèle MODEL_PATH = os.path.join(BASE_DIR, "model", "modele_xgb_getaround.pkl") # Charger le modèle model = joblib.load(MODEL_PATH) st_titre("Estimation du prix de location") # Créer 2 colonnes pour les sliders numériques col1, col2 = st.columns(2) with col1: mileage = st.slider("Kilométrage (km)", min_value=0, max_value=300_000, step=1000, value=50_000) with col2: engine_power = st.slider("Puissance moteur (ch)", min_value=40, max_value=300, step=5, value=100) # Créer 4 colonnes pour selectbox col1, col2, col3, col4 = st.columns(4) with col1: model_key = st.selectbox("Modèle", sorted(df_price["model_key"].unique())) with col2: fuel = st.selectbox("Carburant", sorted(df_price["fuel"].unique())) with col3: paint_color = st.selectbox("Couleur", sorted(df_price["paint_color"].unique())) #traduction en fr car_type_options = [translation[ct] for ct in sorted(df_price["car_type"].unique())] # Selectbox en français with col4: car_type_fr = st.selectbox("Type de voiture", car_type_options) # Créer 4 colonnes pour la première ligne de checkbox col1, col2, col3, col4 = st.columns(4) with col1: private_parking_available = st.checkbox("Parking privé disponible") with col2: has_gps = st.checkbox("GPS") with col3: has_air_conditioning = st.checkbox("Climatisation") with col4: automatic_car = st.checkbox("Boîte automatique") # Créer 4 colonnes pour la deuxième ligne col5, col6, col7, col8 = st.columns(4) with col5: has_getaround_connect = st.checkbox("Getaround Connect") with col6: has_speed_regulator = st.checkbox("Régulateur de vitesse") with col7: winter_tires = st.checkbox("Pneus hiver") # col8 peut rester vide si tu n'as pas de 4ème checkbox with col8: st.write("") # juste pour laisser la colonne vide # Création du DataFrame d'entrée avec toutes les colonnes input_data = pd.DataFrame([{ "mileage": mileage, "engine_power": engine_power, "fuel": fuel, "car_type": car_type_fr, "model_key": model_key, "paint_color": paint_color, "private_parking_available": int(private_parking_available), "has_gps": int(has_gps), "has_air_conditioning": int(has_air_conditioning), "automatic_car": int(automatic_car), "has_getaround_connect": int(has_getaround_connect), "has_speed_regulator": int(has_speed_regulator), "winter_tires": int(winter_tires) }]) # Prédiction price_pred = model.predict(input_data)[0] # Affichage st.write(f"### Estimation du prix par jour : {price_pred:.2f} $ ")