# import altair as alt # import numpy as np # import pandas as pd # import streamlit as st # """ # # Welcome to Streamlit! # Edit `/streamlit_app.py` to customize this app to your heart's desire :heart:. # If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community # forums](https://discuss.streamlit.io). # In the meantime, below is an example of what you can do with just a few lines of code: # """ # num_points = st.slider("Number of points in spiral", 1, 10000, 1100) # num_turns = st.slider("Number of turns in spiral", 1, 300, 31) # indices = np.linspace(0, 1, num_points) # theta = 2 * np.pi * num_turns * indices # radius = indices # x = radius * np.cos(theta) # y = radius * np.sin(theta) # df = pd.DataFrame({ # "x": x, # "y": y, # "idx": indices, # "rand": np.random.randn(num_points), # }) # st.altair_chart(alt.Chart(df, height=700, width=700) # .mark_point(filled=True) # .encode( # x=alt.X("x", axis=None), # y=alt.Y("y", axis=None), # color=alt.Color("idx", legend=None, scale=alt.Scale()), # size=alt.Size("rand", legend=None, scale=alt.Scale(range=[1, 150])), # )) # Import des bibliothéques import streamlit as st import pandas as pd import pickle import matplotlib.pyplot as plt from dotenv import load_dotenv import os import io from io import StringIO import boto3 import numpy as np import shap from sklearn.linear_model import LinearRegression from langchain_mistralai import ChatMistralAI from langchain_core.output_parsers import StrOutputParser # Charge les variables d'environnement load_dotenv("secrets.env") # Initialise le client S3 s3 = boto3.client( 's3', aws_access_key_id=os.getenv("AWS_ACCESS_KEY_ID"), aws_secret_access_key=os.getenv("AWS_SECRET_ACCESS_KEY"), region_name="eu-west-3" ) # 1. Charge df_dummies_2019.csv → Pour les VALEURS PAR DÉFAUT des sliders obj_dummies = s3.get_object(Bucket="mygeodechet", Key="df_dummies_2019.csv") dummies_data = obj_dummies['Body'].read() df = pd.read_csv(io.BytesIO(dummies_data)).drop(columns=["Unnamed: 0"], errors="ignore") # 2. Charge df_reduced.csv → Pour les PRÉDICTIONS (input des modèles) obj_reduced = s3.get_object(Bucket="mygeodechet", Key="df_reduced.csv") reduced_data = obj_reduced['Body'].read() observed_df = pd.read_csv(io.BytesIO(reduced_data)).drop(columns=["Unnamed: 0"], errors="ignore") # # 1. Charge le CSV (df_dummies_2019.csv) # obj_csv = s3.get_object(Bucket="mygeodechet", Key="df_dummies_2019.csv") # csv_data = obj_csv['Body'].read() # Lit le contenu binaire # df = pd.read_csv(io.BytesIO(csv_data)).drop(columns=["Unnamed: 0"], errors="ignore") # # 2. Charge l'Excel (data_wip_v5.xlsx) # obj_excel = s3.get_object(Bucket="mygeodechet", Key="data_wip_v5.xlsx") # excel_data = obj_excel['Body'].read() # Lit le contenu binaire # observed_df = pd.read_excel(io.BytesIO(excel_data)) # Utilise BytesIO # # Chargement des données # df = pd.read_csv("https://mygeodechet.s3.eu-west-3.amazonaws.com/df_dummies_2019.csv").drop(columns=["Unnamed: 0"], errors="ignore") # observed_df = pd.read_excel("https://mygeodechet.s3.eu-west-3.amazonaws.com/data_wip_v5.xlsx") # liste des départements présents dans les colonnes du df, sans le préfixe "Département_". departements = [col.replace("Département_", "") for col in df.columns if col.startswith("Département_")] # Mise en page st.set_page_config(layout="wide") st.markdown("

♻️ Simulateur de production de déchets par département

", unsafe_allow_html=True) # Titre + Choix département alignés top_col1, top_col2 = st.columns([1, 2]) with top_col1: st.markdown("

📍 Choix du département

", unsafe_allow_html=True) with top_col2: st.markdown("

📈 Comparaison entre valeurs observées et prédites

", unsafe_allow_html=True) # Séparation en colonnes top_input_col, chart_col = st.columns([1, 2]) with top_input_col: selected_dept = st.selectbox("Sélectionner un département", sorted(departements), index=sorted(departements).index("Ain") if "Ain" in departements else 0) row_default = df[df[f"Département_{selected_dept}"] == 1].iloc[0] default_dict = row_default.to_dict() st.subheader("⚙️ Paramètres modifiables") form_input = {} categories = { "📊 Population": [ "densité", "pop_globale", "tranche_age_0-24", "tranche_age_25-59", "tranche_age_60+", "csp1_agriculteurs", "csp2_artisans_commerçant_chef_entreprises", "csp3_cadres_professions_intellectuelles", "csp4_professions_intermédiaires", "csp5_employés", "csp6_ouvriers", "csp7_retraités", "csp8_sans_activité" ], "🏭 Activité économique": [ "nb_salaries_secteur_agricole", "nb_salaries_secteur_industrie", "nb_salaries_secteur_service", "nbre_entreprises", "nbre_entreprises_agricole", "nbre_entreprises_industrie", "nbre_entreprises_service" ], "🗑️ Déchets": [ "tonnage_dechet_produit", "Total_autres_dechets", "Déblais_gravats", "Déchets_verts", "Encombrants", "Matériaux_recyclables" ] } for category_name, variables in categories.items(): with st.expander(category_name, expanded=True): for var in variables: if var in default_dict: col_slider, col_input = st.columns([2, 1]) with col_slider: slider_value = st.slider( f"🔧 {var}", min_value=float(default_dict[var]) * 0, max_value=float(default_dict[var]) * 1.5, value=float(default_dict[var]), step=1.0, key=f"slider_{var}" ) with col_input: text_val = st.text_input(f"{var} (manuel)", value=str(slider_value), key=f"text_{var}") try: form_input[var] = float(text_val) except ValueError: form_input[var] = slider_value input_df = pd.DataFrame([form_input]) input_df_complete = row_default.to_frame().T.copy() for col in input_df.columns: if col in input_df_complete.columns: input_df_complete.at[input_df_complete.index[0], col] = input_df.at[0, col] with chart_col: st.markdown("
", unsafe_allow_html=True) btn_col = st.columns([3, 2, 3])[1] with btn_col: run_eval = st.button("🔍 Lancer l'évaluation") st.markdown("
", unsafe_allow_html=True) model_paths = { "Déblais et Gravats": "src/model_paths/model_ols_Déblais_gravats.pkl", "Déchets verts": "src/model_paths/model_ols_Déchets_verts.pkl", "Encombrants": "src/model_paths/model_ols_Encombrants.pkl", "Matériaux recyclables": "src/model_paths/model_ols_Matériaux_recyclables.pkl", "Total autres déchets": "src/model_paths/model_ols_Total_autres_dechets.pkl" } col_mapping = { "Déblais et Gravats": "Déblais_gravats", "Déchets verts": "Déchets_verts", "Encombrants": "Encombrants", "Matériaux recyclables": "Matériaux_recyclables", "Total autres déchets": "Total_autres_dechets" } valeurs_observees = [] valeurs_predites = [] labels = [] if run_eval: for typologie, path in model_paths.items(): try: with open(path, "rb") as f: model = pickle.load(f) # expected_cols = model.model.exog_names # if "const" in expected_cols and "const" not in input_df_complete.columns: # input_df_complete["const"] = 1.0 # prediction = max(0, model.predict(input_df_complete[expected_cols]).iloc[0]) prediction = max(0, model.predict(input_df_complete).iloc[0]) valeurs_predites.append(prediction) labels.append(typologie) filtered = observed_df[ (observed_df["Département"] == selected_dept) & (observed_df["année"] == 2019) ] excel_col = col_mapping.get(typologie) if not filtered.empty and excel_col in filtered.columns: valeurs_observees.append(filtered[excel_col].values[0]) else: valeurs_observees.append(0.0) except Exception as e: st.error(f"Erreur avec le modèle {typologie}") st.exception(e) if valeurs_observees and valeurs_predites: x = np.arange(len(labels)) width = 0.4 fig, ax = plt.subplots(figsize=(10, 6)) bars1 = ax.bar(x - width / 2, valeurs_observees, width, label='Observé (2019)', color='steelblue') bar_colors = [(1, 0, 0, 0.6) if pred > obs else (0, 0.6, 0, 0.6) for pred, obs in zip(valeurs_predites, valeurs_observees)] bars2 = ax.bar(x + width / 2, valeurs_predites, width, label='Prévision', color=bar_colors) for i in range(len(labels)): ax.text(x[i] - width / 2, valeurs_observees[i] + max(valeurs_observees) * 0.01, f"{valeurs_observees[i]:,.0f}", ha='center', va='bottom', fontsize=9) ax.text(x[i] + width / 2, valeurs_predites[i] + max(valeurs_predites) * 0.01, f"{valeurs_predites[i]:,.0f}", ha='center', va='bottom', fontsize=9) ax.set_ylabel("Tonnes") ax.set_title("Comparaison Observé vs Prédit") ax.set_xticks(x) ax.set_xticklabels(labels, rotation=45, ha='right') ax.legend() st.pyplot(fig)