xxxxxxxxxx
# Tables - fusion achats
L'exécution de la cellule de code ci-dessous permet d'ouvrir un fichier CSV et d'en transférer le contenu dans deux tables :
- `table_clients` contient des enregistrements qui indiquent les coordonnées de clients - **identifiés par leur mail** - d'un site de commerce en ligne,
- `table_montants` contient des enregistrements qui indiquent les caractéristiques de certaines commandes effectuées sur ce site de commerce en ligne.
On sait par ailleurs que **tous les mails figurant dans `table_montants` figurent aussi dans `table_clients`**.
L'exécution de la cellule de code ci-dessous permet d'ouvrir un fichier CSV et d'en transférer le contenu dans deux tables :
table_clients
contient des enregistrements qui indiquent les coordonnées de clients - identifiés par leur mail - d'un site de commerce en ligne,table_montants
contient des enregistrements qui indiquent les caractéristiques de certaines commandes effectuées sur ce site de commerce en ligne.On sait par ailleurs que tous les mails figurant dans table_montants
figurent aussi dans table_clients
.
xxxxxxxxxx
import csv
import pandas
def charger_fichier( nom_fic ):
"""
Permet de lire un fichier CSV en utilisant la ligne d'entêtes
Retourne une liste de dictionnaires.
"""
table = []
fichier_csv = open( nom_fic , "r", newline ="", encoding ="iso-8859-1" )
lecteur_fichier = csv.DictReader( fichier_csv , delimiter ="\t")
for enreg in lecteur_fichier :
table.append (dict ( enreg )) # enreg est de type OrderedDict on le remet endict
fichier_csv.close()
return table
def afficher(table):
f = pandas.DataFrame(table)
return f
table_clients = charger_fichier('./clients.csv')
table_montants = charger_fichier('./montants.csv')
xxxxxxxxxx
*Question 1 :*
En étudiant le code ci-dessus, répondre aux questions suivantes :
- Quelle fonction du langage python permet d'ouvrir un fichier ?
- Lors de l'appel de fonction, quel argument indique à python que le fichier est à ouvrir en lecture et pas en écriture ?
- Quel est l'encodage des fichiers CSV utilisés : `utf-8` ou `ascii` ou `iso-8859-1`?
- Quel est le séparateur des fichiers CSV utilisés : `;` ou `,` ou `:` ou `'\t'` (tabulation) ?
- Pourquoi est-il important de fermer le fichier une fois qu'on a fini de l'utiliser ?
Question 1 :
En étudiant le code ci-dessus, répondre aux questions suivantes :
Quelle fonction du langage python permet d'ouvrir un fichier ?
Lors de l'appel de fonction, quel argument indique à python que le fichier est à ouvrir en lecture et pas en écriture ?
Quel est l'encodage des fichiers CSV utilisés : utf-8
ou ascii
ou iso-8859-1
?
Quel est le séparateur des fichiers CSV utilisés : ;
ou ,
ou :
ou '\t'
(tabulation) ?
Pourquoi est-il important de fermer le fichier une fois qu'on a fini de l'utiliser ?
xxxxxxxxxx
La fonction du langage python qui permet d'ouvrir un fichier est : ...
L'argument qui indique à python que le fichier est à ouvrir en lecture est : ...
L'encodage des fichiers CSV utilisés est : ...
Le séparateur des fichiers CSV utilisés est : ...
Il est important de fermer le fichier une fois qu'on a fini de l'utiliser ...
xxxxxxxxxx
<details>
<summary style="border:1pt solid slateblue; border-radius:5pt; width:15%; color:slateblue; padding:3px; background-color: lightcyan"> Solution </summary>
<div style="border:1pt solid slateblue; border-radius:5pt; color:slateblue; padding:3px; background-color: lightcyan">
- La fonction du langage python qui permet d'ouvrir un fichier est : `open`
- L'argument qui indique à python que le fichier est à ouvrir en lecture est : `'r'`
- L'encodage des fichiers CSV utilisés est : `'iso-8859-1'`
- Le séparateur des fichiers CSV utilisés est : `'\t'` (tabulation).
- Il est important de fermer le fichier une fois qu'on a fini de l'utiliser pour libérer le fichier, c'est à dire pour que les autres applications puissent l'utiliser à leur tour si besoin.
</div>
</details>
La fonction du langage python qui permet d'ouvrir un fichier est : open
L'argument qui indique à python que le fichier est à ouvrir en lecture est : 'r'
L'encodage des fichiers CSV utilisés est : 'iso-8859-1'
Le séparateur des fichiers CSV utilisés est : '\t'
(tabulation).
Il est important de fermer le fichier une fois qu'on a fini de l'utiliser pour libérer le fichier, c'est à dire pour que les autres applications puissent l'utiliser à leur tour si besoin.
xxxxxxxxxx
*Question 2 :*
En exécutant deux instructions bien choisies, déterminer combien d'*enregistrements* (c-à-d de lignes) contiennent ces tables.
Question 2 :
En exécutant deux instructions bien choisies, déterminer combien d'enregistrements (c-à-d de lignes) contiennent ces tables.
xxxxxxxxxx
...
xxxxxxxxxx
<details>
<summary style="border:1pt solid slateblue; border-radius:5pt; width:15%; color:slateblue; padding:3px; background-color: lightcyan"> Solution </summary>
<div style="border:1pt solid slateblue; border-radius:5pt; color:slateblue; padding:3px; background-color: lightcyan">
```python
len(table_clients)
```
</div>
</details>
len(table_clients)
xxxxxxxxxx
...
xxxxxxxxxx
<details>
<summary style="border:1pt solid slateblue; border-radius:5pt; width:15%; color:slateblue; padding:3px; background-color: lightcyan"> Solution </summary>
<div style="border:1pt solid slateblue; border-radius:5pt; color:slateblue; padding:3px; background-color: lightcyan">
```python
len(table_montants)
```
</div>
</details>
len(table_montants)
xxxxxxxxxx
<hr style="height:1px;"/>
*Remarque : Pour faciliter l'affichage **des tables**, vous pouvez utiliser la fonction `afficher` :*
Remarque : Pour faciliter l'affichage des tables, vous pouvez utiliser la fonction afficher
:
xxxxxxxxxx
afficher(table_clients)
xxxxxxxxxx
afficher(table_montants)
xxxxxxxxxx
<hr style="height:1px;"/>
xxxxxxxxxx
*Question 3 :*
Compléter la séquence d'instructions ci-dessous afin de fusionner les deux tables en une troisième table.
Question 3 :
Compléter la séquence d'instructions ci-dessous afin de fusionner les deux tables en une troisième table.
xxxxxxxxxx
import copy
table_fusion = []
for montant in table_montants:
for client in table_clients:
if ... :
...
...
...
...
...
...
afficher(table_fusion)
xxxxxxxxxx
<details>
<summary style="border:1pt solid slateblue; border-radius:5pt; width:15%; color:slateblue; padding:3px; background-color: lightcyan"> Solution </summary>
<div style="border:1pt solid slateblue; border-radius:5pt; color:slateblue; padding:3px; background-color: lightcyan">
Première version (on fait une boucle pour ajouter les informations du client):
```python
import copy #<---- spécifique versions 1 et 2
table_fusion = []
for montant in table_montants:
for client in table_clients:
if client['mail'] == montant['mail']:
enregistrement = copy.deepcopy(montant) #<---- spécifique versions 1 et 2
for key, val in client.items(): #<---- spécifique version 1
enregistrement[key] = val #<---- spécifique version 1
table_fusion.append(enregistrement)
break
afficher(table_fusion)
```
Seconde version (on ajoute « à la main » les informations du client):
```python
import copy #<---- spécifique versions 1 et 2
table_fusion = []
for montant in table_montants:
for client in table_clients:
if client['mail'] == montant['mail']:
enregistrement = copy.deepcopy(montant) #<---- spécifique versions 1 et 2
enregistrement['prenom_nom'] = client['prenom_nom'] #<---- spécifique versions 2 et 3
enregistrement['adresse'] = client['adresse'] #<---- spécifique versions 2 et 3
enregistrement['code_postal'] = client['code_postal'] #<---- spécifique versions 2 et 3
enregistrement['ville'] = client['ville'] #<---- spécifique versions 2 et 3
enregistrement['etat'] = client['etat'] #<---- spécifique versions 2 et 3
table_fusion.append(enregistrement)
break
afficher(table_fusion)
```
Troisième version (on ajoute « à la main » les informations du montant et celles du client):
```python
table_fusion = []
for montant in table_montants:
for client in table_clients:
if client['mail'] == montant['mail']:
enregistrement = dict() #<---- spécifique version 3
enregistrement['mail'] = montant['mail'] #<---- spécifique version 3
enregistrement['carte'] = montant['carte'] #<---- spécifique version 3
enregistrement['montant'] = montant['montant'] #<---- spécifique version 3
enregistrement['date'] = montant['date'] #<---- spécifique version 3
enregistrement['heure'] = montant['heure'] #<---- spécifique version 3
enregistrement['prenom_nom'] = client['prenom_nom'] #<---- spécifique versions 2 et 3
enregistrement['adresse'] = client['adresse'] #<---- spécifique versions 2 et 3
enregistrement['code_postal'] = client['code_postal'] #<---- spécifique versions 2 et 3
enregistrement['ville'] = client['ville'] #<---- spécifique versions 2 et 3
enregistrement['etat'] = client['etat'] #<---- spécifique versions 2 et 3
table_fusion.append(enregistrement)
break
afficher(table_fusion)
```
</div>
</details>
Première version (on fait une boucle pour ajouter les informations du client):
import copy #<---- spécifique versions 1 et 2
table_fusion = []
for montant in table_montants:
for client in table_clients:
if client['mail'] == montant['mail']:
enregistrement = copy.deepcopy(montant) #<---- spécifique versions 1 et 2
for key, val in client.items(): #<---- spécifique version 1
enregistrement[key] = val #<---- spécifique version 1
table_fusion.append(enregistrement)
break
afficher(table_fusion)
Seconde version (on ajoute « à la main » les informations du client):
import copy #<---- spécifique versions 1 et 2
table_fusion = []
for montant in table_montants:
for client in table_clients:
if client['mail'] == montant['mail']:
enregistrement = copy.deepcopy(montant) #<---- spécifique versions 1 et 2
enregistrement['prenom_nom'] = client['prenom_nom'] #<---- spécifique versions 2 et 3
enregistrement['adresse'] = client['adresse'] #<---- spécifique versions 2 et 3
enregistrement['code_postal'] = client['code_postal'] #<---- spécifique versions 2 et 3
enregistrement['ville'] = client['ville'] #<---- spécifique versions 2 et 3
enregistrement['etat'] = client['etat'] #<---- spécifique versions 2 et 3
table_fusion.append(enregistrement)
break
afficher(table_fusion)
Troisième version (on ajoute « à la main » les informations du montant et celles du client):
table_fusion = []
for montant in table_montants:
for client in table_clients:
if client['mail'] == montant['mail']:
enregistrement = dict() #<---- spécifique version 3
enregistrement['mail'] = montant['mail'] #<---- spécifique version 3
enregistrement['carte'] = montant['carte'] #<---- spécifique version 3
enregistrement['montant'] = montant['montant'] #<---- spécifique version 3
enregistrement['date'] = montant['date'] #<---- spécifique version 3
enregistrement['heure'] = montant['heure'] #<---- spécifique version 3
enregistrement['prenom_nom'] = client['prenom_nom'] #<---- spécifique versions 2 et 3
enregistrement['adresse'] = client['adresse'] #<---- spécifique versions 2 et 3
enregistrement['code_postal'] = client['code_postal'] #<---- spécifique versions 2 et 3
enregistrement['ville'] = client['ville'] #<---- spécifique versions 2 et 3
enregistrement['etat'] = client['etat'] #<---- spécifique versions 2 et 3
table_fusion.append(enregistrement)
break
afficher(table_fusion)
xxxxxxxxxx
*Question 4 :*
Dans les solutions proposées à la question 3 ci-dessus, on souhaite inverser les deux boucles et faire :
```python
for client in table_clients:
for montant in table_montants:
```
au lieu de :
```python
for montant in table_montants:
for client in table_clients:
```
Si on effectue cette inversion, quelle ligne de code faut-il supprimer pour que la fusion soit correcte ?
Question 4 :
Dans les solutions proposées à la question 3 ci-dessus, on souhaite inverser les deux boucles et faire :
for client in table_clients:
for montant in table_montants:
au lieu de :
for montant in table_montants:
for client in table_clients:
Si on effectue cette inversion, quelle ligne de code faut-il supprimer pour que la fusion soit correcte ?
xxxxxxxxxx
<details>
<summary style="border:1pt solid slateblue; border-radius:5pt; width:15%; color:slateblue; padding:3px; background-color: lightcyan"> Solution </summary>
<div style="border:1pt solid slateblue; border-radius:5pt; color:slateblue; padding:3px; background-color: lightcyan">
Il faut alors supprimer l'instruction `break` car un client peut avoir plusieurs montants qui lui correspondent (alors qu'un montant ne correspond qu'à un seul client).
Pour chaque client on est donc obligé d'analyser **tous** les montants : on ne peut pas s'arrêter dès qu'on a trouvé un montant qui correspond à ce client.
</div>
</details>
Il faut alors supprimer l'instruction break
car un client peut avoir plusieurs montants qui lui correspondent (alors qu'un montant ne correspond qu'à un seul client).
Pour chaque client on est donc obligé d'analyser tous les montants : on ne peut pas s'arrêter dès qu'on a trouvé un montant qui correspond à ce client.