From 38982d2cec039896e1e3a7026b1e9d460d266a2f Mon Sep 17 00:00:00 2001 From: Marilyne HU <marilyne.hu@student-cs.fr> Date: Tue, 1 Apr 2025 08:26:29 +0200 Subject: [PATCH] update new fonctionnality --- README.md | 15 +- app.py | 138 +--------------- onglets/__pycache__/onglet1.cpython-312.pyc | Bin 0 -> 7165 bytes onglets/onglet1.py | 147 ++++++++++++++++++ onglets/onglet2.py | 0 utils/__pycache__/utils_graph.cpython-312.pyc | Bin 0 -> 7271 bytes utils/test_notebook.ipynb | 84 ++++++++++ utils_graph.py => utils/utils_graph.py | 62 +++----- 8 files changed, 271 insertions(+), 175 deletions(-) create mode 100644 onglets/__pycache__/onglet1.cpython-312.pyc create mode 100644 onglets/onglet1.py create mode 100644 onglets/onglet2.py create mode 100644 utils/__pycache__/utils_graph.cpython-312.pyc create mode 100644 utils/test_notebook.ipynb rename utils_graph.py => utils/utils_graph.py (63%) diff --git a/README.md b/README.md index f282e32..48de65d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,16 @@ # Streamlit Projet -Lien en ligne du logiciel : https://app-project-gem6konsqjctcv2zfkc54v.streamlit.app/ \ No newline at end of file +Arborescance de l'application : +- data : le répertoire contient les données nécessaires au bon fonctionnement du logiciel +- onglets : contient les différents types de graphiques (bar horizontale, etc.) +- utils : contient l'ensemble des fonctions nécessaires au bon fonctionnement de l'application + +Ce logiciel a été mis en ligne via Github et accessible à partir de ce lien : https://app-project-gem6konsqjctcv2zfkc54v.streamlit.app/ + +Une barre de sélection avec un entier correspond au nombre de lignes qu'on affiche dans le graphique à partir des données (compter à partir de la première ligne des données). + +Pour pouvoir mettre une couleur de légende, il faut sélectionner la colonne "numero_color" des données de test, qui correspond à l'index des couleurs de chaque barre horizontale. De plus, on peut saisir manuellement le nom de la couleur. + + + + diff --git a/app.py b/app.py index 4b4edb5..8ee249a 100644 --- a/app.py +++ b/app.py @@ -5,138 +5,14 @@ from matplotlib.colors import LinearSegmentedColormap, ListedColormap, to_hex import matplotlib.patches as mpatches from io import BytesIO -import utils_graph -from utils_graph import plot_graph +import utils.utils_graph as utils_graph +from utils.utils_graph import plot_graph -st.title('Logiciel cartographique') - -upload_file = st.file_uploader('Charger vos données en format .csv ou .xlsx.') - -if upload_file is not None : - - # chargement des données - filename = upload_file.name - - # vérifie la forme des données - if filename.endswith('.csv'): - df = pd.read_csv(upload_file) - st.success("Fichier CSV chargé avec succès.") - - elif filename.endswith('.xlsx') or filename.endswith('.xls'): - df = pd.read_excel(upload_file) - st.success("Fichier Excel chargé avec succès.") - - else: - st.error("Format de fichier non supporté. Veuillez charger un .csv ou un .xlsx.") - - # visualisation des données - st.header('Visualisation des données :') - st.write(df.head(5)) # pour 5 lignes - - # bloc sur les infos du dataframe - st.subheader('Information sur les données :') - with st.expander("📊 Aperçu du DataFrame"): - st.markdown(f"**Dimensions :** {df.shape[0]} lignes × {df.shape[1]} colonnes") - st.markdown("**Colonnes disponibles :**") - st.write(list(df.columns)) - st.markdown("**Types de données :**") - st.write(df.dtypes) - - st.subheader('Choix d\'option :') - if df.shape[0]>12 : - nb_line = st.number_input( - "Nombre de lignes à afficher", - min_value=1, - max_value=len(df), - value=5, - step=1, - format="%d" # ↠force l'affichage et le retour d'un entier - ) - - # choix des colonnes à tracer - columns = df.columns.tolist() - - col_x = st.selectbox('Choisir la colonne des valeurs (x)', columns) - col_y = st.selectbox('Choisir la colonne des catégories (y)', columns) - - title_choice = st.checkbox("Voulez-vous mettre un titre au graphique ?") - if title_choice: - title = st.text_input("Entrez le titre du graphique :", key="title_input") - else: - title = None +from onglets import onglet1 - x_choice = st.checkbox("Voulez-vous nommer l'axe des abscisses ?") - if x_choice: - xlabel = st.text_input("Entrez le nom de l'axe des abscisses :", key="xlabel_input") - else: - xlabel = None - - y_choice = st.checkbox("Voulez-vous nommer l'axe des ordonnées ?") - if y_choice: - ylabel = st.text_input("Entrez le nom de l'axe des ordonnées :", key="ylabel_input") - else: - ylabel = None - - model_graph = utils_graph.plot_graph(df = df.loc[:nb_line-1, :], x = col_x, y = col_y) - legend_choice = st.checkbox('Voulez-vous mettre une légende de couleurs ?') - - if legend_choice: - col_color = st.selectbox('Choisir la colonne des numéros de couleurs', columns) - - try : - # Premier tracé pour générer list_colors - model_graph.barh_subplot(colors=col_color, show=False, title= title, xlabel= xlabel, ylabel=ylabel) - colors_rgba = model_graph.list_colors - - custom_colors = {} - legend_labels = [] - legend_indices = [] - - st.markdown("Personnalisation des couleurs et des légendes :") - - for i, rgba in enumerate(colors_rgba): - hex_color = to_hex(rgba) - col1, col2 = st.columns(2) - with col1: - picked_color = st.color_picker(f"Couleur {i+1}", hex_color) - with col2: - label = st.text_input(f"Légende {i+1}", key=f"legend_{i}") - - if label.strip(): # légende non vide - legend_labels.append(label) - legend_indices.append(i) - custom_colors[i] = {"color": picked_color, "label": label} - - # Retracer avec légendes non vides - barh = model_graph.barh_subplot( - colors=col_color, - legend_list=legend_labels, - title_legend="Légende", - legend_indices=legend_indices, - title= title, - xlabel= xlabel, - ylabel= ylabel - ) - - st.pyplot(barh) - - except Exception as e: - st.warning("âš ï¸ Cette colonne ne semble pas contenir des numéros de couleurs valides.") - - else: - # Tracer sans légende - barh = model_graph.barh_subplot(title= title, xlabel= xlabel, ylabel= ylabel) - st.pyplot(barh) +st.title('Logiciel cartographique') - # Sauvegarde du graphique dans un buffer en mémoire - img_buffer = BytesIO() - barh.savefig(img_buffer, format='png', dpi=300, bbox_inches='tight') - img_buffer.seek(0) # Revenir au début du buffer +option = st.sidebar.selectbox("Choisir le format du graphique :", ("Graphique en barre horizontale","Histogramme")) - # Bouton de téléchargement - st.download_button( - label="📥 Télécharger le graphique", - data=img_buffer, - file_name="mon_graphique.png", - mime="image/png" - ) +if option == "Graphique en barre horizontale" : + onglet1.display() \ No newline at end of file diff --git a/onglets/__pycache__/onglet1.cpython-312.pyc b/onglets/__pycache__/onglet1.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1ff1334974f64fdca5dd440f8446d4991fcbb0ae GIT binary patch literal 7165 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 literal 0 HcmV?d00001 diff --git a/onglets/onglet1.py b/onglets/onglet1.py new file mode 100644 index 0000000..199e248 --- /dev/null +++ b/onglets/onglet1.py @@ -0,0 +1,147 @@ +import streamlit as st +import pandas as pd +from matplotlib.colors import to_hex +from io import BytesIO +import sys +import os + +sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'utils'))) + +import utils.utils_graph as utils_graph + + +def display() : + upload_file = st.file_uploader('Charger vos données en format .csv ou .xlsx.') + + if upload_file is not None : + + # chargement des données + filename = upload_file.name + + # vérifie la forme des données + if filename.endswith('.csv'): + df = pd.read_csv(upload_file) + st.success("Fichier CSV chargé avec succès.") + + elif filename.endswith('.xlsx') or filename.endswith('.xls'): + df = pd.read_excel(upload_file) + st.success("Fichier Excel chargé avec succès.") + + else: + st.error("Format de fichier non supporté. Veuillez charger un .csv ou un .xlsx.") + + # visualisation des données + st.header('Visualisation des données :') + st.write(df.head(5)) # pour 5 lignes + + # bloc sur les infos du dataframe + st.subheader('Information sur les données :') + with st.expander("📊 Aperçu du DataFrame"): + st.markdown(f"**Dimensions :** {df.shape[0]} lignes × {df.shape[1]} colonnes") + st.markdown("**Colonnes disponibles :**") + st.write(list(df.columns)) + st.markdown("**Types de données :**") + st.write(df.dtypes) + + st.subheader('Choix d\'option :') + if df.shape[0]>12 : + nb_line = st.number_input( + "Nombre de lignes à afficher", + min_value=1, + max_value=len(df), + value=5, + step=1, + format="%d" # ↠force l'affichage et le retour d'un entier + ) + + # choix des colonnes à tracer + columns = df.columns.tolist() + + col_x = st.selectbox('Choisir la colonne des valeurs (x)', columns) + col_y = st.selectbox('Choisir la colonne des catégories (y)', columns) + + title_choice = st.checkbox("Voulez-vous mettre un titre au graphique ?") + if title_choice: + title = st.text_input("Entrez le titre du graphique :", key="title_input") + else: + title = None + + x_choice = st.checkbox("Voulez-vous nommer l'axe des abscisses ?") + if x_choice: + xlabel = st.text_input("Entrez le nom de l'axe des abscisses :", key="xlabel_input") + else: + xlabel = None + + y_choice = st.checkbox("Voulez-vous nommer l'axe des ordonnées ?") + if y_choice: + ylabel = st.text_input("Entrez le nom de l'axe des ordonnées :", key="ylabel_input") + else: + ylabel = None + + model_graph = utils_graph.plot_graph(df = df.loc[:nb_line-1, :], x = col_x, y = col_y) + legend_choice = st.checkbox('Voulez-vous mettre une légende de couleurs ?') + + #annotation = st.checkbox('Voulez-cous mettre une annotation ?') + #if annotation : + # col_nombre = st.selectbox('Colonne des valeurs absolues', columns) + + if legend_choice: + col_color = st.selectbox('Choisir la colonne des numéros de couleurs', columns) + + try : + # Premier tracé pour générer list_colors + model_graph.barh_subplot(colors=col_color, show=False, title= title, xlabel= xlabel, ylabel=ylabel) + colors_rgba = model_graph.list_colors + + custom_colors = {} + legend_labels = [] + legend_indices = [] + + st.markdown("Personnalisation des couleurs et des légendes :") + + for i, rgba in enumerate(colors_rgba): + hex_color = to_hex(rgba) + col1, col2 = st.columns(2) + with col1: + picked_color = st.color_picker(f"Couleur {i+1}", hex_color) + with col2: + label = st.text_input(f"Légende {i+1}", key=f"legend_{i}") + + if label.strip(): # légende non vide + legend_labels.append(label) + legend_indices.append(i) + custom_colors[i] = {"color": picked_color, "label": label} + + # Retracer avec légendes non vides + barh = model_graph.barh_subplot( + colors=col_color, + legend_list=legend_labels, + title_legend="Légende", + legend_indices=legend_indices, + title= title, + xlabel= xlabel, + ylabel= ylabel + ) + + st.pyplot(barh) + + except Exception as e: + st.warning("âš ï¸ Cette colonne ne semble pas contenir des numéros de couleurs valides.") + + else: + # Tracer sans légende + barh = model_graph.barh_subplot(title= title, xlabel= xlabel, ylabel= ylabel) + st.pyplot(barh) + + # Sauvegarde du graphique dans un buffer en mémoire + img_buffer = BytesIO() + barh.savefig(img_buffer, format='png', dpi=300, bbox_inches='tight') + img_buffer.seek(0) # Revenir au début du buffer + + # Bouton de téléchargement + st.download_button( + label="📥 Télécharger le graphique", + data=img_buffer, + file_name="mon_graphique.png", + mime="image/png" + ) diff --git a/onglets/onglet2.py b/onglets/onglet2.py new file mode 100644 index 0000000..e69de29 diff --git a/utils/__pycache__/utils_graph.cpython-312.pyc b/utils/__pycache__/utils_graph.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ea4c79ac17785b3e3b8ee181f5d9b7f84ff1dd50 GIT binary patch literal 7271 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 literal 0 HcmV?d00001 diff --git a/utils/test_notebook.ipynb b/utils/test_notebook.ipynb new file mode 100644 index 0000000..47eb8a7 --- /dev/null +++ b/utils/test_notebook.ipynb @@ -0,0 +1,84 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "\n", + "from utils_graph import plot_graph" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_excel(r'../data/df_cfa_anonyme.xlsx')\n", + "df = df.loc[:12,:]" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "model = plot_graph(df = df, x = 'count', y = 'denomination_cfa')" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "<Figure size 1000x600 with 1 Axes>" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "graph = model.barh_subplot()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/utils_graph.py b/utils/utils_graph.py similarity index 63% rename from utils_graph.py rename to utils/utils_graph.py index c97694e..588399a 100644 --- a/utils_graph.py +++ b/utils/utils_graph.py @@ -41,7 +41,7 @@ class plot_graph() : if self.ax is None or self.fig is None or force_new_fig: self.fig, self.ax = plt.subplots(figsize=self.figsize) - bars = self.ax.barh(self.y, self.x, color = colors_bars, hatch = hatches) + self.bars = self.ax.barh(self.y, self.x, color = colors_bars, hatch = hatches) if legend_list and colors is not None: legend_elements = [] @@ -86,53 +86,29 @@ class plot_graph() : return self.fig # partie à revoir selon les besoins des missions - def annotation(self) : + def annotation(self, pourcentage = None, Nombre = None) : - """ # Ajouter des annotations sur les barres - if pourcentage_list == False : - for n, bar in enumerate(bars): + if pourcentage and not Nombre : + for n, bar in enumerate(self.bars) : width = bar.get_width() - if np.isnan(width): - # Gérer le cas où la largeur est NaN - text = "N/A" - elif nombre and slash : - text = f"{round(width)}/{self.df.loc[n,slash]}" - elif nombre and slash == False : - text = f"{round(width)}" - else: - if pourcentage and self.df.shape[0]<10: - text = f"{round((width / self.df['count'].sum()) * 100, 1)}% ({int(width)})" - elif pourcentage and self.df.shape[0]>=10: - text = f"{round((width / total) * 100, 1)}% ({int(width)})" - else : - text = f"{round(width)}%" - - if width == 0 : - ax.text(2 if not np.isnan(width) else 0 , bar.get_y() + bar.get_height() / 2, - text,va='center', ha='left', color='gray', fontsize=9) - else : - ax.text(width * 1.01 if not np.isnan(width) else 0 , bar.get_y() + bar.get_height() / 2, + text = self.df.loc[n,pourcentage] + self.ax.text(width * 1.01 if not np.isnan(width) else 0 , bar.get_y() + bar.get_height() / 2, text, va='center', ha='left', color='gray', fontsize=9) - - elif pourcentage_list != False: - for n,bar in enumerate(bars): + + elif Nombre and not pourcentage : + for n, bar in enumerate(self.bars) : width = bar.get_width() - if np.isnan(width): - # Gérer le cas où la largeur est NaN - text = "N/A" - elif inverse : - text = f"{width}% ({self.df.loc[n,pourcentage_list]})" - - else : - text = f"{self.df.loc[n,pourcentage_list]}% ({width})" - if width == 0 : - ax.text(2 if not np.isnan(width) else 0 , bar.get_y() + bar.get_height() / 2, - text,va='center', ha='left', color='gray', fontsize=9) - else : - ax.text(width * 1.01 if not np.isnan(width) else 0 , bar.get_y() + bar.get_height() / 2, - text, va='center', ha='left', color='gray', fontsize=9)""" + text = self.df.loc[n,Nombre] + self.ax.text(width * 1.01 if not np.isnan(width) else 0 , bar.get_y() + bar.get_height() / 2, + text, va='center', ha='left', color='gray', fontsize=9) - pass + elif Nombre and pourcentage : + for n, bar in enumerate(self.bars) : + width = bar.get_width() + text = f'{self.df.loc[n,Nombre]} ({self.df.loc[n,pourcentage]} %)' + self.ax.text(width * 1.01 if not np.isnan(width) else 0 , bar.get_y() + bar.get_height() / 2, + text, va='center', ha='left', color='gray', fontsize=9) + def encadrer(self) : -- GitLab