<jupyter_start><jupyter_text>VisualisationDurant cet ultime chapitre, nous utiliserons une librairie de visualisation très connue dans le monde scientifique : *Matplotlib*. Mais avant cela, reprenons notre structure de données à l’état dans lequel nous l’avons laissée au chapitre précédent.La première étape consistait à récupérer et ordonner les données du fichier :<jupyter_code>"""Récupérer et ordonner les données"""

# Importation des modules
import csv
from collections import defaultdict

# Chargement de la ressource dans une variable 'fichier'
with open('notes.csv') as fichier:

    # Création d'un lecteur de fichier
    lecteur = csv.DictReader(fichier, delimiter='\t')

    # Sauvegarde des lignes du fichier
    data = [ ligne for ligne in lecteur ]

# Une liste de tuples par discipline
data_dict = defaultdict(list)

for d in data:
    data_dict[d['discipline']].append(
        ( d['date'], d['note'] )
    )

# Tri en place des dates par discpline
for discipline, dates in data_dict.items():
    dates.sort()<jupyter_output><empty_output><jupyter_text>Ensuite, nous avons effectué un calcul de la moyenne à date pour chaque discipline :<jupyter_code>"""Calcul de la moyenne à date pour chaque discipline"""

for discipline, resultats in data_dict.items():

    # Total initialisé à 0
    total = 0

    # Pour chaque tour dans la boucle de la discipline
    for i, (date, note) in enumerate(resultats):

        # Calcul du total
        total += int(note)

        # Moyenne
        moyenne = total / (i + 1)

        # La ligne courante (date, note), devient (date, note, moyenne)
        resultats[i] = (date, note, moyenne)<jupyter_output><empty_output><jupyter_text>Puis nous avons calculé la moyenne générale actualisée à chaque date :<jupyter_code>"""
    Calculer une moyenne générale :
    1. Préparer la structure de données
"""

# Insertion d'une clé "Générale"
data_dict['Générale'] = dict()

# Pour chaque résultat dans le dictionnaire
for discipline, resultat in data_dict.items():

    # Si la discipline est différente de "Générale"
    if discipline != 'Générale':

        # Pour chaque triplet de date, note et moyenne
        for date, note, moyenne in resultat:

            # Ajouter une clé date avec pour valeur une structure float vide
            data_dict['Générale'][date] = float()
"""
    Calculer une moyenne générale :
    2. Ajouter le calcul
"""

# Compteur et total initialisés à 0
compteur, total = 0, 0

# Pour chaque date unique
for date_unique in sorted(data_dict['Générale']):

    # Parcourir le dictionnaire
    for discipline, resultat in data_dict.items():

        # Seulement si la discipline n'est pas "Générale"
        if discipline != 'Générale':

            # On déplie le triplet
            for date, note, moyenne in resultat:

                # On vérifie que la date du résultat correspond à la date analysée
                if date == date_unique:

                    # Incrémentation du nombre de notes
                    compteur += 1

                    # Addition au total
                    total += int(note)

                    # Modification de la moyenne pour le jour
                    data_dict['Générale'][date] = total / compteur<jupyter_output><empty_output><jupyter_text>Trier un dictionnaireDernière opération préparatoire avant l’affichage des diagrammes, nous allons trier les données de la clé `Générale` dans le dictionnaire `data_dict` dans l’ordre chronologique. Trier un dictionnaire est un peu plus délicat que trier une liste. Il n’existe par exemple pas de méthode `sort()` qui fasse un tri en place. La solution consiste à utiliser la fonction générale `sorted()` en spécifiant une clé de tri grâce au paramètre `key`. Comme les données sont représentées sous la forme `date: moyenne`, la clé de tri est bien la `date` et non la moyenne. On opère alors grâce à une fonction anonyme ou *lambda* :<jupyter_code># Tri par date
# Remplacer les données actuelles par celles triées par date
data_dict['Générale'] = sorted(data_dict['Générale'].items(), key=lambda d:d[0])<jupyter_output><empty_output><jupyter_text>Un avantage non négligeable de cette technique est qu’elle transforme ensuite ce qui était un dictionnaire en liste de tuples, la structure choisie pour les autres clés de notre `data_dict` !<jupyter_code># Affichage des 5 premiers résultats de la moyenne générale
data_dict['Générale'][:5]<jupyter_output><empty_output><jupyter_text>Produire des diagrammes Un diagramme en barresPour notre premier diagramme, l’objectif est simple : il s’agira de représenter visuellement la quantité de plusieurs modalités. Prenons le tirage d’un dés à six faces. Les modalités possibles sont limitées : soit le 1 est tiré, soit le 2… jusqu’au 6. Effectuons une centaine de tirages aléatoires de ce dé et comptabilisons le nombre de tirages pour chaque face :<jupyter_code>from collections import Counter
from random import choices

# Une liste des faces d'un dé
faces = list(range(1, 7))

tirages = Counter(choices(faces, k=100))<jupyter_output><empty_output><jupyter_text>Pour rappel, un objet `Counter` ressemble à un dictionnaire, que nous pouvons ensuite trier par clé :<jupyter_code>tirages = sorted(tirages.items(), key=lambda d:d[0])<jupyter_output><empty_output><jupyter_text>Notre variable `tirages` contient une liste de tuples avec toutes les données dont nous avons besoin. La première valeur de chaque tuple correspond à la face d’un dé, quant à la seconde, elle correspond au nombre de fois où cette face a été tirée.Un diagramme se positionne dans un plan cartésien à deux axes : un axe horizontal pour les abscisses (noté $x$) et un axe vertical pour les ordonnées (noté $y$). Répartissons nos données dans deux listes distinctes :<jupyter_code># Axe horizontal : faces d'un dés
x = [ face for face, nb in tirages ]

# Axe vertical : nombre de tirages
y = [ nb for face, nb in tirages ]<jupyter_output><empty_output><jupyter_text>Occupons-nous à présent de la réalisation du diagramme. Elle passe par l’appel à un module `matplotlib` :<jupyter_code># Import du package "pyplot" renommé "plt"
import matplotlib.pyplot as plt<jupyter_output><empty_output><jupyter_text>Il ne nous reste plus qu'à utiliser la méthode `bar()` avec nos données :<jupyter_code>plt.bar(x, y)<jupyter_output><empty_output><jupyter_text>Parmi les améliorations possibles, définissons titres et légendes :<jupyter_code># Tracer une figure
plt.figure()

# Un titre
plt.title('Tirages d’un dé à 6 faces')

# Légende des abscisses
plt.xlabel('Faces du dé')

# Légende des ordonnées
plt.ylabel('Nombre de tirages')

# Construire le diagramme en barres
plt.bar(x, y)

# Afficher
plt.show()<jupyter_output><empty_output><jupyter_text>Une courbe d’évolutionPrenons l’exemple de l’évolution du nombre de personnes hospitalisées de la Covid en Indre-et-Loire entre le 1er janvier et le 1er juin 2021. Les données sont les suivantes :<jupyter_code>x = ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin']
y = [155, 167, 174, 209, 218, 144]<jupyter_output><empty_output><jupyter_text>À toi d’essayer de paramétrer la courbe en utilisant cette fois-ci la méthode `plot()` :<jupyter_code># Ton code ici<jupyter_output><empty_output><jupyter_text>Un nuage de pointsUn nuage de points est une manière élégante de représenter la distribution de valeurs tout en déterminant rapidement une tendance centrale. Dans l’exemple que nous suivons, plusieurs notes peuvent tomber un même jour. Réalisons deux listes :1. toutes les dates sans dédoublonnage ;2. toutes les notes.<jupyter_code># Une liste des données
donnees = list()

# Pour chaque discipline
for discipline, resultats in data_dict.items():
    # Tant qu'elle ne correspond pas à "Générale"
    if discipline != 'Générale':
        # Insertion d'un tuple (date, note) dans la liste
        for date, note, moyenne in resultats:
            donnees.append(tuple([date, int(note)]))

# Tri des tuples par ordre chronologique
donnees = sorted(donnees, key=lambda t:t[0])<jupyter_output><empty_output><jupyter_text>Préparons nos axes $x$ et $y$ :<jupyter_code>x = [ date for date, note in donnees ]
y = [ note for date, note in donnees ]<jupyter_output><empty_output><jupyter_text>Avec la méthode `scatter()` et quelques autres aménagements, affichons notre nuage de points :<jupyter_code># Tracer une un plan avec certaines dimensions
plt.figure(figsize=(15,6))

# Les notes, sur l'axe des ordonnées, vont de 0 à 20
plt.ylim(0,21)

# Formatage automatique des dates (rotation + alignement)
plt.gcf().autofmt_xdate()

# Construire le nuage de points
plt.scatter(x, y)

# Afficher une date sur deux pour plus de visibilité
ax = plt.gca()
for label in ax.xaxis.get_ticklabels()[::2]:
    label.set_visible(False)

# Afficher
plt.show()<jupyter_output><empty_output><jupyter_text>En un clin d’œil, grâce à ce genre de représentations, on observe que les notes de l’élève que nous suivons se situent dans une fourchette entre 5 et 15.  Évolution de la moyenne en mathématiquesTu devrais être capable d’afficher sur une courbe l’évolution de la moyenne en mathématiques de notre élève. **Attention !** N’oublie pas que les notes sont au format *chaîne de caractères* et que tu devras probablement les convertir en entiers numériques.<jupyter_code># Une liste de dates en abscisses

# Une liste de moyennes en ordonnées

# Tracer une un plan avec certaines dimensions


# La moyenne, sur l'axe des ordonnées, peut s'étendre de 0 à 20


# Titre du diagramme


# Légende de l'axe des ordonnées


# Formatage automatique des dates


# Construction de la courbe


# Affichage du diagramme<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.07977178423236514, 'fraction_numerical': 0.006742738589211619, 'mean_word_length': 4.371030640668524, 'pattern_counts': {'":': 0, '<': 69, '<?xml version=': 0, '>': 69, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '17', 'dir': 'jupyter-structured-clean-dedup', 'id': '433454', 'license': 'MIT', 'n_tokens_mistral': 3249, 'n_tokens_neox': 3216, 'n_words': 1165, 'path': '6. Visualisation.ipynb', 'repo_name': 'Alex-bzh/aymeric', 'size': '9640'}