ericjedha commited on
Commit
42542c5
·
verified ·
1 Parent(s): 3c41440

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +130 -11
app.py CHANGED
@@ -5,7 +5,6 @@ import plotly.graph_objects as go
5
  from sqlalchemy import create_engine, text
6
  from datetime import datetime, timedelta
7
  import os
8
- from skimpy import skim
9
 
10
  # ========================== CONFIGURATION ==========================
11
  st.set_page_config(
@@ -274,19 +273,139 @@ def page_eda():
274
  st.error("Impossible de charger les données")
275
  return
276
 
277
- # ========================== 1. RÉSUMÉ AVEC SKIMPY ==========================
278
- st.markdown("## 📋 Résumé des données avec Skimpy")
279
 
280
- # Capturer la sortie de skim dans un buffer
281
- import io
282
- from contextlib import redirect_stdout
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
283
 
284
- buffer = io.StringIO()
285
- with redirect_stdout(buffer):
286
- skim(df)
 
 
 
 
287
 
288
- skim_output = buffer.getvalue()
289
- st.text(skim_output)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
290
 
291
  st.markdown("---")
292
 
 
5
  from sqlalchemy import create_engine, text
6
  from datetime import datetime, timedelta
7
  import os
 
8
 
9
  # ========================== CONFIGURATION ==========================
10
  st.set_page_config(
 
273
  st.error("Impossible de charger les données")
274
  return
275
 
276
+ # ========================== 1. RÉSUMÉ DU DATASET ==========================
277
+ st.markdown("## 📋 Résumé du Dataset")
278
 
279
+ # Informations générales
280
+ col1, col2, col3, col4 = st.columns(4)
281
+ with col1:
282
+ st.metric("📊 Nombre de lignes", f"{len(df):,}")
283
+ with col2:
284
+ st.metric("📋 Nombre de colonnes", f"{len(df.columns)}")
285
+ with col3:
286
+ st.metric("💾 Taille mémoire", f"{df.memory_usage(deep=True).sum() / 1024**2:.2f} MB")
287
+ with col4:
288
+ duplicates = df.duplicated().sum()
289
+ st.metric("🔄 Doublons", f"{duplicates:,}")
290
+
291
+ # Valeurs manquantes
292
+ st.markdown("### 🔍 Valeurs manquantes")
293
+ missing = df.isnull().sum()
294
+ missing_pct = (missing / len(df) * 100).round(2)
295
+ missing_df = pd.DataFrame({
296
+ 'Colonne': missing.index,
297
+ 'Manquantes': missing.values,
298
+ 'Pourcentage': missing_pct.values
299
+ })
300
+ missing_df = missing_df[missing_df['Manquantes'] > 0].sort_values('Manquantes', ascending=False)
301
+
302
+ if not missing_df.empty:
303
+ fig_missing = px.bar(
304
+ missing_df,
305
+ x='Colonne',
306
+ y='Pourcentage',
307
+ title='Pourcentage de valeurs manquantes par colonne',
308
+ color='Pourcentage',
309
+ color_continuous_scale='Reds',
310
+ text=missing_df['Pourcentage'].apply(lambda x: f"{x:.1f}%")
311
+ )
312
+ fig_missing.update_layout(showlegend=False, height=400)
313
+ st.plotly_chart(fig_missing, use_container_width=True)
314
+ else:
315
+ st.success("✅ Aucune valeur manquante dans le dataset !")
316
+
317
+ # Statistiques descriptives
318
+ st.markdown("### 📊 Statistiques descriptives (Variables numériques)")
319
 
320
+ # Sélecteur de colonnes numériques
321
+ numeric_cols_all = df.select_dtypes(include=['float64', 'int64']).columns.tolist()
322
+ selected_stats_cols = st.multiselect(
323
+ "Choisissez les colonnes à analyser",
324
+ numeric_cols_all,
325
+ default=numeric_cols_all[:5]
326
+ )
327
 
328
+ if selected_stats_cols:
329
+ stats_df = df[selected_stats_cols].describe().T
330
+ stats_df['missing'] = df[selected_stats_cols].isnull().sum().values
331
+ stats_df['missing_pct'] = (stats_df['missing'] / len(df) * 100).round(2)
332
+
333
+ # Formater pour l'affichage
334
+ display_stats = stats_df[['count', 'mean', 'std', 'min', '25%', '50%', '75%', 'max', 'missing', 'missing_pct']]
335
+ display_stats.columns = ['Count', 'Moyenne', 'Écart-type', 'Min', 'Q1', 'Médiane', 'Q3', 'Max', 'Manquantes', 'Manquantes (%)']
336
+
337
+ st.dataframe(
338
+ display_stats.style.format({
339
+ 'Moyenne': '{:.2f}',
340
+ 'Écart-type': '{:.2f}',
341
+ 'Min': '{:.2f}',
342
+ 'Q1': '{:.2f}',
343
+ 'Médiane': '{:.2f}',
344
+ 'Q3': '{:.2f}',
345
+ 'Max': '{:.2f}',
346
+ 'Manquantes (%)': '{:.2f}'
347
+ }),
348
+ use_container_width=True
349
+ )
350
+
351
+ # Distribution des variables numériques
352
+ st.markdown("### 📈 Distributions des variables numériques")
353
+ selected_dist = st.selectbox("Choisissez une variable à visualiser", selected_stats_cols)
354
+
355
+ col_hist, col_box = st.columns(2)
356
+
357
+ with col_hist:
358
+ fig_hist = px.histogram(
359
+ df,
360
+ x=selected_dist,
361
+ nbins=50,
362
+ title=f"Distribution de {selected_dist}",
363
+ color_discrete_sequence=['#636EFA']
364
+ )
365
+ fig_hist.update_layout(showlegend=False, height=350)
366
+ st.plotly_chart(fig_hist, use_container_width=True)
367
+
368
+ with col_box:
369
+ fig_box = px.box(
370
+ df,
371
+ y=selected_dist,
372
+ title=f"Box plot de {selected_dist}",
373
+ color_discrete_sequence=['#636EFA']
374
+ )
375
+ fig_box.update_layout(showlegend=False, height=350)
376
+ st.plotly_chart(fig_box, use_container_width=True)
377
+
378
+ # Variables catégorielles
379
+ st.markdown("### 🏷️ Variables catégorielles")
380
+ categorical_cols = df.select_dtypes(include=['object', 'category']).columns.tolist()
381
+
382
+ if categorical_cols:
383
+ selected_cat = st.selectbox("Choisissez une variable catégorielle", categorical_cols)
384
+
385
+ value_counts = df[selected_cat].value_counts().head(15)
386
+
387
+ col_bar, col_info = st.columns([2, 1])
388
+
389
+ with col_bar:
390
+ fig_cat = px.bar(
391
+ x=value_counts.index,
392
+ y=value_counts.values,
393
+ title=f"Top 15 valeurs de {selected_cat}",
394
+ labels={'x': selected_cat, 'y': 'Count'},
395
+ color=value_counts.values,
396
+ color_continuous_scale='Blues'
397
+ )
398
+ fig_cat.update_layout(showlegend=False, height=400)
399
+ st.plotly_chart(fig_cat, use_container_width=True)
400
+
401
+ with col_info:
402
+ st.markdown("#### Statistiques")
403
+ st.metric("Valeurs uniques", df[selected_cat].nunique())
404
+ st.metric("Valeur la plus fréquente", value_counts.index[0])
405
+ st.metric("Fréquence max", f"{value_counts.values[0]:,}")
406
+ st.metric("% de la plus fréquente", f"{(value_counts.values[0] / len(df) * 100):.1f}%")
407
+ else:
408
+ st.info("Aucune variable catégorielle détectée")
409
 
410
  st.markdown("---")
411