LAST / app.py
LEWOPO's picture
Update app.py
ac4d73c verified
raw
history blame
12.4 kB
import streamlit as st
from streamlit_option_menu import option_menu
import pandas as pd
import pickle
import lime
import lime.lime_tabular
import streamlit.components.v1 as components
from PIL import Image
import seaborn as sns
import matplotlib.pyplot as plt
# 1=sidebar menu, 2=horizontal menu, 3=horizontal menu w/ custom menu
EXAMPLE_NO = 3
st.set_page_config(layout='wide')
st.markdown("""
<style>
.block-container {
padding-top: 2rem;
padding-bottom: 0rem;
padding-left: 1rem;
padding-right: 1rem;
}
</style>
""", unsafe_allow_html=True)
def streamlit_menu(example=1):
if example == 1:
# 1. as sidebar menu
with st.sidebar:
selected = option_menu(
menu_title="Main Menu", # required
options=["Acceuil", "Statistique", "Prédiction"], # required
icons=["house", "book", "bow_and_arrow"], # optional
menu_icon="cast", # optional
default_index=0, # optional
)
return selected
if example == 2:
# 2. horizontal menu w/o custom style
selected = option_menu(
menu_title=None, # required
options=["Acceuil", "Statistique", "Prédiction"], # required
icons=["house", "book", "envelope"], # optional
menu_icon="cast", # optional
default_index=0, # optional
orientation="horizontal",
)
return selected
if example == 3:
# 2. horizontal menu with custom style
selected = option_menu(
menu_title=None, # required
options=["Acceuil", "Statistique", "Prédiction"], # required
icons=["house", "book", "envelope"], # optional
menu_icon="cast", # optional
default_index=0, # optional
orientation="horizontal",
styles={
"container": {"padding": "0!important", "background-color": "#fafafa"},
"icon": {"color": "orange", "font-size": "25px"},
"nav-link": {
"font-size": "25px",
"text-align": "left",
"margin": "0px",
"--hover-color": "#eee",
},
"nav-link-selected": {"background-color": "skyblue"},
},
)
return selected
selected = streamlit_menu(example=EXAMPLE_NO)
if selected == "Prédiction":
# st.title(f"You have selected {selected}")
# Load your trained model
with open('model.pkl', 'rb') as file:
model = pickle.load(file)
obesity_mapping = {
0: 'Normal',
1: 'Surpoid\Obése'
}
# Define the input features for the user to input
def user_input_features():
age = st.number_input('Age:',min_value=8, max_value=19, value=19, step=1, format="%d")
classe = st.radio('Classe_', ('Primaire','Secondaire'))
Zone = st.radio('zone', ('Rurale', 'Urbaine'))
Voler = st.radio('Voler', ('Oui', 'Non'))
Diversité = st.radio('Diversité', ('Mauvaise', 'Bonne'))
Region = st.selectbox(
'Region de ',
('Nord_ouest' ,'Sud_ouest', 'Ouest')
)
Source_eau=st.selectbox(
'Provenence ',
('Camwater','Eau_de_surface','forage','Puits','Eau_minérale')
)
Sexe = st.radio('Genre', ('F', 'M'))
Zone = 1 if Zone == 'Rurale' else 0
classe = 1 if classe == 'Primaire' else 0
Diversité = 1 if Diversité == 'Mauvaise' else 0
Region = ['Nord_ouest' ,'Sud_ouest', 'Ouest'].index(Region)
Source_eau=['Camwater','Eau_de_surface','forage','Puits','Eau_minérale'].index(Source_eau)
sex_f = 1 if Sexe == 'F' else 0
sex_m = 1 if Sexe == 'M' else 0
data = {
'Region': Region,
'Zone': Zone,
'Classe': classe,
'Age': age,
'Diversité': Diversité,
'Voler': Voler,
'Source_eau':Source_eau,
'Genre_F': sex_f,
'Genre_M': sex_m
}
features = pd.DataFrame(data, index=[0])
return features
# st.title('Obesity App')
# Display the input fields
input_df = user_input_features()
# Convertir toutes les colonnes non numériques en numérique si possible
input_df = input_df.apply(pd.to_numeric, errors='coerce')
# Remplacer les NaN par une valeur arbitraire (par exemple 0) si nécessaire
input_df = input_df.fillna(0)
# Initialiser LIME
explainer = lime.lime_tabular.LimeTabularExplainer(
training_data=input_df.values, # Entraînement sur la base des données d'entrée
feature_names=input_df.columns,
class_names=[obesity_mapping[0], obesity_mapping[1]],
mode='classification'
)
# Predict button
if st.button('Predict'):
# Make a prediction
prediction = model.predict(input_df)
prediction_proba = model.predict_proba(input_df)[0]
data = {
'Statut nutritionnel': [obesity_mapping[i] for i in range(len(prediction_proba))],
'Probabilité': prediction_proba
}
# Create a dataframe to display the results
result_df = pd.DataFrame(data)
# Transpose the dataframe to have obesity types as columns and add a row header
result_df = result_df.T
result_df.columns = result_df.iloc[0]
result_df = result_df.drop(result_df.index[0])
result_df.index = ['Probability']
# Display the results in a table with proper formatting
st.table(result_df.style.format("{:.4f}"))
# Générer l'explication LIME pour l'individu
# exp = explainer.explain_instance(input_df.values[0], model.predict_proba, num_features=5)
# # Afficher les explications dans Streamlit
# st.subheader('Explication LIME')
# exp.show_in_notebook(show_table=True, show_all=False)
# st.write(exp.as_list())
# Générer l'explication LIME pour l'individu
exp = explainer.explain_instance(input_df.values[0], model.predict_proba, num_features=4)
# Récupérer l'explication LIME sous forme HTML
explanation_html = exp.as_html()
# Afficher l'explication LIME dans Streamlit
st.subheader('Explication LIME')
# Utiliser Streamlit pour afficher du HTML
components.html(explanation_html, height=800) # Ajuster la hauteur selon le contenu
if selected == "Acceuil":
avant_propos = """
<div style="background-color: white; padding: 20px; border-radius: 10px;
display: flex; justify-content: center; align-items: center;
height: 100vh; flex-direction: column;">
<h2 style="color: blue; text-align: center;">Avant-propos</h2>
<p style="color: blue; text-align: center; max-width: 800px;">
L'obésité est l'une des principales préoccupations de santé publique à travers le monde, avec des répercussions notables sur la qualité de vie et les coûts des soins de santé.
Dans un contexte où les maladies chroniques liées à l'obésité, telles que le diabète et les maladies cardiovasculaires, continuent de croître, il est impératif de développer des outils capables de prédire et de prévenir cette condition.
</p>
<p style="color: blue; text-align: center; max-width: 800px;">
L'application que nous présentons ici repose sur les technologies modernes de <strong>machine learning</strong> pour prédire le risque d'obésité à partir de divers facteurs liés au mode de vie,
aux habitudes alimentaires et aux caractéristiques individuelles. Cette solution, développée à l'aide de <strong>Streamlit</strong>, permet non seulement d'offrir une interface intuitive et accessible,
mais également d'analyser rapidement et précisément les données des utilisateurs afin d'anticiper les risques associés au surpoids.
</p>
<p style="color: blue; text-align: center; max-width: 800px;">
L'objectif principal de cette application est de fournir une aide à la décision pour les professionnels de santé, les chercheurs, et même les utilisateurs individuels
qui souhaitent comprendre et gérer leur risque personnel. En quelques clics, les utilisateurs peuvent explorer les facteurs influents et recevoir des prévisions basées sur des algorithmes avancés d'apprentissage automatique.
</p>
<p style="color: blue; text-align: center; max-width: 800px;">
Cette application est le fruit d'une volonté de concilier les avancées technologiques et l'impératif de santé publique qu'est la lutte contre l'obésité.
Nous espérons qu'elle contribuera à renforcer les actions de prévention et à offrir un support utile aux efforts de réduction des taux d'obésité.
</p>
</div>
"""
# Afficher le texte stylisé en bleu et centré sur un fond blanc
st.markdown(avant_propos, unsafe_allow_html=True)
# Ajouter un bouton qui redirige vers un site externe
url = "https://www.who.int/fr/news-room/fact-sheets/detail/obesity-and-overweight" # Remplacez par l'URL souhaitée
if st.button("pour plus d'informations"):
st.write(f"[Cliquez ici pour visiter le site]({url})")
if selected == "Statistique":
# Ouvrir l'image avec Pillow
#image = Image.open("az.JPEG")
# Redimensionner l'image (largeur, hauteur)
#image = image.resize((300, 200)) # Par exemple, 300x200 pixels
# Afficher l'image redimensionnée
#st.image(image, caption="Image redimensionnée", use_column_width=False)
# Titre de l'application
st.title("Visualisation des données avec Seaborn et Pandas")
# Charger le fichier CSV
uploaded_file = st.file_uploader("Choisissez un fichier", type=["csv", "xlsx", "json"])
if uploaded_file is not None:
# Lecture du fichier CSV
file_extension = uploaded_file.name.split('.')[-1]
if file_extension == 'csv':
# Lecture du fichier CSV
df = pd.read_csv(uploaded_file)
elif file_extension == 'xlsx':
# Lecture du fichier Excel
df = pd.read_excel(uploaded_file)
elif file_extension == 'json':
# Lecture du fichier JSON
df = pd.read_json(uploaded_file)
else:
st.error("Format de fichier non supporté!")
# Afficher le dataframe
st.write("Aperçu du dataset :")
st.write(df.head())
# Afficher les statistiques descriptives
st.write("Statistiques descriptives :")
st.write(df.describe())
# Sélection des variables pour les visualisations
numerical_columns = df.select_dtypes(include=['float64', 'int64']).columns.tolist()
categorical_columns = df.select_dtypes(include=['object', 'category']).columns.tolist()
# Distribution d'une variable
st.subheader("Distribution d'une variable numérique")
selected_column = st.selectbox("Choisissez une variable numérique", numerical_columns)
if st.button("Afficher la distribution"):
fig, ax = plt.subplots(figsize=(5, 6))
sns.histplot(df[selected_column], kde=True, ax=ax)
st.pyplot(fig)
# Scatter plot
st.subheader("Scatter Plot entre deux variables numériques")
x_axis = st.selectbox("Choisissez la variable pour l'axe X", numerical_columns)
y_axis = st.selectbox("Choisissez la variable pour l'axe Y", numerical_columns, key='scatter')
if st.button("Afficher le scatter plot"):
fig, ax = plt.subplots(figsize=(8, 4))
sns.scatterplot(x=df[x_axis], y=df[y_axis], ax=ax)
st.pyplot(fig)
# Boxplot
st.subheader("Boxplot d'une variable numérique par rapport à une variable catégorielle")
selected_categorical = st.selectbox("Choisissez une variable catégorielle", categorical_columns)
selected_numerical = st.selectbox("Choisissez une variable numérique", numerical_columns, key='boxplot')
if st.button("Afficher le boxplot"):
fig, ax = plt.subplots(figsize=(8, 4))
sns.boxplot(x=df[selected_categorical], y=df[selected_numerical], ax=ax)
st.pyplot(fig)