From 926b2e0eef94d379f6bc61dd6e9c75c0084979cc Mon Sep 17 00:00:00 2001 From: Sandrine Date: Sat, 4 May 2024 23:37:46 +0200 Subject: [PATCH 1/4] =?UTF-8?q?pour=20les=20parties=20soci=C3=A9t=C3=A9s?= =?UTF-8?q?=20de=20production=20et=20r=C3=A9compenses,=20ajout=20de=20filt?= =?UTF-8?q?res=20(date=20de=20sortie,=20type=20de=20l'oeuvre,=20choix=20de?= =?UTF-8?q?=20l'oeuvre)=20dans=20la=20sidebar=20pour=20adapter=20les=20gra?= =?UTF-8?q?phique=20et=20le=20texte=20d'analyse=20en=20fonction?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/odi_streamlit.py | 277 +++++++++++++++------- app/pages/odi - enrichissement fichier.py | 2 +- poetry.lock | 17 +- pyproject.toml | 1 + 4 files changed, 206 insertions(+), 91 deletions(-) diff --git a/app/odi_streamlit.py b/app/odi_streamlit.py index a93d896..8354167 100644 --- a/app/odi_streamlit.py +++ b/app/odi_streamlit.py @@ -36,9 +36,10 @@ def load_data(file: str) -> pd.DataFrame: return df # TODO connect to Google Sheet and load data -file_path = ("https://raw.githubusercontent.com/dataforgoodfr/12_observatoire_des_imaginaires/" - "main/data/Etape%201%20Identification%20du%20film%20-%20Feuille%201%20-%20enrichi.csv") - +file_path = ("https://raw.githubusercontent.com/dataforgoodfr/" +"12_observatoire_des_imaginaires/analyse/streamlit_app_v2/" +"data/Etape%201%20Identification%20du%20film%20-%20Feuille%201%20-%20enrichi.csv") +#"./data/Etape 1 Identification du film - Feuille 1 - enrichi.csv" if "data" not in st.session_state: st.session_state["data"] = load_data(file_path) @@ -49,6 +50,17 @@ def load_data(file: str) -> pd.DataFrame: # Renommer la colonne title -> TITRE data.rename(columns={"title": "TITRE"}, inplace=True) +# Et Supprimer les lignes où toutes les valeurs sont NaN +df = data.dropna(how="all") + +# Nettoyage du data set + +# mettre les titres en majuscule +df["TITRE"] = df["TITRE"].str.upper() +# Convertir les années en entier +annee = "release_year" +df[annee] = pd.to_numeric(df[annee], errors="coerce").fillna(0).astype(int) + logo= ("https://media.licdn.com/dms/image/D4E0BAQEZHVBxFn3OXQ/company-logo_200_200/" "0/1697116934909/cercle_thmatique_culture_the_shifters_logo?e=1718841600&v=beta" "&t=_2DWaEBrblIgXhgVASUipHTcJesOL6s1Sk2uH73Kx58") @@ -65,6 +77,24 @@ def load_data(file: str) -> pd.DataFrame: "Cette application analyse les données du sondage " "de **l'Observatoire des Imaginaires**. ", ) + with st.container(border=True): + st.markdown("**Filtres d'analyse**") + + #filtre année de sortie + list_year = df["release_year"].sort_values().unique() + start_clr, end_clr = st.select_slider("Choisissez la/les date(s) d'analyse", + options=list_year, value=(min(list_year), max(list_year))) + + #filtre type de contenu vu + type_contenu_choice = st.selectbox( + "Choisissez un type de contenu", + df["TYPE"].unique(), + index=None, + ) + + #filtre nom de l'oeuvre + choix_nom_oeuvre = st.multiselect("Choisissez un ou plusieurs film(s)", + df["TITRE"].sort_values().unique(), default=None) ### B. Container du header @@ -75,17 +105,6 @@ def load_data(file: str) -> pd.DataFrame: ### C. Container des métriques cont_metric = st.container() -# Et Supprimer les lignes où toutes les valeurs sont NaN -df = data.dropna(how="all") - -# Nettoyage du data set - -# mettre les titres en majuscule -df["TITRE"] = df["TITRE"].str.upper() -# Convertir les années en entier -annee = "release_year" -df[annee] = pd.to_numeric(df[annee], errors="coerce").fillna(0).astype(int) - with cont_metric: with st.expander("Aperçu des données"): st.dataframe(df) @@ -204,6 +223,7 @@ def load_data(file: str) -> pd.DataFrame: col_pays, col_contenu_vide, col_pays_annee = st.columns([4, 0.5, 4]) country_group_df = df + country_group_df = ( country_group_df.groupby("pays_rework") .count() @@ -269,6 +289,7 @@ def load_data(file: str) -> pd.DataFrame: ) st.plotly_chart(fig_pays, use_container_width=True) + with col_pays_annee: country_group_df_rework = df.groupby(["pays_rework", "production_countries", @@ -380,6 +401,7 @@ def get_chart_82052330(df: pd.DataFrame, liste: list[str], titre: str) -> None: st.plotly_chart(fig, theme="streamlit") + # Préparation du dataframe pour les films genre_group_df = df[["id_tmdb", "genres", "TITRE", "TYPE"]].drop_duplicates() @@ -408,18 +430,68 @@ def get_chart_82052330(df: pd.DataFrame, liste: list[str], titre: str) -> None: get_chart_82052330(total_film, liste_genre_cine, "Répartition des genres (uniques)") +### Analyses des sociétés de productions with st.container(): + st.subheader("Sociétés de production") + + col_choix_film_prod, col_prod_graph = st.columns([3, 5]) + # Préparation du dataframe pour les films - productions_df = df[ - ["id_tmdb", "TITRE", "TYPE", "production_companies"] - ].drop_duplicates() + if len(choix_nom_oeuvre)!=0 and type_contenu_choice is not None: + productions_df = df[(df["TITRE"].isin(choix_nom_oeuvre))&\ + (df["TYPE"]== type_contenu_choice)&\ + (df.release_year >= start_clr) & \ + (df.release_year <= end_clr)][ + ["id_tmdb", "TITRE", "TYPE", "production_companies"] + ].drop_duplicates() + if len(productions_df) == 0: + productions_df = df[ + ["id_tmdb", "TITRE", "TYPE", "production_companies"] + ].drop_duplicates() + with col_choix_film_prod: + st.markdown("#### :warning: Aucun film ne correspond à votre choix.\ + Veuillez modifier un ou plusieurs filtres", + ) + elif len(choix_nom_oeuvre)!=0 and type_contenu_choice is None: + productions_df = df[(df["TITRE"].isin(choix_nom_oeuvre))&\ + (df.release_year >= start_clr) & \ + (df.release_year <= end_clr)][ + ["id_tmdb", "TITRE", "TYPE", "production_companies"] + ].drop_duplicates() + if len(productions_df) == 0: + productions_df = df[ + ["id_tmdb", "TITRE", "TYPE", "production_companies"] + ].drop_duplicates() + with col_choix_film_prod: + st.markdown("#### :warning: Aucun film ne correspond à votre choix.\ + Veuillez modifier un ou plusieurs filtres", + ) + elif len(choix_nom_oeuvre)==0 and type_contenu_choice is not None: + productions_df = df[(df["TYPE"] == (type_contenu_choice))&\ + (df.release_year >= start_clr) & \ + (df.release_year <= end_clr)][ + ["id_tmdb", "TITRE", "TYPE", "production_companies"] + ].drop_duplicates() + if len(productions_df) == 0: + productions_df = df[ + ["id_tmdb", "TITRE", "TYPE", "production_companies"] + ].drop_duplicates() + with col_choix_film_prod: + st.markdown("#### :warning: Aucun film ne correspond à votre choix.\ + Veuillez modifier un ou plusieurs filtres", + ) + else: + productions_df = df[(df.release_year >= start_clr) & \ + (df.release_year <= end_clr)][ + ["id_tmdb", "TITRE", "TYPE", "production_companies"] + ].drop_duplicates() + # je crée une liste de genres uniques liste_production_cine = list({p for prod in productions_df["production_companies"] for p in prod.split(",") }) - # je compte le nombre de films par producteur productions_df = pd.concat( [productions_df, pd.DataFrame(columns=liste_production_cine)], @@ -443,21 +515,34 @@ def get_chart_82052330(df: pd.DataFrame, liste: list[str], titre: str) -> None: .reset_index() .rename(columns={0: "total_film", "index": "production_companies"}) ) - total_film_prod.insert(2, "TYPE", "FILM") - get_chart_82052330( + with col_choix_film_prod: + # Combine all parts and use markdown + prod_comment = ( + f"**Répartition des sociétes de productions** " + f"pour :blue[{type_contenu_choice}] ont pour " + f"pays d'origine :blue[{choix_nom_oeuvre}] (:blue[%]), alors que la " + f"majorité des contenus français sont visionnés xxx (xxx%)." + ) + st.markdown(prod_comment) + with col_prod_graph: + get_chart_82052330( total_film_prod, liste_production_cine, "Répartition des producteurs", - ) + ) with st.container(): st.subheader("Récompenses") - col_choix_annee, col_award_graph = st.columns([4, 6]) - # Préparation du dataframe pour les films - award_df = df[ - ["id_tmdb", "TITRE", "TYPE", "nb_recompense", "liste_festival","release_year"] - ].drop_duplicates() + if len(choix_nom_oeuvre)==0: + award_df = df[ + ["id_tmdb", "TITRE", "TYPE", "nb_recompense", "liste_festival","release_year"] + ].drop_duplicates() + st.dataframe(award_df) + else : + award_df = df[df["TITRE"].isin(choix_nom_oeuvre)][ + ["id_tmdb", "TITRE", "TYPE", "nb_recompense", "liste_festival","release_year"] + ].drop_duplicates() liste_award_cine = list({p for prod in award_df["liste_festival"] for p in str(prod).split(",") @@ -465,43 +550,56 @@ def get_chart_82052330(df: pd.DataFrame, liste: list[str], titre: str) -> None: if (debug): st.write(liste_award_cine) - list_year = award_df["release_year"].sort_values().unique() - - with col_choix_annee : - start_clr, end_clr = st.select_slider("Choisir la/les date(s) d'analyse", - options=list_year, value=(min(list_year), max(list_year))) - - # je conmpte le nombre de films par récompense award_df = pd.concat([award_df, pd.DataFrame(columns=liste_award_cine)]) for col in liste_award_cine: award_df[col] = [1 if col in str(a).split(",")\ else 0 for a in award_df["liste_festival"]] - # j'ajoute une colonne qui fait la somme des films pour une récompense donnés - # et ajoute le type pour cette nouvelle ligne - total_film_award = dict( - award_df.loc[(award_df["TYPE"] == "FILM")&\ + #J'isole le nombre de contenus sans récompenses + + content_without_award = len(award_df[(award_df["liste_festival"].isnull())&\ (award_df.release_year >= start_clr) & \ - (award_df.release_year <= end_clr)][liste_award_cine].sum(), + (award_df.release_year <= end_clr)])\ + /len(award_df[(award_df.release_year >= start_clr) & \ + (award_df.release_year <= end_clr)]) + + content_without_award_string = ( + f"**:blue[{int(content_without_award*100)}%]** des oeuvres analyseés " + f"n'ont reçu aucun prix cinématographique." ) + # j'ajoute une colonne qui fait la somme des films pour une récompense donnés + # et ajoute le type pour cette nouvelle ligne + if type_choice is None: + total_film_award = dict( + award_df.loc[(award_df["liste_festival"].notnull())&\ + (award_df.release_year >= start_clr) & \ + (award_df.release_year <= end_clr)][liste_award_cine].sum(), + ) + else : + st.write(award_df) + total_film_award = dict( + award_df[(award_df["liste_festival"].notnull())&\ + (award_df.release_year >= start_clr) &\ + (award_df.release_year <= end_clr)][liste_award_cine].sum(), + ) + total_film_award = ( pd.DataFrame.from_dict(total_film_award, orient="index") .reset_index() - .rename(columns={0: "total_film", "index": "liste_festival"}) - ) - total_film_award.insert(2, "TYPE", "FILM") + .rename(columns={0: "total_film", "index": "liste_festival"})) - with col_award_graph : - get_chart_82052330( - total_film_award, liste_award_cine, - f"Répartition des récompenses de {start_clr} à {end_clr}") + get_chart_82052330( + total_film_award, liste_award_cine, + f"Répartition des récompenses de {start_clr} à {end_clr}") + + st.write(content_without_award_string) st.divider() -### TODO Analyse de l’échantillon +### TODO Analyse de l'échantillon # Questions # Quels sont les sous-échantillons statistiquement représentatifs qui peuvent être analysés ? @@ -517,9 +615,9 @@ def get_chart_82052330(df: pd.DataFrame, liste: list[str], titre: str) -> None: # Répartition des genres (uniques) - ok # Répartition des producteurs - déjà ok # Nombre de films pour chaque type de récompense documentées -# (Césars, Cannes, Oscars…) / par année de sortie +# (Césars, Cannes, Oscars…) / par année de sortie - ok # Année de sortie en fonction de nationalité -# Genres en fonction de l’année de sortie +# Genres en fonction de l'année de sortie # Genres en fonction de la nationalité # Nationalité en fonction du canal de diffusion # Genre en fonction du canal de diffusion @@ -528,11 +626,11 @@ def get_chart_82052330(df: pd.DataFrame, liste: list[str], titre: str) -> None: # TODO Analyse des doublons # Pour chaque contenu présents plusieurs fois: # visualisation de toutes les réponses divergentes -# visualisation des personnages à la même désignation (nom ou nom d’acteur) +# visualisation des personnages à la même désignation (nom ou nom d'acteur) # et des réponses divergentes pour les mêmes personnages -# TODO Analyse de l’arène +# TODO Analyse de l'arène # Questions # Où se passent les récits ? @@ -540,7 +638,7 @@ def get_chart_82052330(df: pd.DataFrame, liste: list[str], titre: str) -> None: # Dans quels types de société se déroulent nos récits (réalité vs fantaisie, dystopie # vs utopies…) ? Y a t-il une influence du genre ? # À quelle époque se passent les récits ? Quelle est la proportion de récits qui ne se -# déroulent pas à l’époque de leur écriture ? Comment est-ce influencé par leur genre ? +# déroulent pas à l'époque de leur écriture ? Comment est-ce influencé par leur genre ? # Est-ce que ces tendances évoluent au cours du temps ? st.subheader("Analyse de l'époque du récit") @@ -650,15 +748,15 @@ def get_chart_82052330(df: pd.DataFrame, liste: list[str], titre: str) -> None: # Visualisations # Répartitions: -# Pays de l’action +# Pays de l'action # Nombre de pays par film (1, 2 …) -# Environnement de l’action -# Époque de l’action -# Temporalité de l’action (i.e. temps de l’action par rapport à époque d’écriture du récit) +# Environnement de l'action +# Époque de l'action +# Temporalité de l'action (i.e. temps de l'action par rapport à époque d'écriture du récit) # Type de société # Type de mondes # Corrélations : -# Pays de l’action vs pays de production +# Pays de l'action vs pays de production # Type de monde vs année de production # Type de monde vs genre # Type de monde vs nationalité du film @@ -672,14 +770,14 @@ def get_chart_82052330(df: pd.DataFrame, liste: list[str], titre: str) -> None: # Temporalité du récit vs canal de diffusion # Temporalité du récit vs type de monde # Temporalité du récit vs type de société -# Nombre de pays de l’action vs genre +# Nombre de pays de l'action vs genre # TODO Analyse des personnages renseignés # Questions: # Quelles sont les caractéristiques des personnages ? Qui sont-ils ? Comment vivent-ils ? -# Quelle est l’influence des caractéristiques du film sur les caractéristiques des personnages ? +# Quelle est l'influence des caractéristiques du film sur les caractéristiques des personnages ? # Visualisations: # Nombre total de personnages renseignés @@ -687,7 +785,7 @@ def get_chart_82052330(df: pd.DataFrame, liste: list[str], titre: str) -> None: # En cas de contenus identiques, identification des désignations identiques et # comparaison des divergences dans les répon # Répartitions: -# Tranches d’âges +# Tranches d'âges # Genre # Ethnicités # Gentil ou méchant @@ -701,7 +799,7 @@ def get_chart_82052330(df: pd.DataFrame, liste: list[str], titre: str) -> None: # Questions # Les personnages de fiction présentent-ils des traits de caractères écologiques ? -# si oui, qui sont ces personnages ? Est-ce que c’est influencé par les caractéristiques +# si oui, qui sont ces personnages ? Est-ce que c'est influencé par les caractéristiques # du film (nationalité …) ? Est-ce que ça évolue dans le temps ? # Visualisations @@ -711,31 +809,31 @@ def get_chart_82052330(df: pd.DataFrame, liste: list[str], titre: str) -> None: # Corrélation entre la présence de personnage ayant une sensibilité écolo et les # caractéristiques du film (année / nationalité / genre / producteur / canal de diffusion) -# TODO Analyse de la mobilité à l’écran +# TODO Analyse de la mobilité à l'écran # Questions -# Comment se déplace-t-on à l’écran ? Est-ce qu’il y a une corrélation entre -# Visualisation de la proportion de modes de transport représentés à l’écran. Filtres +# Comment se déplace-t-on à l'écran ? Est-ce qu'il y a une corrélation entre +# Visualisation de la proportion de modes de transport représentés à l'écran. Filtres # possibles sur les caractéristiques du contenu (ex. que les films français) -# ou sur la nature des personnages (ex. tranches d’âge). +# ou sur la nature des personnages (ex. tranches d'âge). # Objectif: répondre aux questions suivantes: -# Comment se déplace-t-on à l’écran ? -# Est-ce que ça varie selon le type de personnage et leur sensibilité à l’écologie ? +# Comment se déplace-t-on à l'écran ? +# Est-ce que ça varie selon le type de personnage et leur sensibilité à l'écologie ? -# TODO Analyse de l’habitat -# Visualisation générale des modes d’habitat à l’écran, avec filtres possibles sur les +# TODO Analyse de l'habitat +# Visualisation générale des modes d'habitat à l'écran, avec filtres possibles sur les # types de contenu ou sur les caractéristiques des personnages (ex. comment habitent les -# jeunes ? comment habitent les CSP+ ?). Importance corréler l’habitat à l’emploi exercé +# jeunes ? comment habitent les CSP+ ?). Importance corréler l'habitat à l'emploi exercé # (i.e. la catégorie socio-professionnelle). -# Corrélation entre les lieux de vie et les lieux de l’action (dans la catégorie arène). +# Corrélation entre les lieux de vie et les lieux de l'action (dans la catégorie arène). # Question posée : les “aventures” se passent-elles forcément loin du lieu de vie des -# personnages ? Regarder notamment l’influence du genre et l’influence de la nationalité +# personnages ? Regarder notamment l'influence du genre et l'influence de la nationalité # du film -# TODO Analyse de l’emploi -# Visualisation des emplois représentés à l’écran selon le type de contenu. -# Intéressant de regarder qui pratique quel type d’emploi (femmes vs hommes, jeunes…) -# Corrélation entre le métier pratiqué et la sensibilité du personnage à l’écologie +# TODO Analyse de l'emploi +# Visualisation des emplois représentés à l'écran selon le type de contenu. +# Intéressant de regarder qui pratique quel type d'emploi (femmes vs hommes, jeunes…) +# Corrélation entre le métier pratiqué et la sensibilité du personnage à l'écologie with st.container(): st.subheader("Analyse des métiers") @@ -813,9 +911,9 @@ def get_chart_82052330(df: pd.DataFrame, liste: list[str], titre: str) -> None: # Analyse de la technologie -# Visualisation de l’emploi de la technologie à l’écran selon le type de film (regarder en -# particulier le genre) et le type de personnage (corréler en particulier à l’âge). -# Question sous-jacente : comment utilise-t-on la technologie à l’écran ? est-ce +# Visualisation de l'emploi de la technologie à l'écran selon le type de film (regarder en +# particulier le genre) et le type de personnage (corréler en particulier à l'âge). +# Question sous-jacente : comment utilise-t-on la technologie à l'écran ? est-ce # systématique ? est-ce corrélé à une certaine forme de réalité des usages ? with st.container(): st.subheader("Analyse de la technologie") @@ -903,6 +1001,7 @@ def get_chart_82052330(df: pd.DataFrame, liste: list[str], titre: str) -> None: melted_data_all = prepare_technology_data(data=df, colname_id="age_group") melted_data_all.rename(columns={"age_group": "Catégorie d'âge"}, inplace=True) + fig = px.histogram( melted_data_all, x="Technology", @@ -925,14 +1024,14 @@ def get_chart_82052330(df: pd.DataFrame, liste: list[str], titre: str) -> None: # TODO Analyse des modes de vie -# TODO L’écologie dans le récit +# TODO L'écologie dans le récit # TODO # Pédagogie? # Cartographie des contenus qui mentionnent un enjeu écologique et corrélation à leurs # caractéristiques (nationalité etc.). Est-ce que ça a évolué au cours du temps ? Est-ce -# que certains genres s’y prêtent plus que d’autres ? Quand l’écologie est mentionnée, -# de quel type de récit s’agit-il ? (dystopie, récit futuriste…) +# que certains genres s'y prêtent plus que d'autres ? Quand l'écologie est mentionnée, +# de quel type de récit s'agit-il ? (dystopie, récit futuriste…) # Adéquation entre le score calculé et le score proposé par les répondants # Enjeux écologiques les plus fréquemment montrés / les plus ignorés @@ -992,28 +1091,28 @@ def get_chart_82052330(df: pd.DataFrame, liste: list[str], titre: str) -> None: st.plotly_chart(fig) -# Box office / récompenses obtenues par les films qui parlent d’écologie ou qui ont +# Box office / récompenses obtenues par les films qui parlent d'écologie ou qui ont # des scores écologiques élevées (question : ces films sont-ils vus ?) -# A l’inverse, quels scores écologiques pour les films les plus vus au box office ? +# A l'inverse, quels scores écologiques pour les films les plus vus au box office ? # Pédagogie clandestine ? # Visualisation et statistiques sur les comportements listés, avec filtres possibles # sur la nature des contenus. # Corrélation au score écologique proposé par les répondants, la question étant : les -# spectateurs font-ils le lien entre certains comportements montrés à l’écran et -# l’impact écologique d’un contenu ? +# spectateurs font-ils le lien entre certains comportements montrés à l'écran et +# l'impact écologique d'un contenu ? # Personnage écolo vs récit écolo -# La biodiversité à l’écran +# La biodiversité à l'écran # La perception des répondants # Quels types de contenus remportent les meilleurs scores? # Quels types de contenus remportent les moins bons scores? -# L’influence du profil des répondants +# L'influence du profil des répondants # Sur les scores fournis # Sur le nombre de réponses type “je ne sais pas / je ne me souviens plus” @@ -1021,7 +1120,7 @@ def get_chart_82052330(df: pd.DataFrame, liste: list[str], titre: str) -> None: # Questions: # Quelles sont les caractéristiques des personnages ? Qui sont-ils ? Comment vivent-ils ? -# Quelle est l’influence des caractéristiques du film sur les caractéristiques des personnages ? +# Quelle est l'influence des caractéristiques du film sur les caractéristiques des personnages ? # Visualisations: # Nombre total de personnages renseignés @@ -1038,7 +1137,7 @@ def get_chart_82052330(df: pd.DataFrame, liste: list[str], titre: str) -> None: # comparaison des divergences dans les répon # Répartitions: -# Tranches d’âges +# Tranches d'âges # Melanger les differentes characteres blended_column = [val for pair in zip(data["character2_age_group"], data["character4_age_group"], strict=False) for val in pair] diff --git a/app/pages/odi - enrichissement fichier.py b/app/pages/odi - enrichissement fichier.py index 4dc8753..abaf71c 100644 --- a/app/pages/odi - enrichissement fichier.py +++ b/app/pages/odi - enrichissement fichier.py @@ -51,7 +51,7 @@ @st.cache_data def load_header_tmdb(): with open("./secret/TMDB.txt", "r") as file: - file_lines = file.read().split('\n') + file_lines = file.read().split('\n') header_tmdb = [token.split(':') for token in file_lines][0][1].replace('/n','') return header_tmdb diff --git a/poetry.lock b/poetry.lock index 9db7c24..1919ece 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2878,6 +2878,21 @@ files = [ [package.dependencies] streamlit = ">=0.63" +[[package]] +name = "streamlit-plotly-events" +version = "0.0.6" +description = "Plotly chart component for Streamlit that also allows for events to bubble back up to Streamlit." +optional = false +python-versions = ">=3.6" +files = [ + {file = "streamlit-plotly-events-0.0.6.tar.gz", hash = "sha256:1fe25dbf0e5d803aeb90253be04d7b395f5bcfdf3c654f96ff3c19424e7f9582"}, + {file = "streamlit_plotly_events-0.0.6-py3-none-any.whl", hash = "sha256:e63fbe3c6a0746fdfce20060fc45ba5cd97805505c332b27372dcbd02c2ede29"}, +] + +[package.dependencies] +plotly = ">=4.14.3" +streamlit = ">=0.63" + [[package]] name = "tenacity" version = "8.3.0" @@ -3370,4 +3385,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "234f5bae8df2d725b09e251697514ba125026d24693c3267f53b9e8d45429e92" +content-hash = "c91b8b5bf0ecd42b5935d7208155127fb4d7cb8a6a1900d41c6ab2dd2e0833fb" diff --git a/pyproject.toml b/pyproject.toml index 447573d..8c2e529 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,6 +27,7 @@ python-dotenv = "^1.0.1" datasets = "^2.18.0" pycountry-convert = "^0.7.2" fire = "^0.6.0" +streamlit-plotly-events = "^0.0.6" [tool.poetry.group.dev.dependencies] pre-commit = "^2.20.0" From 4b92ed19797720fc3cd0fe403932b2053045e150 Mon Sep 17 00:00:00 2001 From: Sandrine Date: Tue, 7 May 2024 00:08:57 +0200 Subject: [PATCH 2/4] ajout de filtres sur graphiques --- app/odi_streamlit.py | 484 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 395 insertions(+), 89 deletions(-) diff --git a/app/odi_streamlit.py b/app/odi_streamlit.py index 8354167..b4d63dc 100644 --- a/app/odi_streamlit.py +++ b/app/odi_streamlit.py @@ -39,7 +39,7 @@ def load_data(file: str) -> pd.DataFrame: file_path = ("https://raw.githubusercontent.com/dataforgoodfr/" "12_observatoire_des_imaginaires/analyse/streamlit_app_v2/" "data/Etape%201%20Identification%20du%20film%20-%20Feuille%201%20-%20enrichi.csv") -#"./data/Etape 1 Identification du film - Feuille 1 - enrichi.csv" +#file_path = "app/data/Etape 1 Identification du film - Feuille 1 - enrichi.csv" # noqa: ERA001 if "data" not in st.session_state: st.session_state["data"] = load_data(file_path) @@ -190,16 +190,18 @@ def load_data(file: str) -> pd.DataFrame: df.groupby("release_year") .count() .reset_index()[["release_year", "TITRE"]] - .rename(columns={"TITRE": "nb_titre"}) + .rename(columns={"TITRE": "Nb_titres", + "release_year": "Année de sortie"}) ) + date_group_df["periode_percent"] = 100 * ( - 1 - (date_group_df.nb_titre.cumsum() / date_group_df.nb_titre.sum()) + 1 - (date_group_df.Nb_titres.cumsum() / date_group_df.Nb_titres.sum()) ) date_min = str(df.release_year.min()) date_max = str(df.release_year.max()) date_pareto = date_group_df[date_group_df["periode_percent"] <= 80][ # noqa: PLR2004 - "release_year"].min() + "Année de sortie"].min() date_value_pareto = int( round( @@ -209,114 +211,85 @@ def load_data(file: str) -> pd.DataFrame: ) st.markdown( - (f"Les contenus datent d'une période qui s'étend de **:blue[{date_min}]**" - f" à **:blue[{date_max}]**. **:blue[{date_value_pareto}%]** des contenus \ - sont postérieurs à" - f" **:blue[{date_pareto}]**." + (f"Les oeuvres analysées sont sorties sur une période qui s'étend" + f"de **:blue[{date_min}]** à **:blue[{date_max}]**." + f" \n\n**:blue[{date_value_pareto}%]** des années de sorties sont égales ou " + f"postérieures à **:blue[{date_pareto}]**." ), ) -st.bar_chart(date_group_df, x="release_year", y="nb_titre") + st.bar_chart(date_group_df, x="Année de sortie", y="Nb_titres") with st.container(border=True): st.subheader("Nationalité des contenus") col_pays, col_contenu_vide, col_pays_annee = st.columns([4, 0.5, 4]) - country_group_df = df - country_group_df = ( - country_group_df.groupby("pays_rework") + df.groupby("pays_rework") .count() .reset_index()[["pays_rework", "TITRE"]] - .rename(columns={"TITRE": "nb_titre"}) - .sort_values("nb_titre") - ) - country_group_df["country_percent_cumul"] = round( - 100 - * ( - 1 - - (country_group_df.nb_titre.cumsum() / country_group_df.nb_titre.sum()) - ), - 0, + .rename(columns={"TITRE": "Nb_titres"}) + .sort_values("Nb_titres") ) + + # Calcul du pourcentage par pays country_group_df["country_percent"] = round( - 100 * (country_group_df.nb_titre / country_group_df.nb_titre.sum()), + 100 * (country_group_df.Nb_titres / country_group_df.Nb_titres.sum()), 2, ) - country_value_pareto = int( - round( - country_group_df[ - country_group_df["country_percent"] >= 10 # noqa: PLR2004 - ][ - "country_percent" - ].sum(), - 2, - ), - ) - country_group_df_pareto = country_group_df[ - country_group_df["country_percent"] >= 10 # noqa: PLR2004 - ][["pays_rework", "country_percent"]].sort_values( - "country_percent", - ascending=False, - ) - - # Pre-calculate the two largest values + # Identification des 2 principaux pays suivant leur pourcentage top_countries_df = country_group_df.nlargest(2,"country_percent").reset_index(drop=True) - # Extract country names and percentages for readability + # Calcul de la somme des 2 principaux pourcentages + country_value_pareto = int(top_countries_df["country_percent"].sum()) + + # Extraction des nom et % de 2 pays country1_name = top_countries_df["pays_rework"][0].capitalize() country1_percent = top_countries_df["country_percent"][0] country2_name = top_countries_df["pays_rework"][1].capitalize() country2_percent = top_countries_df["country_percent"][1] - # Format the output string - output_string = ( + # Formatage du commentaire + comment_pays_string = ( f"A **:blue[{country_value_pareto}%]**, les 2 principaux pays dont les contenus " - f"sont les plus visionnés sont : {country1_name} ({country1_percent}%) et " - f"{country2_name} ({country2_percent}%)." + f"sont les plus visionnés sont : **:blue[{country1_name}]** ({country1_percent}%) et " + f"**:blue[{country2_name}]** ({country2_percent}%)." ) - st.write(output_string) - - with col_pays : - fig_pays = px.bar( - country_group_df, - y="pays_rework", - x="nb_titre", - orientation="h", - text_auto=True, - ) - st.plotly_chart(fig_pays, use_container_width=True) - - - with col_pays_annee: - country_group_df_rework = df.groupby(["pays_rework", - "production_countries", - "release_year"]).count().reset_index()[["pays_rework", - "production_countries", - "release_year", - "TITRE"]].rename(columns={"TITRE": "Nb_titres", - "production_countries": "Pays", - "release_year":"Année de sortie" }) - - country_group_df_rework["Année de sortie"] = \ - country_group_df_rework["Année de sortie"].astype("str") - - fig_pays_annee = px.bar(country_group_df_rework.sort_values(["Année de sortie"]), - y="pays_rework", - x="Nb_titres", - color="Année de sortie", - orientation="h", - color_discrete_map={ - "1997": "#E44F43", - "2024": "#0B5773", - "2022": "#7BC0AC", - "2023": "#D3C922"}, - text_auto=True, - hover_data={"pays_rework":False, - "Année de sortie":True, "Pays":True}) - st.plotly_chart(fig_pays_annee, use_container_width=True) + # Affichage du commentaire + st.write(comment_pays_string) + + # Préparation du df pour le graph avec le nom détaillé pays + country_group_df_rework = df.groupby(["pays_rework", + "production_countries", + "release_year"]).count().reset_index()[["pays_rework", + "production_countries", + "release_year", + "TITRE"]].rename(columns={"TITRE": "Nb_titres", + "pays_rework": "Pays-Coproduction", + "production_countries": "Pays", + "release_year":"Année de sortie" }).sort_values("Nb_titres") + + country_group_df_rework["Année de sortie"] = \ + country_group_df_rework["Année de sortie"].astype("str") + + fig_pays_annee = px.bar(country_group_df_rework.sort_values(["Année de sortie"]), + y="Nb_titres", + x="Année de sortie", + color="Pays-Coproduction", + color_discrete_map={ + "International": "#D3C922", + "United States of America": "#0B5773", + "France": "#7BC0AC", + #"": "#E44F43" + }, + text_auto=True, + hover_data={"Pays-Coproduction":False, + "Année de sortie":True, "Pays":True}) + st.plotly_chart(fig_pays_annee, use_container_width=True) + + st.markdown("***(Passer le curseur sur 'International' pour voir le détail des pays)***") # LIEUX VISIONNAGE with st.container(): @@ -388,6 +361,339 @@ def load_data(file: str) -> pd.DataFrame: st.divider() with st.container(): st.subheader("Genres Cinématographiques") + ######################## + # load dataset + # Préparation du dataframe pour les films + genre_group_df = df[["id_tmdb", "genres", "TITRE", "TYPE", + "release_year"]].set_index(["id_tmdb", "TITRE", "TYPE","release_year"])\ + .apply(lambda x: x.str.split(",").explode()).reset_index() + + genre_group_df["genres"] = genre_group_df["genres"].apply(lambda x: x.lstrip().rstrip()) + + dfs = list(genre_group_df.groupby(["release_year","TYPE","TITRE"])) + st.write(dfs) + + #first_title = dict(dfs[0][0]) # noqa: ERA001 + + traces = [] + + button_layer_1_height = 1.08 + buttons_year = [] + buttons_type = [] + buttons_title = [] + + for i,d in enumerate(list(genre_group_df.groupby(["release_year"]))): + visible = [False] * len(list(genre_group_df.groupby(["release_year"]))) + visible[i] = True + name_year = d[0] + #name_type = d[0] # noqa: ERA001 + #name_title = d[0] # noqa: ERA001 + + traces.append( + px.treemap(d[1], + path=["genres"], #px.Constant("all"), + values="id_tmdb").update_traces(visible=True if i==0 else False).data[0], # noqa: SIM210 + ) + buttons_year.append(dict(label=f"{name_year}", + method="update", + args=[{"visible":visible}, + {"title":f"{name_year}"}])) + + updatemenus = [{"active":0, "buttons": buttons_year}] + + fig = go.Figure(data=traces, + layout=dict(updatemenus=updatemenus)) + + fig.update_layout(title="", title_x=0.5) + + st.plotly_chart(fig, theme=None) + + for i,d in enumerate(list(genre_group_df.groupby(["TITRE"]))): + visible = [False] * len(list(genre_group_df.groupby(["TITRE"]))) + visible[i] = True + #name_year = d[0] # noqa: ERA001 + #name_type = d[0] # noqa: ERA001 + name_title = d[0] + + traces.append( + px.treemap(d[1], + path=["genres"], #px.Constant("all"), + values="id_tmdb").update_traces(visible=True if i==0 else False).data[0], # noqa: SIM210 + ) + buttons_title.append(dict(label=f"{name_title}", + method="update", + args=[{"visible":visible}, + {"title":f"{name_title}"}])) + + updatemenus = [{"active":0, "buttons": buttons_title}] + + fig = go.Figure(data=traces, + layout=dict(updatemenus=updatemenus)) + + fig.update_layout(title="", title_x=0.5) + + st.plotly_chart(fig, theme=None) + + for i,d in enumerate(list(genre_group_df.groupby(["TYPE"]))): + visible = [False] * len(list(genre_group_df.groupby(["TYPE"]))) + visible[i] = True + #name_year = d[0] # noqa: ERA001 + name_type = d[0] + #name_title = d[0] # noqa: ERA001 + + traces.append( + px.treemap(d[1], + path=["genres"], #px.Constant("all"), + values="id_tmdb").update_traces(visible=True if i==0 else False).data[0], # noqa: SIM210 + ) + buttons_type.append(dict(label=f"{name_type}", + method="update", + args=[{"visible":visible}, + {"title":f"{name_type}"}])) + + + updatemenus = [{"active":0, "buttons": buttons_type}] + + fig = go.Figure(data=traces, + layout=dict(updatemenus=updatemenus)) + + fig.update_layout(title="", title_x=0.5) + + st.plotly_chart(fig, theme=None) + + """# je crée une liste de genres uniques + liste_genre_cine = list({g.lstrip().rstrip() for genre\ + in genre_group_df["genres"] for g in genre.split(",")}) + + # je compte le nombre de films avec au moins le genre pris en compte + genre_group_df = pd.concat([genre_group_df, pd.DataFrame(columns=liste_genre_cine)]) + for col in liste_genre_cine: + genre_group_df[col] = [ + 1 if col in o.split(",") else 0 for o in genre_group_df["genres"] + ] + st.dataframe(genre_group_df) + # j'ajoute une colonne qui fait la somme des films pour un genre donné + # et ajoute le type pour cette nouvelle ligne + total_film = dict( + genre_group_df.loc[genre_group_df["TYPE"] == "FILM"][liste_genre_cine].sum(), + ) + st.write(total_film) + + total_film = ( + pd.DataFrame.from_dict(total_film, orient="index") + .reset_index() + .rename(columns={0: "total_film", "index": "genres"}) + ) + st.dataframe(genre_group_df)""" + + genre_group_df = genre_group_df[["id_tmdb", "genres", + "release_year"]].groupby(["genres","release_year"]).count().reset_index() + + total_genre_dict = dict( + pd.pivot_table(genre_group_df, values="id_tmdb", + index=["genres"], + columns=["release_year"]).sum(axis="columns",numeric_only=True), + ) + + genre_group_df.insert(3,"total_genre", + genre_group_df["genres"].apply(lambda g:total_genre_dict[g])) + + st.dataframe(genre_group_df) + parents = [""]*len(genre_group_df["genres"].unique()) + + # Create figure + + fig = go.Figure(go.Treemap(labels=genre_group_df[["genres","total_genre"]]["genres"], + values=genre_group_df[["genres","total_genre"]]["total_genre"], + parents = parents)) + + # Add dropdowns + button_layer_1_height = 1.08 + fig.update_layout( + updatemenus=[ + dict( + buttons=[ + dict( + args=["colorscale", "Viridis"], + label="Viridis", + method="restyle", + ), + dict( + args=["colorscale", "Cividis"], + label="Cividis", + method="restyle", + ), + dict( + args=["colorscale", "Blues"], + label="Blues", + method="restyle", + ), + dict( + args=["colorscale", "Greens"], + label="Greens", + method="restyle", + ), + ], + direction="down", + pad={"r": 10, "t": 10}, + showactive=True, + x=0.1, + xanchor="left", + y=button_layer_1_height, + yanchor="top", + ), + dict( + buttons=[ + dict( + args=["reversescale", False], + label="False", + method="restyle", + ), + dict( + args=["reversescale", True], + label="True", + method="restyle", + ), + ], + direction="down", + pad={"r": 10, "t": 10}, + showactive=True, + x=0.37, + xanchor="left", + y=button_layer_1_height, + yanchor="top", + ), + dict( + buttons=[ + dict( + args=[{"contours.showlines": False, "type": "contour"}], + label="Hide lines", + method="restyle", + ), + dict( + args=[{"contours.showlines": True, "type": "contour"}], + label="Show lines", + method="restyle", + ), + ], + direction="down", + pad={"r": 10, "t": 10}, + showactive=True, + x=0.58, + xanchor="left", + y=button_layer_1_height, + yanchor="top", + ), + ], + ) + st.plotly_chart(fig, theme="streamlit") + + """# Update plot sizing + fig.update_layout( + width=800, + height=900, + autosize=False, + margin=dict(t=100, b=0, l=0, r=0), + ) + + # Update 3D scene options + fig.update_scenes( + aspectratio=dict(x=1, y=1, z=0.7), + aspectmode="manual" + ) + + # Add dropdowns + button_layer_1_height = 1.08 + fig.update_layout( + updatemenus=[ + dict( + buttons=list([ + dict( + args=["colorscale", "Viridis"], + label="Viridis", + method="restyle" + ), + dict( + args=["colorscale", "Cividis"], + label="Cividis", + method="restyle" + ), + dict( + args=["colorscale", "Blues"], + label="Blues", + method="restyle" + ), + dict( + args=["colorscale", "Greens"], + label="Greens", + method="restyle" + ), + ]), + direction="down", + pad={"r": 10, "t": 10}, + showactive=True, + x=0.1, + xanchor="left", + y=button_layer_1_height, + yanchor="top" + ), + dict( + buttons=list([ + dict( + args=["reversescale", False], + label="False", + method="restyle" + ), + dict( + args=["reversescale", True], + label="True", + method="restyle" + ) + ]), + direction="down", + pad={"r": 10, "t": 10}, + showactive=True, + x=0.37, + xanchor="left", + y=button_layer_1_height, + yanchor="top" + ), + dict( + buttons=list([ + dict( + args=[{"contours.showlines": False, "type": "contour"}], + label="Hide lines", + method="restyle" + ), + dict( + args=[{"contours.showlines": True, "type": "contour"}], + label="Show lines", + method="restyle" + ), + ]), + direction="down", + pad={"r": 10, "t": 10}, + showactive=True, + x=0.58, + xanchor="left", + y=button_layer_1_height, + yanchor="top" + ), + ] + ) + + fig.update_layout( + annotations=[ + dict(text="colorscale", x=0, xref="paper", y=1.06, yref="paper", + align="left", showarrow=False), + dict(text="Reverse
Colorscale", x=0.25, xref="paper", y=1.07, + yref="paper", showarrow=False), + dict(text="Lines", x=0.54, xref="paper", y=1.06, yref="paper", + showarrow=False) + ])""" + st.plotly_chart(fig, theme="streamlit") + + ######################## # Fonction pour créer le treemap @st.cache_data def get_chart_82052330(df: pd.DataFrame, liste: list[str], titre: str) -> None: @@ -401,7 +707,7 @@ def get_chart_82052330(df: pd.DataFrame, liste: list[str], titre: str) -> None: st.plotly_chart(fig, theme="streamlit") - +""" # Préparation du dataframe pour les films genre_group_df = df[["id_tmdb", "genres", "TITRE", "TYPE"]].drop_duplicates() @@ -428,7 +734,7 @@ def get_chart_82052330(df: pd.DataFrame, liste: list[str], titre: str) -> None: ) total_film.insert(2, "TYPE", "FILM") - get_chart_82052330(total_film, liste_genre_cine, "Répartition des genres (uniques)") + get_chart_82052330(total_film, liste_genre_cine, "Répartition des genres (uniques)")""" ### Analyses des sociétés de productions with st.container(): @@ -616,7 +922,7 @@ def get_chart_82052330(df: pd.DataFrame, liste: list[str], titre: str) -> None: # Répartition des producteurs - déjà ok # Nombre de films pour chaque type de récompense documentées # (Césars, Cannes, Oscars…) / par année de sortie - ok -# Année de sortie en fonction de nationalité +# Année de sortie en fonction de nationalité - ok # Genres en fonction de l'année de sortie # Genres en fonction de la nationalité # Nationalité en fonction du canal de diffusion From 14c89480c8b43243a3a0fa939404ad1520e9f1d1 Mon Sep 17 00:00:00 2001 From: Sandrine Date: Sun, 12 May 2024 14:43:09 +0200 Subject: [PATCH 3/4] =?UTF-8?q?ajout=20fonction=20pour=20filtres=20propres?= =?UTF-8?q?=20aux=20graphiques.=20ajout=20fonction=20pour=20activer=20les?= =?UTF-8?q?=20filtres.=20Ajout=20et=20mise=20=C3=A0=20jour=20des=20dataviz?= =?UTF-8?q?=20sur=20les=20pays=20d'origine=20des=20pays,=20les=20canaux=20?= =?UTF-8?q?de=20diffusion,=20les=20genres=20cin=C3=A9matographiques,=20les?= =?UTF-8?q?=20soci=C3=A9t=C3=A9s=20de=20production=20et=20les=20r=C3=A9com?= =?UTF-8?q?penses.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/odi_streamlit.py | 709 +++++++++++++++++++------------------------ 1 file changed, 318 insertions(+), 391 deletions(-) diff --git a/app/odi_streamlit.py b/app/odi_streamlit.py index b4d63dc..8704913 100644 --- a/app/odi_streamlit.py +++ b/app/odi_streamlit.py @@ -5,7 +5,6 @@ # Core Pkgs import pandas as pd import plotly.express as px -import plotly.graph_objects as go import streamlit as st # Other Pkgs @@ -61,6 +60,99 @@ def load_data(file: str) -> pd.DataFrame: annee = "release_year" df[annee] = pd.to_numeric(df[annee], errors="coerce").fillna(0).astype(int) +#Fonction pour créer des filtres pour les graphiques +def filtres_internes(df: pd.DataFrame) -> None: + col_filtre_annee, col_filtre_type, col_filtre_titre = st.columns(3) + with col_filtre_annee: + #filtre année de sortie + list_year = df["release_year"].sort_values().unique() + start_clr, end_clr = st.select_slider("Choisissez encore la/les date(s) d'analyse", + options=list_year, value=(min(list_year), max(list_year))) + with col_filtre_type: + #filtre type de contenu vu + type_contenu_choice = st.selectbox( + "Choisissez encore un type de contenu", + df["TYPE"].unique(), + index=None, + ) + with col_filtre_titre: + #filtre nom de l'oeuvre + choix_nom_oeuvre = st.multiselect("Choisissez encore un ou plusieurs film(s)", + df["TITRE"].sort_values().unique(), default=None) + return start_clr, end_clr,type_contenu_choice,choix_nom_oeuvre + +#Fonction pour créer un graphique en fonction des filtres +def application_filtres(df: pd.DataFrame, colonne:str) -> None : + start_clr = colonnes_filtres[0] + end_clr = colonnes_filtres[1] + type_contenu_choice = colonnes_filtres[2] + choix_nom_oeuvre = colonnes_filtres[3] + + # Préparation du dataframe pour les films + if len(choix_nom_oeuvre)!=0 and type_contenu_choice is not None: + df = df[(df["TITRE"].isin(choix_nom_oeuvre))&\ + (df["TYPE"]== type_contenu_choice)&\ + (df.release_year >= start_clr) & \ + (df.release_year <= end_clr)][ + ["id_tmdb", "TITRE", "TYPE", *colonne] + ].drop_duplicates() + if len(df) == 0: + df = df[ + ["id_tmdb", "TITRE", "TYPE", *colonne] + ].drop_duplicates() + with col_choix_film_prod: + st.markdown("#### :warning: Aucun film ne correspond à votre choix.\ + Veuillez modifier un ou plusieurs filtres", + ) + elif len(choix_nom_oeuvre)!=0 and type_contenu_choice is None: + df = df[(df["TITRE"].isin(choix_nom_oeuvre))&\ + (df.release_year >= start_clr) & \ + (df.release_year <= end_clr)][ + ["id_tmdb", "TITRE", "TYPE", *colonne] + ].drop_duplicates() + if len(df) == 0: + df = df[ + ["id_tmdb", "TITRE", "TYPE", *colonne] + ].drop_duplicates() + with col_choix_film_prod: + st.markdown("#### :warning: Aucun film ne correspond à votre choix.\ + Veuillez modifier un ou plusieurs filtres", + ) + elif len(choix_nom_oeuvre)==0 and type_contenu_choice is not None: + df = df[(df["TYPE"] == (type_contenu_choice))&\ + (df.release_year >= start_clr) & \ + (df.release_year <= end_clr)][ + ["id_tmdb", "TITRE", "TYPE", *colonne] + ].drop_duplicates() + if len(df) == 0: + df = df[ + ["id_tmdb", "TITRE", "TYPE", *colonne] + ].drop_duplicates() + with col_choix_film_prod: + st.markdown("#### :warning: Aucun film ne correspond à votre choix.\ + Veuillez modifier un ou plusieurs filtres", + ) + else: + df = df[(df.release_year >= start_clr) & \ + (df.release_year <= end_clr)][ + ["id_tmdb", "TITRE", "TYPE", *colonne] + ].drop_duplicates() + return df + +# Fonction pour créer le treemap +@st.cache_data +def get_chart_82052330(df: pd.DataFrame, liste: list[str], titre: str) -> None: + fig = px.treemap( + df, + path=[px.Constant("all"), liste], + values="total_film", # color='TYPE', + title=titre, + ) + fig.update_layout(margin={"t":50, "l":25, "r":25, "b":25}) + + st.plotly_chart(fig, theme="streamlit") + + logo= ("https://media.licdn.com/dms/image/D4E0BAQEZHVBxFn3OXQ/company-logo_200_200/" "0/1697116934909/cercle_thmatique_culture_the_shifters_logo?e=1718841600&v=beta" "&t=_2DWaEBrblIgXhgVASUipHTcJesOL6s1Sk2uH73Kx58") @@ -77,7 +169,7 @@ def load_data(file: str) -> pd.DataFrame: "Cette application analyse les données du sondage " "de **l'Observatoire des Imaginaires**. ", ) - with st.container(border=True): + with st.container(): st.markdown("**Filtres d'analyse**") #filtre année de sortie @@ -220,7 +312,7 @@ def load_data(file: str) -> pd.DataFrame: st.bar_chart(date_group_df, x="Année de sortie", y="Nb_titres") -with st.container(border=True): +with st.container(): st.subheader("Nationalité des contenus") col_pays, col_contenu_vide, col_pays_annee = st.columns([4, 0.5, 4]) @@ -291,428 +383,211 @@ def load_data(file: str) -> pd.DataFrame: st.markdown("***(Passer le curseur sur 'International' pour voir le détail des pays)***") +st.divider() + # LIEUX VISIONNAGE with st.container(): st.subheader("Canaux de diffusion") - canal_group_df = ( - df.groupby("channel") - .count()[["TITRE"]] - .rename(columns={"TITRE": "nb_titre"}) - .sort_values("nb_titre", ascending=False) - ) - canal_group_df["canal_percent"] = 100 * ( - canal_group_df.nb_titre / canal_group_df.nb_titre.sum() - ) - canal_country_group_df = ( - df.groupby(["channel", "pays_rework"]) - .count()[["TITRE"]] - .rename(columns={"TITRE": "nb_titre"}) - .sort_values("nb_titre", ascending=False) - .reset_index() - ) - col_text_canal, col_table_canal = st.columns([5, 3]) - with col_text_canal: - canal_visionne1 = canal_group_df.nb_titre.nlargest(2).reset_index()["channel"][ - 0 - ] - percent_canal_visionne1 = round(canal_group_df.canal_percent.nlargest(2)[0], 2) - canal_visionne2 = canal_group_df.nb_titre.nlargest(2).reset_index()["channel"][ - 1 - ] - percent_canal_visionne2 = round(canal_group_df.canal_percent.nlargest(2)[1], 2) + dico_canaux_diff = { + "Salle de Cinéma" : "Salle de Cinéma", + "TV/Streaming" : ["Netflix","Amazon Prime","Disney+","OCS","Mubi","La Cinetek","TF1", + "France TV","Canal+ / C8","M6 / W9","Arte / Arte.tv","Paramount+"], + "Location / VOD" : "Location / VOD (YouTube, MyCanal...)", + "Support physique" : "Support physique (VHS, DVD, Blu-Ray)", + "Téléchargement":"Téléchargement", + "Autre":"Autre"} - # Pre-calculate and capitalize channel names - channel1 = canal_visionne1.capitalize() - channel2 = canal_visionne2.capitalize() + canal_group_df = ( + df[["channel","TITRE","genres","id_tmdb","production_countries","release_year"]] + .groupby(["channel","TITRE","genres","production_countries","release_year"]) + .count().reset_index().sort_values("id_tmdb", ascending=False) + .rename(columns={"id_tmdb": "Nb_titres", + "production_countries": "Pays", + "release_year":"Année de sortie" })) - # Prepare the first part of the message - part1 = ( - f"Les contenus sont visionnés principalement sur :blue[{channel1}] " - f"(:blue[{percent_canal_visionne1}%]) et :blue[{channel2}] " - f"(:blue[{percent_canal_visionne2}%])." - ) + canal_group_df = canal_group_df.set_index(["channel","TITRE","Année de sortie", + "Pays","Nb_titres"])\ + .apply(lambda x: x.str.split(",").explode()).reset_index() - # Calculate country of origin for the most watched content on channel1 - cntr_df = canal_country_group_df[canal_country_group_df["channel"] == canal_visionne1] - top_country = cntr_df.nlargest(1, "nb_titre").reset_index()["pays_rework"][0] + canal_group_df = canal_group_df.set_index(["channel","TITRE","Année de sortie", + "Nb_titres","genres"])\ + .apply(lambda x: x.str.split(",").explode()).reset_index() - # Prepare the second part of the message - part2 = ( - f"\n\nLa majorité des contenus visionnés sur :blue[{channel1}] ont pour " - f"pays d'origine :blue[{top_country}] (:blue[%]), alors que la " - f"majorité des contenus français sont visionnés xxx (xxx%)." - ) + # Retrait des espaces inutiles + canal_group_df["genres"] = canal_group_df["genres"].apply(lambda x: x.lstrip().rstrip()) + canal_group_df["Pays"] = canal_group_df["Pays"]\ + .apply(lambda x: x.lstrip().rstrip()) - # Combine all parts and use markdown - st.markdown(part1 + part2) + canal_group_df["canal_percent"] = round(100 * ( + canal_group_df.Nb_titres / canal_group_df.Nb_titres.sum() + ),2) - # Les contenus sont visionnés principalement sur Netflix (29.91%) ou dans - # une salle de cinéma (28.97%). La majorité des contenus américains sont - # visionnés sur Netflix (40.48% des contenus US), alors que la majorité - # des contenus français sont visionnés au cinéma (44.19%). - # 23.36% des contenus sont visionnés sur un canal `autre` - # que la liste proposée (cf ci-dessous) - - # with col_table_canal: - # st.markdown(set(canal_group_df.reset_index().channel)) - -st.divider() -with st.container(): - st.subheader("Genres Cinématographiques") - ######################## - # load dataset - # Préparation du dataframe pour les films - genre_group_df = df[["id_tmdb", "genres", "TITRE", "TYPE", - "release_year"]].set_index(["id_tmdb", "TITRE", "TYPE","release_year"])\ - .apply(lambda x: x.str.split(",").explode()).reset_index() + # Ajout de la colonne "type de diffusion" qui regroupe les canaux par sur ensemble + canal_group_df["type de diffusion"]=\ + canal_group_df["channel"].apply(lambda c: \ + next(k for k, v in dico_canaux_diff.items() if c in v)) - genre_group_df["genres"] = genre_group_df["genres"].apply(lambda x: x.lstrip().rstrip()) + col_text_canal, col_graph_canal = st.columns([3,5]) + with col_text_canal: + canal_text_df = canal_group_df.groupby(["type de diffusion"])\ + .sum().reset_index().sort_values("canal_percent", ascending = False) - dfs = list(genre_group_df.groupby(["release_year","TYPE","TITRE"])) - st.write(dfs) + canal = iter(canal_text_df.nlargest(2,"canal_percent")["type de diffusion"]) + canal_percent = iter(canal_text_df.nlargest(2,"canal_percent")["canal_percent"]) - #first_title = dict(dfs[0][0]) # noqa: ERA001 + canal1 = next(canal) + canal_percent1 = round(next(canal_percent), 2) - traces = [] + canal2 = next(canal) + canal_percent2 = round(next(canal_percent), 2) - button_layer_1_height = 1.08 - buttons_year = [] - buttons_type = [] - buttons_title = [] + # Prepare the first part of the message + part1 = ( + f"Les contenus sont visionnés principalement en :blue[{canal1}] " + f"(:blue[{canal_percent1}%]) et :blue[{canal2}] " + f"(:blue[{canal_percent2}%])." + ) - for i,d in enumerate(list(genre_group_df.groupby(["release_year"]))): - visible = [False] * len(list(genre_group_df.groupby(["release_year"]))) - visible[i] = True - name_year = d[0] - #name_type = d[0] # noqa: ERA001 - #name_title = d[0] # noqa: ERA001 + # Combine all parts and use markdown + st.markdown(part1) - traces.append( - px.treemap(d[1], - path=["genres"], #px.Constant("all"), - values="id_tmdb").update_traces(visible=True if i==0 else False).data[0], # noqa: SIM210 - ) - buttons_year.append(dict(label=f"{name_year}", - method="update", - args=[{"visible":visible}, - {"title":f"{name_year}"}])) + with col_graph_canal: + canal_graph_df = canal_group_df.groupby(["type de diffusion","channel"])\ + .sum().reset_index().sort_values("canal_percent", ascending = False) - updatemenus = [{"active":0, "buttons": buttons_year}] + fig_canal = px.bar(canal_graph_df, x="type de diffusion", y="canal_percent", + color="channel") - fig = go.Figure(data=traces, - layout=dict(updatemenus=updatemenus)) + fig_canal.update_layout( + title="Pourcentage de titres par canal de diffusion", + xaxis_title="Canal de diffusion", + yaxis_title="Pourcentage de titres", + legend_title=None, + ) - fig.update_layout(title="", title_x=0.5) + st.plotly_chart(fig_canal) + st.divider() - st.plotly_chart(fig, theme=None) + # Nationalité en fonction du canal de diffusion : color = production_countries, x = channel + canal_country_group_df = ( + canal_group_df.groupby(["type de diffusion", "Pays"]) + .count()[["Nb_titres"]] + .sort_values("Nb_titres", ascending=False) + .reset_index() + ) - for i,d in enumerate(list(genre_group_df.groupby(["TITRE"]))): - visible = [False] * len(list(genre_group_df.groupby(["TITRE"]))) - visible[i] = True - #name_year = d[0] # noqa: ERA001 - #name_type = d[0] # noqa: ERA001 - name_title = d[0] + # Calculate country of origin for the most watched content on channel1 + cntr_df = canal_country_group_df[canal_country_group_df["type de diffusion"] == canal1] + top_country = cntr_df.nlargest(1, "Nb_titres").reset_index()["Pays"][0] - traces.append( - px.treemap(d[1], - path=["genres"], #px.Constant("all"), - values="id_tmdb").update_traces(visible=True if i==0 else False).data[0], # noqa: SIM210 + # Prepare the second part of the message + part2 = ( + f"\n\nLa majorité des contenus visionnés en :blue[{canal1}] ont pour " + f"pays d'origine :blue[{top_country}] (:blue[%]), alors que la " + f"majorité des contenus français sont visionnés xxx (xxx%)." ) - buttons_title.append(dict(label=f"{name_title}", - method="update", - args=[{"visible":visible}, - {"title":f"{name_title}"}])) - updatemenus = [{"active":0, "buttons": buttons_title}] + canal_graph_country_df = canal_group_df.groupby(["channel","Pays"])\ + .sum().reset_index().sort_values("canal_percent", ascending = False) - fig = go.Figure(data=traces, - layout=dict(updatemenus=updatemenus)) + fig_canal_country = px.bar(canal_graph_country_df, x="channel", y="canal_percent", + color="Pays") - fig.update_layout(title="", title_x=0.5) + fig_canal_country.update_layout( + title="Pourcentage de titres par canal de diffusion par pays", + xaxis_title="Canal de diffusion", + yaxis_title="Pourcentage de titres", + legend_title=None, + ) - st.plotly_chart(fig, theme=None) + st.plotly_chart(fig_canal_country) - for i,d in enumerate(list(genre_group_df.groupby(["TYPE"]))): - visible = [False] * len(list(genre_group_df.groupby(["TYPE"]))) - visible[i] = True - #name_year = d[0] # noqa: ERA001 - name_type = d[0] - #name_title = d[0] # noqa: ERA001 + # Combine all parts and use markdown + st.markdown(part2) - traces.append( - px.treemap(d[1], - path=["genres"], #px.Constant("all"), - values="id_tmdb").update_traces(visible=True if i==0 else False).data[0], # noqa: SIM210 - ) - buttons_type.append(dict(label=f"{name_type}", - method="update", - args=[{"visible":visible}, - {"title":f"{name_type}"}])) + # Genre en fonction du canal de diffusion : color = genres et x = channel + canal_graph_genres_df = canal_group_df.groupby(["channel","genres"])\ + .sum().reset_index().sort_values("canal_percent", ascending = False) + fig_canal_genres = px.bar(canal_graph_genres_df, x="channel", y="canal_percent", + color="genres") - updatemenus = [{"active":0, "buttons": buttons_type}] + fig_canal_genres.update_layout( + title="Pourcentage de titres par canal de diffusion par genre cinématographique", + xaxis_title="Canal de diffusion", + yaxis_title="Pourcentage de titres", + legend_title=None, + ) - fig = go.Figure(data=traces, - layout=dict(updatemenus=updatemenus)) + st.plotly_chart(fig_canal_genres) - fig.update_layout(title="", title_x=0.5) + # Année en fonction du canal de diffusion : color = Année de sortie et x = channel + canal_graph_annee_df = canal_group_df.groupby(["type de diffusion","Année de sortie"])\ + .sum().reset_index().sort_values("Année de sortie", ascending = False) - st.plotly_chart(fig, theme=None) + fig_canal_annee = px.line(canal_graph_annee_df, x="Année de sortie", y="canal_percent", + color="type de diffusion") - """# je crée une liste de genres uniques - liste_genre_cine = list({g.lstrip().rstrip() for genre\ - in genre_group_df["genres"] for g in genre.split(",")}) + fig_canal_annee.update_layout( + title="Pourcentage de titres par canal de diffusion par type de diffusion", + xaxis_title="Année de sortie", + yaxis_title="Pourcentage de titres", + legend_title=None, + ) - # je compte le nombre de films avec au moins le genre pris en compte - genre_group_df = pd.concat([genre_group_df, pd.DataFrame(columns=liste_genre_cine)]) - for col in liste_genre_cine: - genre_group_df[col] = [ - 1 if col in o.split(",") else 0 for o in genre_group_df["genres"] - ] - st.dataframe(genre_group_df) - # j'ajoute une colonne qui fait la somme des films pour un genre donné - # et ajoute le type pour cette nouvelle ligne - total_film = dict( - genre_group_df.loc[genre_group_df["TYPE"] == "FILM"][liste_genre_cine].sum(), - ) - st.write(total_film) + st.plotly_chart(fig_canal_annee) - total_film = ( - pd.DataFrame.from_dict(total_film, orient="index") - .reset_index() - .rename(columns={0: "total_film", "index": "genres"}) - ) - st.dataframe(genre_group_df)""" + # Les contenus sont visionnés principalement sur Netflix (29.91%) ou dans + # une salle de cinéma (28.97%). La majorité des contenus américains sont + # visionnés sur Netflix (40.48% des contenus US), alors que la majorité + # des contenus français sont visionnés au cinéma (44.19%). + # 23.36% des contenus sont visionnés sur un canal `autre` + # que la liste proposée (cf ci-dessous) - genre_group_df = genre_group_df[["id_tmdb", "genres", - "release_year"]].groupby(["genres","release_year"]).count().reset_index() + # with col_table_canal: + # st.markdown(set(canal_group_df.reset_index().channel)) - total_genre_dict = dict( - pd.pivot_table(genre_group_df, values="id_tmdb", - index=["genres"], - columns=["release_year"]).sum(axis="columns",numeric_only=True), - ) +st.divider() - genre_group_df.insert(3,"total_genre", - genre_group_df["genres"].apply(lambda g:total_genre_dict[g])) - - st.dataframe(genre_group_df) - parents = [""]*len(genre_group_df["genres"].unique()) - - # Create figure - - fig = go.Figure(go.Treemap(labels=genre_group_df[["genres","total_genre"]]["genres"], - values=genre_group_df[["genres","total_genre"]]["total_genre"], - parents = parents)) - - # Add dropdowns - button_layer_1_height = 1.08 - fig.update_layout( - updatemenus=[ - dict( - buttons=[ - dict( - args=["colorscale", "Viridis"], - label="Viridis", - method="restyle", - ), - dict( - args=["colorscale", "Cividis"], - label="Cividis", - method="restyle", - ), - dict( - args=["colorscale", "Blues"], - label="Blues", - method="restyle", - ), - dict( - args=["colorscale", "Greens"], - label="Greens", - method="restyle", - ), - ], - direction="down", - pad={"r": 10, "t": 10}, - showactive=True, - x=0.1, - xanchor="left", - y=button_layer_1_height, - yanchor="top", - ), - dict( - buttons=[ - dict( - args=["reversescale", False], - label="False", - method="restyle", - ), - dict( - args=["reversescale", True], - label="True", - method="restyle", - ), - ], - direction="down", - pad={"r": 10, "t": 10}, - showactive=True, - x=0.37, - xanchor="left", - y=button_layer_1_height, - yanchor="top", - ), - dict( - buttons=[ - dict( - args=[{"contours.showlines": False, "type": "contour"}], - label="Hide lines", - method="restyle", - ), - dict( - args=[{"contours.showlines": True, "type": "contour"}], - label="Show lines", - method="restyle", - ), - ], - direction="down", - pad={"r": 10, "t": 10}, - showactive=True, - x=0.58, - xanchor="left", - y=button_layer_1_height, - yanchor="top", - ), - ], - ) - st.plotly_chart(fig, theme="streamlit") +### Analyses des Genres Cinématographiques +with st.container(): + st.subheader("Genres Cinématographiques") - """# Update plot sizing - fig.update_layout( - width=800, - height=900, - autosize=False, - margin=dict(t=100, b=0, l=0, r=0), - ) + # Préparation du dataframe pour créer une ligne par genre, pays, continent poour chaque film + genre_df = df[["genres","production_countries","pays_rework","contient_list", + "continent","TYPE","release_year", "TITRE","id_tmdb"]]\ + .set_index(["production_countries","pays_rework","contient_list", + "continent", "TYPE","release_year", "TITRE","id_tmdb"])\ + .apply(lambda x: x.str.split(",").explode()).reset_index() - # Update 3D scene options - fig.update_scenes( - aspectratio=dict(x=1, y=1, z=0.7), - aspectmode="manual" - ) + genre_df = genre_df.set_index(["genres","pays_rework","contient_list", + "continent", "TYPE","release_year", "TITRE","id_tmdb"])\ + .apply(lambda x: x.str.split(",").explode()).reset_index() - # Add dropdowns - button_layer_1_height = 1.08 - fig.update_layout( - updatemenus=[ - dict( - buttons=list([ - dict( - args=["colorscale", "Viridis"], - label="Viridis", - method="restyle" - ), - dict( - args=["colorscale", "Cividis"], - label="Cividis", - method="restyle" - ), - dict( - args=["colorscale", "Blues"], - label="Blues", - method="restyle" - ), - dict( - args=["colorscale", "Greens"], - label="Greens", - method="restyle" - ), - ]), - direction="down", - pad={"r": 10, "t": 10}, - showactive=True, - x=0.1, - xanchor="left", - y=button_layer_1_height, - yanchor="top" - ), - dict( - buttons=list([ - dict( - args=["reversescale", False], - label="False", - method="restyle" - ), - dict( - args=["reversescale", True], - label="True", - method="restyle" - ) - ]), - direction="down", - pad={"r": 10, "t": 10}, - showactive=True, - x=0.37, - xanchor="left", - y=button_layer_1_height, - yanchor="top" - ), - dict( - buttons=list([ - dict( - args=[{"contours.showlines": False, "type": "contour"}], - label="Hide lines", - method="restyle" - ), - dict( - args=[{"contours.showlines": True, "type": "contour"}], - label="Show lines", - method="restyle" - ), - ]), - direction="down", - pad={"r": 10, "t": 10}, - showactive=True, - x=0.58, - xanchor="left", - y=button_layer_1_height, - yanchor="top" - ), - ] - ) + genre_df = genre_df.set_index(["genres","production_countries","pays_rework", + "continent", "TYPE","release_year", "TITRE","id_tmdb"])\ + .apply(lambda x: x.str.split(",").explode()).reset_index() - fig.update_layout( - annotations=[ - dict(text="colorscale", x=0, xref="paper", y=1.06, yref="paper", - align="left", showarrow=False), - dict(text="Reverse
Colorscale", x=0.25, xref="paper", y=1.07, - yref="paper", showarrow=False), - dict(text="Lines", x=0.54, xref="paper", y=1.06, yref="paper", - showarrow=False) - ])""" - st.plotly_chart(fig, theme="streamlit") + # Retrait des espaces inutiles + genre_df["genres"] = genre_df["genres"].apply(lambda x: x.lstrip().rstrip()) - ######################## - # Fonction pour créer le treemap - @st.cache_data - def get_chart_82052330(df: pd.DataFrame, liste: list[str], titre: str) -> None: - fig = px.treemap( - df, - path=[px.Constant("all"), liste], - values="total_film", # color='TYPE', - title=titre, - ) - fig.update_layout(margin={"t":50, "l":25, "r":25, "b":25}) + genre_df["production_countries"] = genre_df["production_countries"]\ + .apply(lambda x: x.lstrip().rstrip()) - st.plotly_chart(fig, theme="streamlit") + genre_df["contient_list"] = genre_df["contient_list"].apply(lambda x: x.lstrip().rstrip()) -""" - # Préparation du dataframe pour les films - genre_group_df = df[["id_tmdb", "genres", "TITRE", "TYPE"]].drop_duplicates() + # Ajout des colonnes de filtres + colonnes_filtres = filtres_internes(genre_df) + + # Création du dataframe pour le treemap en fonction des filtres choisis + genre_group_df = application_filtres(genre_df[["id_tmdb", "genres", "TITRE", "TYPE", + "release_year"]],["genres"]) # je crée une liste de genres uniques - liste_genre_cine = list({g for genre in genre_group_df["genres"] for g in genre.split(",")}) + liste_genre_cine = list({g for genre\ + in genre_group_df["genres"] for g in genre.split(",")}) # je compte le nombre de films avec au moins le genre pris en compte genre_group_df = pd.concat([genre_group_df, pd.DataFrame(columns=liste_genre_cine)]) @@ -732,9 +607,67 @@ def get_chart_82052330(df: pd.DataFrame, liste: list[str], titre: str) -> None: .reset_index() .rename(columns={0: "total_film", "index": "genres"}) ) - total_film.insert(2, "TYPE", "FILM") - get_chart_82052330(total_film, liste_genre_cine, "Répartition des genres (uniques)")""" + # Affichage du Treemap + get_chart_82052330(total_film, liste_genre_cine, "Répartition des genres (uniques)") + + + st.markdown("### Genres en fonction de la nationalité") + col_genre_pays, col_genre_vide, col_genre_annee = st.columns([3,2,3]) + + # Création du dataframe pour le scatter graph en fonction des filtres choisis + genre_group_df = application_filtres(genre_df[["genres","production_countries", + "pays_rework","contient_list","continent", + "TYPE","release_year","id_tmdb","TITRE"]] + ,["release_year","genres","production_countries","pays_rework","contient_list","continent"]) + + genre_group_df = genre_group_df.groupby(["genres","production_countries","pays_rework", + "contient_list","continent", "TYPE","release_year"])\ + .count().reset_index().rename(columns={"production_countries":"pays", + "contient_list":"contient", + "id_tmdb":"nb titres", + "release_year":"année"}) + with col_genre_pays : + fig_scat = px.scatter(genre_group_df, x="genres", y="pays", + color="contient",size="nb titres", hover_data="genres", + color_discrete_map={ + "North America": "#D3C922", + #"North America": "#0B5773", + "Europe": "#7BC0AC", + #"Europe": "#E44F43", # noqa: ERA001 + }) + + fig_scat.update_layout(legend=dict( + orientation="h", + font=dict(size= 10), + yanchor="bottom", + y=1.02, + xanchor="right", + x=1, + )) + + st.plotly_chart(fig_scat, theme="streamlit") + + with col_genre_annee: + fig_scat_year = px.scatter(genre_group_df, x="genres", y="année", + color="contient",size="nb titres", hover_data="genres", + color_discrete_map={ + "North America": "#D3C922", + #"North America": "#0B5773", + "Europe": "#7BC0AC", + #"Europe": "#E44F43", # noqa: ERA001 + }) + + fig_scat_year.update_layout(legend=dict( + orientation="h", + font=dict(size= 10), + yanchor="bottom", + y=1.02, + xanchor="right", + x=1, + )) + + st.plotly_chart(fig_scat_year, theme="streamlit") ### Analyses des sociétés de productions with st.container(): @@ -792,7 +725,7 @@ def get_chart_82052330(df: pd.DataFrame, liste: list[str], titre: str) -> None: ["id_tmdb", "TITRE", "TYPE", "production_companies"] ].drop_duplicates() - # je crée une liste de genres uniques + # je crée une liste de maisons de productions liste_production_cine = list({p for prod in productions_df["production_companies"] for p in prod.split(",") @@ -824,13 +757,9 @@ def get_chart_82052330(df: pd.DataFrame, liste: list[str], titre: str) -> None: with col_choix_film_prod: # Combine all parts and use markdown - prod_comment = ( - f"**Répartition des sociétes de productions** " - f"pour :blue[{type_contenu_choice}] ont pour " - f"pays d'origine :blue[{choix_nom_oeuvre}] (:blue[%]), alors que la " - f"majorité des contenus français sont visionnés xxx (xxx%)." - ) + prod_comment = ("*Texte d'analyse ? Filtre ?*") st.markdown(prod_comment) + with col_prod_graph: get_chart_82052330( total_film_prod, liste_production_cine, "Répartition des producteurs", @@ -844,7 +773,6 @@ def get_chart_82052330(df: pd.DataFrame, liste: list[str], titre: str) -> None: award_df = df[ ["id_tmdb", "TITRE", "TYPE", "nb_recompense", "liste_festival","release_year"] ].drop_duplicates() - st.dataframe(award_df) else : award_df = df[df["TITRE"].isin(choix_nom_oeuvre)][ ["id_tmdb", "TITRE", "TYPE", "nb_recompense", "liste_festival","release_year"] @@ -884,7 +812,6 @@ def get_chart_82052330(df: pd.DataFrame, liste: list[str], titre: str) -> None: (award_df.release_year <= end_clr)][liste_award_cine].sum(), ) else : - st.write(award_df) total_film_award = dict( award_df[(award_df["liste_festival"].notnull())&\ (award_df.release_year >= start_clr) &\ @@ -919,15 +846,15 @@ def get_chart_82052330(df: pd.DataFrame, liste: list[str], titre: str) -> None: # Répartition des années de sortie # Répartition des canaux de diffusion # Répartition des genres (uniques) - ok -# Répartition des producteurs - déjà ok +# Répartition des producteurs - ok # Nombre de films pour chaque type de récompense documentées # (Césars, Cannes, Oscars…) / par année de sortie - ok # Année de sortie en fonction de nationalité - ok -# Genres en fonction de l'année de sortie -# Genres en fonction de la nationalité -# Nationalité en fonction du canal de diffusion -# Genre en fonction du canal de diffusion -# Année en fonction du canal de diffusion +# Genres en fonction de l'année de sortie - ok +# Genres en fonction de la nationalité - ok +# Nationalité en fonction du canal de diffusion - ok +# Genre en fonction du canal de diffusion - ok +# Année en fonction du canal de diffusion - ok # TODO Analyse des doublons # Pour chaque contenu présents plusieurs fois: From 42c5149795768cdce2cdcb42d6c4fff229f14295 Mon Sep 17 00:00:00 2001 From: scorreia Date: Thu, 16 May 2024 23:02:34 +0200 Subject: [PATCH 4/4] add missing plotly.graph_objects import --- app/odi_streamlit.py | 1 + 1 file changed, 1 insertion(+) diff --git a/app/odi_streamlit.py b/app/odi_streamlit.py index 8704913..535422a 100644 --- a/app/odi_streamlit.py +++ b/app/odi_streamlit.py @@ -5,6 +5,7 @@ # Core Pkgs import pandas as pd import plotly.express as px +import plotly.graph_objects as go import streamlit as st # Other Pkgs