Renommer données_en_table -> donnees_en_table
Suppression des accents pour éviter les problèmes d'encodage Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
327
donnees_en_table/Exercices/CORRECTION.md
Normal file
327
donnees_en_table/Exercices/CORRECTION.md
Normal file
@@ -0,0 +1,327 @@
|
||||
## Correction - Données en table
|
||||
|
||||
---
|
||||
|
||||
### 1. Manipulation de fichiers CSV
|
||||
|
||||
- On peut représenter un enregistrement par un dictionnaire.
|
||||
- Une virgule (CSV : Comma Separated Values - Valeurs séparées par une virgule). Néanmoins, le format CSV autorise d'autres séparateurs.
|
||||
- La table étant une liste de dictionnaires, on obtient donc le premier élément de la liste, c'est à dire un dictionnaire, donc une ligne de la table.
|
||||
|
||||
---
|
||||
|
||||
### 2. Opérations sur les tables
|
||||
|
||||
- Pour sélectionner des colonnes selon un critère donné, on va utiliser la fonction projection.
|
||||
|
||||
```python
|
||||
def projection(table, liste_attributs):
|
||||
return [{clé:ligne[clé] for clé in ligne if clé in liste_attributs} for ligne in table]
|
||||
```
|
||||
|
||||
- La fonction *select* ici va sélectionner les lignes dont une des valeurs vaut 19. On obtient donc :
|
||||
|
||||
```python
|
||||
[{'Prénom': 'Chandler', 'Math': '19', 'Anglais': '15', 'NSI': '17'},
|
||||
{'Prénom': 'Ross', 'Math': '14', 'Anglais': '19', 'NSI': '13'}]
|
||||
```
|
||||
|
||||
- Il y a deux (2) noms qui sont communs aux tables : on aura donc deux (2) lignes. De plus, la table U rajoute ses deux (2) colonnes (Âge, Mail) aux quatre de la table T : on aura donc 6 (six) colonnes.
|
||||
|
||||
---
|
||||
|
||||
### 3. Déterminer des fonctions basiques
|
||||
|
||||
- Puisqu'il s'agit de compter le nombre de lignes, donc d'enregistrements, on peut donc utiliser la fonction *len* pour obtenir la longueur de la liste de dictionnaires.
|
||||
|
||||
```python
|
||||
def cardinalite(table):
|
||||
return len(table)
|
||||
```
|
||||
|
||||
- La liste des attributs d'une table correspond aux clés du premier dictionnaire (en supposant que la table est cohérente) :
|
||||
|
||||
```python
|
||||
def attributs(table):
|
||||
if len(table) == 0:
|
||||
return []
|
||||
return list(table[0].keys())
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. Reconnaître une fonction
|
||||
|
||||
```python
|
||||
def mystère(t, cs):
|
||||
t_p = []
|
||||
for l in t :
|
||||
nvlle_l = {}
|
||||
for c in l:
|
||||
if c in cs:
|
||||
nvelle_l[c] = l[c]
|
||||
t_p.append(nvlle_l)
|
||||
return t_p
|
||||
```
|
||||
|
||||
Cette fonction réalise une **projection** : elle crée une nouvelle table ne contenant que les colonnes (attributs) spécifiés dans la liste `cs`.
|
||||
|
||||
- `t` est la table d'origine (liste de dictionnaires)
|
||||
- `cs` est la liste des colonnes à conserver
|
||||
- Pour chaque ligne `l` de la table, on crée un nouveau dictionnaire `nvlle_l` ne contenant que les clés présentes dans `cs`
|
||||
- On retourne la nouvelle table `t_p`
|
||||
|
||||
**Remarque** : Il y a une erreur dans le code original (`nvelle_l` au lieu de `nvlle_l`). La version corrigée serait :
|
||||
|
||||
```python
|
||||
def projection(table, colonnes):
|
||||
table_projetee = []
|
||||
for ligne in table:
|
||||
nouvelle_ligne = {}
|
||||
for colonne in ligne:
|
||||
if colonne in colonnes:
|
||||
nouvelle_ligne[colonne] = ligne[colonne]
|
||||
table_projetee.append(nouvelle_ligne)
|
||||
return table_projetee
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 5. Tester la cohérence d'une table
|
||||
|
||||
- Fonction `coherence` qui teste si chaque ligne a le même ensemble d'attributs :
|
||||
|
||||
```python
|
||||
def coherence(table):
|
||||
"""
|
||||
Teste si chaque ligne de la table a le même ensemble d'attributs
|
||||
:param table: (list) une liste de dictionnaires
|
||||
:return: (bool) True si la table est cohérente, False sinon
|
||||
"""
|
||||
if len(table) == 0:
|
||||
return True
|
||||
|
||||
attributs_reference = set(table[0].keys())
|
||||
|
||||
for ligne in table:
|
||||
if set(ligne.keys()) != attributs_reference:
|
||||
return False
|
||||
|
||||
return True
|
||||
```
|
||||
|
||||
- Fonction `doublons` qui vérifie si un attribut apparaît deux fois avec la même valeur :
|
||||
|
||||
```python
|
||||
def doublons(table, attribut):
|
||||
"""
|
||||
Vérifie si un attribut apparaît deux fois avec la même valeur
|
||||
:param table: (list) une liste de dictionnaires
|
||||
:param attribut: (str) le nom de l'attribut à vérifier
|
||||
:return: (bool) True s'il y a des doublons, False sinon
|
||||
"""
|
||||
valeurs_vues = []
|
||||
|
||||
for ligne in table:
|
||||
valeur = ligne[attribut]
|
||||
if valeur in valeurs_vues:
|
||||
return True
|
||||
valeurs_vues.append(valeur)
|
||||
|
||||
return False
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 6. Lier tableur, fichier CSV et liste de dictionnaires
|
||||
|
||||
```python
|
||||
PlanningTwitch = [
|
||||
{'NomStream': 'AntoineDaniel', 'Genre': 'M', 'Jeu': 'Fall_Guys', 'Numéro': '1'},
|
||||
{'NomStream': 'MV', 'Genre': 'M', 'Jeu': 'Isaac', 'Numéro': '2'},
|
||||
{'NomStream': 'AngleDroit', 'Genre': 'F', 'Jeu': 'Fall_Guys', 'Numéro': '3'},
|
||||
{'NomStream': 'BagheraJones', 'Genre': 'F', 'Jeu': 'Fall_Guys', 'Numéro': '4'}
|
||||
]
|
||||
```
|
||||
|
||||
- La première ligne de la feuille de calcul contient les en-têtes (attributs) :
|
||||
`NomStream | Genre | Jeu | Numéro`
|
||||
|
||||
- Pour obtenir le fichier CSV correspondant :
|
||||
```python
|
||||
vers_csv('PlanningTwitch', ['NomStream', 'Genre', 'Jeu', 'Numéro'])
|
||||
```
|
||||
|
||||
- La deuxième ligne du fichier CSV :
|
||||
`AntoineDaniel;M;Fall_Guys;1`
|
||||
|
||||
- La cellule C8 de la feuille correspondante : la table n'a que 5 lignes (1 en-tête + 4 données), donc C8 est **vide**.
|
||||
|
||||
- Pour obtenir la valeur d'une cellule (par exemple C2, le jeu d'AntoineDaniel) :
|
||||
```python
|
||||
PlanningTwitch[0]['Jeu'] # 'Fall_Guys'
|
||||
```
|
||||
|
||||
- Pour modifier le jeu de MV :
|
||||
```python
|
||||
PlanningTwitch[1]['Jeu'] = 'Worms'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 7. Ajouter une ligne ou une colonne
|
||||
|
||||
- Pour obtenir la liste de dictionnaires depuis le fichier CSV :
|
||||
```python
|
||||
Groupe1 = import_csv('Groupe1')
|
||||
```
|
||||
|
||||
- Pour ajouter Rachel :
|
||||
```python
|
||||
Groupe1.append({'Prénom': 'Rachel', 'Math': '17', 'Anglais': '19', 'NSI': '18'})
|
||||
```
|
||||
|
||||
- Fonction pour ajouter une colonne moyenne :
|
||||
|
||||
```python
|
||||
from copy import deepcopy
|
||||
|
||||
def ajouter_moyenne(table):
|
||||
"""
|
||||
Ajoute une colonne 'Moyenne' à chaque ligne de la table
|
||||
:param table: (list) une liste de dictionnaires avec des notes
|
||||
:return: (list) une nouvelle table avec la colonne Moyenne
|
||||
"""
|
||||
nouvelle_table = deepcopy(table)
|
||||
|
||||
for ligne in nouvelle_table:
|
||||
math = int(ligne['Math'])
|
||||
anglais = int(ligne['Anglais'])
|
||||
nsi = int(ligne['NSI'])
|
||||
moyenne = (math + anglais + nsi) / 3
|
||||
ligne['Moyenne'] = '{:.1f}'.format(moyenne)
|
||||
|
||||
return nouvelle_table
|
||||
```
|
||||
|
||||
- Pour ajouter une ligne contenant les moyennes par matière :
|
||||
|
||||
```python
|
||||
from copy import deepcopy
|
||||
|
||||
def ajouter_ligne_moyennes(table):
|
||||
"""
|
||||
Ajoute une ligne contenant les moyennes par matière
|
||||
:param table: (list) une liste de dictionnaires avec des notes
|
||||
:return: (list) une nouvelle table avec la ligne des moyennes
|
||||
"""
|
||||
nouvelle_table = deepcopy(table)
|
||||
|
||||
nb_eleves = len(nouvelle_table)
|
||||
total_math = 0
|
||||
total_anglais = 0
|
||||
total_nsi = 0
|
||||
|
||||
for ligne in nouvelle_table:
|
||||
total_math = total_math + int(ligne['Math'])
|
||||
total_anglais = total_anglais + int(ligne['Anglais'])
|
||||
total_nsi = total_nsi + int(ligne['NSI'])
|
||||
|
||||
ligne_moyennes = {
|
||||
'Prénom': 'Moyenne',
|
||||
'Math': '{:.1f}'.format(total_math / nb_eleves),
|
||||
'Anglais': '{:.1f}'.format(total_anglais / nb_eleves),
|
||||
'NSI': '{:.1f}'.format(total_nsi / nb_eleves)
|
||||
}
|
||||
|
||||
nouvelle_table.append(ligne_moyennes)
|
||||
return nouvelle_table
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 8. Sélectionner, trier, joindre
|
||||
|
||||
On définit les tables :
|
||||
|
||||
```python
|
||||
Hero = [
|
||||
{'NumHero': '0', 'NomHero': 'Sangoku', 'VilleHero': 'Kyoto'},
|
||||
{'NumHero': '1', 'NomHero': 'Naruto', 'VilleHero': 'Konoha'},
|
||||
{'NumHero': '2', 'NomHero': 'Luffy', 'VilleHero': 'Fuchsia'},
|
||||
{'NumHero': '3', 'NomHero': 'Ryo Saeba', 'VilleHero': 'Tokyo'},
|
||||
{'NumHero': '4', 'NomHero': 'Saitama', 'VilleHero': 'Ville Z'},
|
||||
{'NumHero': '5', 'NomHero': 'Onizuka', 'VilleHero': 'Tokyo'}
|
||||
]
|
||||
|
||||
Armes = [
|
||||
{'NumHero': '0', 'NomHero': 'Sangoku', 'Arme': 'Ki'},
|
||||
{'NumHero': '1', 'NomHero': 'Naruto', 'Arme': 'Chakra'},
|
||||
{'NumHero': '2', 'NomHero': 'Luffy', 'Arme': 'Corps'},
|
||||
{'NumHero': '3', 'NomHero': 'Ryo Saeba', 'Arme': 'Magnum'},
|
||||
{'NumHero': '4', 'NomHero': 'Saitama', 'Arme': 'Poing'},
|
||||
{'NumHero': '5', 'NomHero': 'Onizuka', 'Arme': 'Tout est une arme'}
|
||||
]
|
||||
```
|
||||
|
||||
- **HeroTokyo** : héros dont la ville est Tokyo
|
||||
|
||||
```python
|
||||
HeroTokyo = select(Hero, "ligne['VilleHero'] == 'Tokyo'")
|
||||
# Résultat :
|
||||
# [{'NumHero': '3', 'NomHero': 'Ryo Saeba', 'VilleHero': 'Tokyo'},
|
||||
# {'NumHero': '5', 'NomHero': 'Onizuka', 'VilleHero': 'Tokyo'}]
|
||||
```
|
||||
|
||||
- **HeroAlpha** : héros triés par ordre alphabétique du nom
|
||||
|
||||
```python
|
||||
HeroAlpha = tri(Hero, 'NomHero')
|
||||
# Résultat :
|
||||
# [{'NumHero': '2', 'NomHero': 'Luffy', 'VilleHero': 'Fuchsia'},
|
||||
# {'NumHero': '1', 'NomHero': 'Naruto', 'VilleHero': 'Konoha'},
|
||||
# {'NumHero': '5', 'NomHero': 'Onizuka', 'VilleHero': 'Tokyo'},
|
||||
# {'NumHero': '3', 'NomHero': 'Ryo Saeba', 'VilleHero': 'Tokyo'},
|
||||
# {'NumHero': '4', 'NomHero': 'Saitama', 'VilleHero': 'Ville Z'},
|
||||
# {'NumHero': '0', 'NomHero': 'Sangoku', 'VilleHero': 'Kyoto'}]
|
||||
```
|
||||
|
||||
- **HeroComplet** : nom, ville et arme des héros (fusion puis projection)
|
||||
|
||||
```python
|
||||
HeroFusion = fusion(Hero, Armes, 'NumHero')
|
||||
HeroComplet = projection(HeroFusion, ['NomHero', 'VilleHero', 'Arme'])
|
||||
# Résultat :
|
||||
# [{'NomHero': 'Sangoku', 'VilleHero': 'Kyoto', 'Arme': 'Ki'},
|
||||
# {'NomHero': 'Naruto', 'VilleHero': 'Konoha', 'Arme': 'Chakra'},
|
||||
# {'NomHero': 'Luffy', 'VilleHero': 'Fuchsia', 'Arme': 'Corps'},
|
||||
# {'NomHero': 'Ryo Saeba', 'VilleHero': 'Tokyo', 'Arme': 'Magnum'},
|
||||
# {'NomHero': 'Saitama', 'VilleHero': 'Ville Z', 'Arme': 'Poing'},
|
||||
# {'NomHero': 'Onizuka', 'VilleHero': 'Tokyo', 'Arme': 'Tout est une arme'}]
|
||||
```
|
||||
|
||||
- **HeroVille** : numéro et ville des héros
|
||||
|
||||
```python
|
||||
HeroVille = projection(Hero, ['NumHero', 'VilleHero'])
|
||||
# Résultat :
|
||||
# [{'NumHero': '0', 'VilleHero': 'Kyoto'},
|
||||
# {'NumHero': '1', 'VilleHero': 'Konoha'},
|
||||
# {'NumHero': '2', 'VilleHero': 'Fuchsia'},
|
||||
# {'NumHero': '3', 'VilleHero': 'Tokyo'},
|
||||
# {'NumHero': '4', 'VilleHero': 'Ville Z'},
|
||||
# {'NumHero': '5', 'VilleHero': 'Tokyo'}]
|
||||
```
|
||||
|
||||
- **HeroImpair** : nom et ville des héros ne venant pas de Tokyo et dont le numéro est impair
|
||||
|
||||
```python
|
||||
HeroImpair = select(Hero, "ligne['VilleHero'] != 'Tokyo' and int(ligne['NumHero']) % 2 == 1")
|
||||
HeroImpair = projection(HeroImpair, ['NomHero', 'VilleHero'])
|
||||
# Résultat :
|
||||
# [{'NomHero': 'Naruto', 'VilleHero': 'Konoha'}]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Source : Florian Mathieu - Licence CC BY NC SA
|
||||
Reference in New Issue
Block a user