diff --git a/module3/avare_vincent_dargaud.html b/module3/avare_vincent_dargaud.html new file mode 100644 index 0000000000000000000000000000000000000000..8a6fce7e7ed950ed4149614dca55cbb813505652 --- /dev/null +++ b/module3/avare_vincent_dargaud.html @@ -0,0 +1,13753 @@ + + +
+ +with open("moliere_avare.txt", "r", encoding="utf-8") as f:
+ texte = f.read()
+
+print(texte[:500]) # affiche les 500 premiers caractères pour vérifier
+import re
+import unicodedata
+from collections import defaultdict, Counter
+
+import pandas as pd
+import numpy as np
+import matplotlib.pyplot as plt
+
+plt.rcParams["figure.figsize"] = (9, 5)
+
+def strip_accents(s: str) -> str:
+ return ''.join(c for c in unicodedata.normalize('NFD', s)
+ if unicodedata.category(c) != 'Mn')
+
+def normalize_name(raw: str) -> str:
+ s = raw.strip()
+ s = s.replace('’', "'")
+ s = s.replace('ſ', 's') # vieilles ligatures éventuelles
+ s = strip_accents(s).upper()
+ s = re.sub(r'[^A-Z\- ]+', '', s) # garde lettres/espaces/tirets
+ s = re.sub(r'\s+', ' ', s).strip()
+ return s
+
+def word_count(text: str) -> int:
+ # enlève didascalies [ ... ] ( ... ) et tirets de réplique
+ text = re.sub(r'\[[^\]]*\]', ' ', text)
+ text = re.sub(r'\([^)]*\)', ' ', text)
+ text = text.replace('–', ' ')
+ tokens = re.findall(r"[A-Za-zÀ-ÖØ-öø-ÿ']+", text)
+ return len(tokens)
+with open("moliere_avare.txt", "r", encoding="utf-8") as f:
+ raw = f.read()
+
+# normalisation minimale
+raw = raw.replace('\r\n', '\n').replace('\r', '\n')
+acte = "INCONNU"
+scene = "INCONNUE"
+
+# compte global par personnage
+wc_by_char = Counter()
+
+# compte par personnage ET par scène
+wc_by_char_scene = defaultdict(int)
+
+lines = raw.split('\n')
+i = 0
+while i < len(lines):
+ line = lines[i].strip()
+
+ # titres d'acte / scène (markdown)
+ m_acte = re.match(r'^\s*##+\s*Acte\b\s*(.*)$', line, flags=re.I)
+ m_scene = re.match(r'^\s*###+\s*Sc[eè]ne\b\s*(.*)$', line, flags=re.I)
+ if m_acte:
+ suffix = m_acte.group(1).strip()
+ acte = f"ACTE {suffix or '?'}"
+ i += 1
+ continue
+ if m_scene:
+ suffix = m_scene.group(1).strip()
+ scene = f"SCENE {suffix or '?'}"
+ i += 1
+ continue
+
+ # ligne de locuteur (MAJUSCULES + point)
+ m_speaker = re.match(r"^([A-ZÉÈÀÂÎÔÛÄËÏÖÜÇŒÆ'\- ]+)\.\s*$", line)
+ if m_speaker:
+ raw_name = m_speaker.group(1)
+ name = normalize_name(raw_name)
+
+ # récupérer la réplique (lignes suivantes jusqu'à ligne vide ou nouveau locuteur/titre)
+ i += 1
+ speech_lines = []
+ while i < len(lines):
+ nxt = lines[i]
+ if not nxt.strip():
+ break
+ if re.match(r'^\s*##+', nxt): # nouveau titre acte/scène
+ break
+ if re.match(r"^([A-ZÉÈÀÂÎÔÛÄËÏÖÜÇŒÆ'\- ]+)\.\s*$", nxt.strip()):
+ break
+ speech_lines.append(nxt)
+ i += 1
+
+ speech = "\n".join(speech_lines)
+ n = word_count(speech)
+ if n > 0:
+ wc_by_char[name] += n
+ key_scene = f"{acte} • {scene}"
+ wc_by_char_scene[(name, key_scene)] += n
+ continue
+
+ i += 1
+
+# DataFrames
+df_total = pd.DataFrame(list(wc_by_char.items()), columns=["personnage", "mots"])\
+ .sort_values("mots", ascending=False).reset_index(drop=True)
+
+df_scene = pd.DataFrame(list(wc_by_char_scene.items()), columns=["pair", "mots"])
+df_scene[["personnage", "scene"]] = pd.DataFrame(df_scene["pair"].tolist(), index=df_scene.index)
+df_scene = df_scene.drop(columns=["pair"])
+print(type(wc_by_char), len(wc_by_char))
+print(list(wc_by_char.items())[:5]) # aperçu des 5 premiers
+topN = 10 # nombre de personnages à afficher
+ax = df_total.head(topN).iloc[::-1].plot(
+ kind="barh",
+ x="personnage",
+ y="mots",
+ color="cornflowerblue",
+ legend=False
+)
+ax.set_xlabel("Nombre de mots prononcés")
+ax.set_ylabel("")
+ax.set_title(f"L'Avare — Top {topN} orateurs")
+plt.tight_layout()
+plt.savefig("avare_top_orateurs.png", dpi=150)
+plt.show()
+main_chars = set(df_total.head(5)["personnage"])
+tmp = df_scene.copy()
+tmp["perso_grp"] = np.where(tmp["personnage"].isin(main_chars), tmp["personnage"], "AUTRES")
+
+pivot = tmp.pivot_table(index="scene", columns="perso_grp", values="mots", aggfunc="sum").fillna(0)
+pivot = pivot.reindex(sorted(pivot.index), axis=0)
+
+pivot.plot(kind="bar", stacked=True, figsize=(12,6))
+plt.xlabel("Scènes")
+plt.ylabel("Mots prononcés")
+plt.title("Répartition par scène (personnages principaux)")
+plt.tight_layout()
+plt.savefig("avare_par_scene.png", dpi=150)
+plt.show()
+idx = df_scene.groupby("scene")["mots"].idxmax()
+df_winner = df_scene.loc[idx, ["scene", "personnage", "mots"]].sort_values("scene")
+df_winner.head(20)
+Ce document propose une exploration computationnelle du texte de L’Avare, en s’appuyant sur les données disponibles sur le site de l’OBVIL. +L’objectif est d’analyser la répartition de la parole entre les personnages — en particulier la quantité de mots prononcés, leur distribution selon les scènes, et la dynamique d’interlocution implicite.
+Cette approche vise à relier les structures littéraires visibles (le texte, les dialogues) à des structures invisibles : rapports de pouvoir, densité psychologique des scènes, et hiérarchie dramatique implicite.
+ +Le texte brut est issu du projet OBVIL. +Nous avons téléchargé la version au format texte brut (.txt) et l’avons placée dans notre environnement Jupyter. +Chaque ligne contenant le nom d’un personnage suivi de ses répliques a été extraite à l’aide d’une expression régulière.
+ +import re, pandas as pd, numpy as np, matplotlib.pyplot as plt
+# (et tout ton parsing jusqu’à la création de df_total et df_scene)
+Le premier graphique illustre la quantité totale de mots prononcés par chaque personnage dans l’ensemble de la pièce.
+On observe que Harpagon domine nettement la parole, suivi de Cléante et de Frosine.
+Cette hiérarchie reflète déjà une logique dramatique : Harpagon, figure de l’avarice incarnée, occupe l’espace verbal comme il occupe l’espace matériel.
plt.imshow(plt.imread("avare_top_orateurs.png"))
+plt.axis("off")
+plt.show()
+Le graphique suivant montre, pour chaque scène, la proportion de mots prononcés par les personnages principaux.
+Cette visualisation permet de détecter les bascules de tension : certaines scènes sont dominées par Frosine, d’autres par Cléante ou Élise, révélant la mécanique d’équilibre typique de Molière.
On perçoit aussi une alternance rythmique : la parole circule comme un bien disputé — signe que, chez Molière, le langage lui-même devient monnaie d’échange.
+ +plt.imshow(plt.imread("avare_par_scene.png"))
+plt.axis("off")
+plt.show()
+L’analyse computationnelle des dialogues de L’Avare révèle un ordre latent : celui de la parole comme capital symbolique. +Plus un personnage parle, plus il contrôle la scène ; mais certains, comme Frosine, dominent sans posséder le pouvoir matériel, tandis que d’autres, comme Élise, sont souvent présents par le silence. +Ce contraste entre parole et pouvoir forme la véritable tension du texte.
+Ainsi, derrière l’économie de l’argent se joue une économie du verbe — où parler, c’est dépenser, et se taire, c’est accumuler.
+ +
+