001_04 — Création d'un graphe avec gestion DataFrame

Cahier des charges

1
# CDC 001_04

Code Python

1
# TD_EDC_01_001_04.py
2
# Résumé : Crée un fichier Excel avec un graphe nuage de points N(i) vs ttf(i)
3
# en utilisant pandas DataFrame pour la gestion des données et xlsxwriter pour le graphe
4
from pathlib import Path
5
import subprocess
6
import pandas as pd
7
import xlsxwriter
8
9
10
def build_paths() -> Path:
11
    """Calcule le chemin du fichier Excel de sortie."""
12
    script = Path(__file__).resolve()
13
    root = script.parent.parent
14
    stem = script.stem
15
    base_dir_name = script.parent.name
16
    xlsx_dir = root / f"{base_dir_name}_do"
17
    xlsx_dir.mkdir(parents=True, exist_ok=True)
18
    
19
    xlsx_path = (xlsx_dir / f"{stem}.xlsx").resolve()
20
    return xlsx_path
21
22
23
def delete_if_exists(file_path: Path) -> None:
24
    """Supprime le fichier s'il existe déjà."""
25
    if file_path.exists():
26
        file_path.unlink()
27
28
29
def prepare_data(n: int = 9, ttf_values: list = None) -> pd.DataFrame:
30
    """Prépare les données sous forme de DataFrame pandas."""
31
    
32
    # Créer les colonnes
33
    i_values = list(range(n + 1))  # [0, 1, 2, ..., 9]
34
    
35
    # Calculer dN(i) : 0 pour i=0, puis 1 pour i≥1
36
    dN_values = [0] + [1] * n  # [0, 1, 1, 1, ..., 1]
37
    
38
    # Calculer N(i) : commence à n et décrémente de dN(i)
39
    N_values = [n - i for i in range(n + 1)]  # [9, 8, 7, ..., 0]
40
    
41
    # Créer le DataFrame
42
    df = pd.DataFrame({
43
        'i': i_values,
44
        'ttf(i)': ttf_values if ttf_values else [0] * (n + 1),
45
        'dN(i)': dN_values,
46
        'N(i)': N_values
47
    })
48
    
49
    return df
50
51
52
def write_dataframe_to_excel(xlsx_path: Path, df: pd.DataFrame) -> None:
53
    """Écrit le DataFrame dans la feuille 'Données' (écrase si existe)."""
54
    
55
    # Utiliser openpyxl pour gérer l'écrasement de feuille
56
    from openpyxl import load_workbook, Workbook
57
    from openpyxl.utils.dataframe import dataframe_to_rows
58
    
59
    # Créer ou charger le workbook
60
    if xlsx_path.exists():
61
        workbook = load_workbook(str(xlsx_path))
62
        # Supprimer la feuille "Données" si elle existe
63
        if "Données" in workbook.sheetnames:
64
            del workbook["Données"]
65
    else:
66
        workbook = Workbook()
67
        # Supprimer la feuille par défaut
68
        if "Sheet" in workbook.sheetnames:
69
            del workbook["Sheet"]
70
    
71
    # Créer la feuille "Données"
72
    worksheet = workbook.create_sheet("Données")
73
    
74
    # Écrire le DataFrame
75
    for r in dataframe_to_rows(df, index=False, header=True):
76
        worksheet.append(r)
77
    
78
    # Sauvegarder
79
    workbook.save(str(xlsx_path))
80
    print(f"✓ DataFrame écrit dans la feuille 'Données' de {xlsx_path}")
81
82
83
def add_chart_from_data_sheet(xlsx_path: Path) -> None:
84
    """Lit les données de la feuille 'Données' et ajoute un graphe avec xlsxwriter."""
85
    
86
    # On ne peut pas modifier un fichier existant avec xlsxwriter
87
    # Il faut tout recréer : lire avec openpyxl, réécrire avec xlsxwriter
88
    from openpyxl import load_workbook
89
    import pandas as pd
90
    
91
    # Lire les données de la feuille "Données"
92
    workbook_read = load_workbook(str(xlsx_path))
93
    worksheet = workbook_read["Données"]
94
    
95
    # Convertir en DataFrame
96
    data = []
97
    headers = []
98
    for i, row in enumerate(worksheet.iter_rows(values_only=True)):
99
        if i == 0:
100
            headers = list(row)
101
        else:
102
            data.append(row)
103
    
104
    df = pd.DataFrame(data, columns=headers)
105
    workbook_read.close()
106
    
107
    # Recréer le fichier avec xlsxwriter (comme 001_03)
108
    workbook = xlsxwriter.Workbook(str(xlsx_path))
109
    worksheet = workbook.add_worksheet("Données")
110
    
111
    # Écrire les en-têtes
112
    for col_num, col_name in enumerate(df.columns):
113
        worksheet.write(0, col_num, col_name)
114
    
115
    # Écrire les données
116
    for row_num, row_data in enumerate(df.values, start=1):
117
        for col_num, value in enumerate(row_data):
118
            worksheet.write(row_num, col_num, value)
119
    
120
    # Créer le graphe EXACTEMENT comme dans 001_03
121
    chart = workbook.add_chart({'type': 'scatter', 'subtype': 'straight_with_markers'})
122
    
123
    n_rows = len(df)
124
    
125
    chart.add_series({
126
        'name':       'N(ttf)',
127
        'categories': ['Données', 1, 1, n_rows, 1],  # ttf(i) : B2:B11
128
        'values':     ['Données', 1, 3, n_rows, 3],  # N(i) : D2:D11
129
    })
130
    
131
    chart.set_title({'name': 'N(i) en fonction de ttf(i)'})
132
    chart.set_x_axis({'name': 'ttf(i)'})
133
    chart.set_y_axis({'name': 'N(i)'})
134
    chart.set_style(13)
135
    
136
    chart_sheet = workbook.add_worksheet("Graphe")
137
    chart_sheet.insert_chart('A1', chart, {'x_scale': 2, 'y_scale': 2})
138
    
139
    workbook.close()
140
    print(f"✓ Graphe ajouté en lisant les données de la feuille 'Données'")
141
142
143
def open_in_excel(xlsx_path: Path) -> None:
144
    """Ouvre le classeur généré dans Excel."""
145
    subprocess.Popen(["start", "excel", str(xlsx_path)], shell=True)
146
147
148
def main() -> None:
149
    """Pipeline : prépare les données avec pandas, crée le fichier Excel avec graphe."""
150
    xlsx_path = build_paths()
151
    
152
    # Données d'entrée
153
    ttf_i = [0, 250, 400, 550, 700, 850, 1000, 1150, 1300, 1450]
154
    
155
    # Préparer les données dans un DataFrame
156
    df = prepare_data(n=9, ttf_values=ttf_i)
157
    
158
    # Afficher le DataFrame pour vérification
159
    print("Données préparées :")
160
    print(df)
161
    print()
162
    
163
    # Créer le fichier Excel
164
    delete_if_exists(xlsx_path)
165
    
166
    # Étape 1 : Écrire le DataFrame dans la feuille "Données"
167
    write_dataframe_to_excel(xlsx_path, df)
168
    
169
    # Étape 2 : Ajouter le graphe en lisant les données de la feuille "Données"
170
    add_chart_from_data_sheet(xlsx_path)
171
    
172
    print(f"Fichier créé : {xlsx_path}")
173
    open_in_excel(xlsx_path)
174
175
176
if __name__ == "__main__":
177
    main()
178

Documentation

1
# 001_04 — Création d'un graphe avec gestion DataFrame
2
3
## Objectifs
4
5
- Utiliser pandas DataFrame pour préparer et gérer les données.
6
- Écrire le DataFrame dans une feuille "Données" Excel.
7
- Générer un graphe nuage de points avec lignes reliant N(i) en fonction de ttf(i).
8
- Séparer clairement la préparation des données, leur écriture et la création du graphe.
9
10
## Fonctionnement
11
12
1. **Préparation** : `prepare_data()` crée un DataFrame avec colonnes i, ttf(i), dN(i), N(i).
13
2. **Écriture** : `write_dataframe_to_excel()` écrit le DataFrame dans la feuille "Données" (écrase si existe).
14
3. **Graphe** : `add_chart_from_data_sheet()` lit les données de la feuille "Données" puis recrée le fichier avec xlsxwriter pour ajouter le graphe.
15
16
## Points techniques
17
18
- **pandas DataFrame** : Gestion structurée des données avec calcul de dN(i) et N(i).
19
- **openpyxl** : Utilisé uniquement pour écrire/lire les données dans la feuille "Données".
20
- **xlsxwriter** : Utilisé pour créer le graphe (seule bibliothèque fiable pour les graphes scatter).
21
- **Stratégie hybride** : Lecture avec openpyxl, réécriture complète avec xlsxwriter pour le graphe.
22
- **Séparation** : Trois fonctions distinctes (prepare_data, write_dataframe, add_chart).
23
24
## Structure des données
25
26
- Colonnes : i, ttf(i), dN(i), N(i)
27
- dN(i) : 0 pour i=0, puis 1 pour i≥1
28
- N(i) : Décrémentation depuis n=9 jusqu'à 0
29
30
## Utilisation
31
32
```bash
33
python 001/001_04.py
34
```
35
36
Fichier produit : `001_do/001_04.xlsx` avec feuilles "Données" et "Graphe".
37
38
## Enseignements
39
40
- xlsxwriter crée des graphes fiables avec une syntaxe simple : `add_series({'categories': ..., 'values': ...})`.
41
- openpyxl a des limitations pour les graphes ScatterChart (séries multiples, graphes vides).
42
- Pour modifier un fichier existant : lire avec openpyxl, réécrire avec xlsxwriter.
43