import pandas as pd import numpy as np import plotly.express as px import plotly.graph_objects as go from plotly.subplots import make_subplots import folium from streamlit_folium import folium_static import streamlit as st def create_price_distribution_chart(data, predicted_price=None): """ Crée un histogramme de la distribution des prix avec la prédiction """ if data is None or 'price' not in data.columns: return None fig = px.histogram( data, x='price', nbins=50, title=" Distribution des Prix Immobiliers", labels={'price': 'Prix ($)', 'count': 'Nombre de propriétés'}, color_discrete_sequence=['#3498db'] ) # Ajouter une ligne verticale pour la prédiction if predicted_price is not None: fig.add_vline( x=predicted_price, line_dash="dash", line_color="red", annotation_text=f"Votre prédiction: ${predicted_price:,.0f}", annotation_position="top right" ) fig.update_layout( template="plotly_dark", plot_bgcolor='rgba(0,0,0,0)', paper_bgcolor='rgba(0,0,0,0)', font=dict(color='#D4DCFF'), title_font_size=20, showlegend=False ) return fig def create_feature_impact_chart(data, feature_name, predicted_price=None): """ Crée un graphique montrant l'impact d'une caractéristique sur le prix """ if data is None or feature_name not in data.columns or 'price' not in data.columns: return None # Calculer la moyenne des prix par valeur de la caractéristique feature_impact = data.groupby(feature_name)['price'].mean().reset_index() fig = px.line( feature_impact, x=feature_name, y='price', title=f" Impact de {feature_name} sur le Prix", labels={'price': 'Prix Moyen ($)', feature_name: feature_name.title()}, markers=True ) # Ajouter une ligne horizontale pour la prédiction if predicted_price is not None: fig.add_hline( y=predicted_price, line_dash="dash", line_color="red", annotation_text=f"Votre prédiction: ${predicted_price:,.0f}", annotation_position="top right" ) fig.update_layout( template="plotly_dark", plot_bgcolor='rgba(0,0,0,0)', paper_bgcolor='rgba(0,0,0,0)', font=dict(color='#D4DCFF'), title_font_size=16, title=dict( x=0.5, xanchor='center', y=0.95, yanchor='top', pad=dict(t=20, b=30, l=20, r=20) ) ) return fig def create_price_vs_area_chart(data, predicted_price=None, predicted_area=None): """ Crée un graphique de dispersion prix vs surface """ if data is None or 'sqft_living' not in data.columns or 'price' not in data.columns: return None fig = px.scatter( data, x='sqft_living', y='price', title=" Prix vs Surface Habitable", labels={'sqft_living': 'Surface Habitable (pieds²)', 'price': 'Prix ($)'}, opacity=0.6, color_discrete_sequence=['#3498db'] ) # Ajouter le point de prédiction if predicted_price is not None and predicted_area is not None: fig.add_scatter( x=[predicted_area], y=[predicted_price], mode='markers', marker=dict(size=15, color='red', symbol='star'), name='Votre prédiction', showlegend=True ) fig.update_layout( template="plotly_dark", plot_bgcolor='rgba(0,0,0,0)', paper_bgcolor='rgba(0,0,0,0)', font=dict(color='#D4DCFF'), title_font_size=16 ) return fig def create_correlation_heatmap(data): """ Crée une heatmap de corrélation entre les caractéristiques """ if data is None: return None # Sélectionner les colonnes numériques numeric_cols = data.select_dtypes(include=[np.number]).columns if len(numeric_cols) < 2: return None correlation_matrix = data[numeric_cols].corr() fig = px.imshow( correlation_matrix, title=" Matrice de Corrélation des Caractéristiques", color_continuous_scale='RdBu', aspect="auto" ) fig.update_layout( template="plotly_dark", plot_bgcolor='rgba(0,0,0,0)', paper_bgcolor='rgba(0,0,0,0)', font=dict(color='#D4DCFF'), title_font_size=16 ) return fig def create_interactive_map(data, lat=None, long=None, predicted_price=None): """ Crée une carte interactive avec les propriétés et la prédiction """ if data is None or 'lat' not in data.columns or 'long' not in data.columns: return None # Calculer le centre de la carte center_lat = data['lat'].mean() if lat is None else lat center_long = data['long'].mean() if long is None else long # Créer la carte m = folium.Map( location=[center_lat, center_long], zoom_start=10, tiles='cartodbpositron' ) # Ajouter les propriétés existantes (échantillon pour éviter la surcharge) sample_data = data.sample(min(100, len(data))) for idx, row in sample_data.iterrows(): folium.CircleMarker( location=[row['lat'], row['long']], radius=3, popup=f"Prix: ${row['price']:,.0f}
Surface: {row['sqft_living']} pieds²", color='blue', fill=True, fillOpacity=0.7 ).add_to(m) # Ajouter la prédiction si disponible if lat is not None and long is not None and predicted_price is not None: folium.Marker( location=[lat, long], popup=f"Votre prédiction: ${predicted_price:,.0f}", icon=folium.Icon(color='red', icon='star') ).add_to(m) return m def create_price_by_zipcode_chart(data, predicted_price=None, predicted_zipcode=None): """ Crée un graphique des prix moyens par code postal """ if data is None or 'zipcode' not in data.columns or 'price' not in data.columns: return None # Calculer le prix moyen par code postal zipcode_prices = data.groupby('zipcode')['price'].mean().reset_index() zipcode_prices = zipcode_prices.sort_values('price', ascending=False).head(20) fig = px.bar( zipcode_prices, x='zipcode', y='price', title=" Prix Moyen par Code Postal (Top 20)", labels={'price': 'Prix Moyen ($)', 'zipcode': 'Code Postal'}, color='price', color_continuous_scale='viridis' ) # Ajouter une ligne horizontale pour la prédiction if predicted_price is not None: fig.add_hline( y=predicted_price, line_dash="dash", line_color="red", annotation_text=f"Votre prédiction: ${predicted_price:,.0f}", annotation_position="top right" ) fig.update_layout( template="plotly_dark", plot_bgcolor='rgba(0,0,0,0)', paper_bgcolor='rgba(0,0,0,0)', font=dict(color='#D4DCFF'), title_font_size=16, xaxis_tickangle=-45, title=dict( x=0.5, xanchor='center', y=0.95, yanchor='top', pad=dict(t=20, b=30, l=20, r=20) ) ) return fig def create_comparison_dashboard(data, predicted_price, input_features): """ Crée un tableau de bord de comparaison """ if data is None: return None # Calculer les statistiques de comparaison stats = { 'Prix moyen du marché': f"${data['price'].mean():,.0f}", 'Prix médian du marché': f"${data['price'].median():,.0f}", 'Votre prédiction': f"${predicted_price:,.0f}", 'Différence avec la moyenne': f"${predicted_price - data['price'].mean():,.0f}", 'Pourcentage vs moyenne': f"{((predicted_price / data['price'].mean()) - 1) * 100:.1f}%" } # Créer un graphique de comparaison comparison_data = pd.DataFrame({ 'Métrique': ['Prix Moyen', 'Prix Médian', 'Votre Prédiction'], 'Prix': [data['price'].mean(), data['price'].median(), predicted_price] }) fig = px.bar( comparison_data, x='Métrique', y='Prix', title=" Comparaison avec le Marché", color='Métrique', color_discrete_map={ 'Prix Moyen': '#3498db', 'Prix Médian': '#2ecc71', 'Votre Prédiction': '#e74c3c' } ) fig.update_layout( template="plotly_dark", plot_bgcolor='rgba(0,0,0,0)', paper_bgcolor='rgba(0,0,0,0)', font=dict(color='#D4DCFF'), title_font_size=16, showlegend=False, title=dict( x=0.5, xanchor='center', y=0.95, yanchor='top', pad=dict(t=20, b=30, l=20, r=20) ) ) return fig, stats