13.4. Trier une table CSV#

On va reprendre le fichier précédent.

import csv
with open('fr-en-annuaire-education.csv', 'r') as descripteur:
    contenu = list(csv.DictReader(descripteur, delimiter=";"))
contenu[0]
{'\ufeffIdentifiant_de_l_etablissement': '0595012C',
 'Nom_etablissement': "Institut d'enseignement technologique privé",
 'Type_etablissement': 'Lycée',
 'Statut_public_prive': 'Privé',
 'Adresse_1': 'Route de Warhem',
 'Adresse_2': 'BP 26',
 'Adresse_3': '',
 'Code_postal': '59492',
 'Code_commune': '59319',
 'Nom_commune': 'Hoymille',
 'Code_departement': '059',
 'Code_academie': '09',
 'Code_region': '32',
 'Ecole_maternelle': '',
 'Ecole_elementaire': '',
 'Voie_generale': '1',
 'Voie_technologique': '1',
 'Voie_professionnelle': '1',
 'Telephone': '03 28 68 67 75',
 'Fax': '03 28 68 65 01',
 'Web': 'https://iet-hoymille.fr/',
 'Mail': 'hoymille@cneap.fr',
 'Restauration': '1',
 'Hebergement': '1',
 'ULIS': '0',
 'Apprentissage': '1',
 'Segpa': '0',
 'Section_arts': '0',
 'Section_cinema': '0',
 'Section_theatre': '0',
 'Section_sport': '0',
 'Section_internationale': '0',
 'Section_europeenne': '0',
 'Lycee_Agricole': '1',
 'Lycee_militaire': '0',
 'Lycee_des_metiers': '0',
 'Post_BAC': '1',
 'Appartenance_Education_Prioritaire': '',
 'GRETA': '0',
 'SIREN_SIRET': '78352239400031',
 'Nombre_d_eleves': '',
 'Fiche_onisep': 'https://www.onisep.fr/http/redirection/etablissement/slug/ENS.5341',
 'position': '50.972959209250554, 2.4614002872998175',
 'Type_contrat_prive': 'SOUS CONTRAT ETABLISSEMENT AGRICOLE',
 'Libelle_departement': 'Nord',
 'Libelle_academie': 'Lille',
 'Libelle_region': 'Hauts-de-France',
 'coordX_origine': '662088.3',
 'coordY_origine': '7097579.1',
 'epsg_origine': 'EPSG:2154',
 'nom_circonscription': '',
 'latitude': '50.972959209250554',
 'longitude': '2.4614002872998175',
 'precision_localisation': 'Numéro de rue',
 'date_ouverture': '1976-12-10',
 'date_maj_ligne': '2025-03-03',
 'etat': 'OUVERT',
 'ministere_tutelle': 'AGRICULTURE',
 'multi_uai': '0',
 'rpi_concentre': '0',
 'rpi_disperse': '',
 'code_nature': '320',
 'libelle_nature': 'LYCEE PROFESSIONNEL',
 'Code_type_contrat_prive': '60',
 'PIAL': '',
 'etablissement_mere': '',
 'type_rattachement_etablissement_mere': '',
 'code_circonscription': '',
 'code_zone_animation_pedagogique': '',
 'libelle_zone_animation_pedagogique': '',
 'code_bassin_formation': '09105',
 'libelle_bassin_formation': 'DUNKERQUE FLANDRE'}
sorted(contenu, key=lambda x: x['Code_commune'])[0]
{'\ufeffIdentifiant_de_l_etablissement': '0010069V',
 'Nom_etablissement': 'Lycée Lamartine',
 'Type_etablissement': 'Lycée',
 'Statut_public_prive': 'Privé',
 'Adresse_1': '41 rue Georges Girerd',
 'Adresse_2': 'BP 79',
 'Adresse_3': '',
 'Code_postal': '01302',
 'Code_commune': '01034',
 'Nom_commune': 'Belley',
 'Code_departement': '001',
 'Code_academie': '10',
 'Code_region': '84',
 'Ecole_maternelle': '',
 'Ecole_elementaire': '',
 'Voie_generale': '1',
 'Voie_technologique': '1',
 'Voie_professionnelle': '0',
 'Telephone': '04 79 81 01 44',
 'Fax': '04 79 81 06 51',
 'Web': 'https://institution-lamartine.fr/lycee-general-et-technologique/',
 'Mail': 'info@institution-lamartine.fr',
 'Restauration': '1',
 'Hebergement': '1',
 'ULIS': '0',
 'Apprentissage': '0',
 'Segpa': '0',
 'Section_arts': '1',
 'Section_cinema': '0',
 'Section_theatre': '0',
 'Section_sport': '0',
 'Section_internationale': '0',
 'Section_europeenne': '0',
 'Lycee_Agricole': '0',
 'Lycee_militaire': '0',
 'Lycee_des_metiers': '0',
 'Post_BAC': '0',
 'Appartenance_Education_Prioritaire': '',
 'GRETA': '0',
 'SIREN_SIRET': '77930082100013',
 'Nombre_d_eleves': '245',
 'Fiche_onisep': 'https://www.onisep.fr/http/redirection/etablissement/slug/ENS.13000',
 'position': '45.76116634137921, 5.684877551823519',
 'Type_contrat_prive': "CONTRAT D'ASSOCIATION TOUTES CLASSES",
 'Libelle_departement': 'Ain',
 'Libelle_academie': 'Lyon',
 'Libelle_region': 'Auvergne-Rhône-Alpes',
 'coordX_origine': '908652.2',
 'coordY_origine': '6521498.9',
 'epsg_origine': 'EPSG:2154',
 'nom_circonscription': '',
 'latitude': '45.76116634137921',
 'longitude': '5.684877551823519',
 'precision_localisation': 'Numéro de rue',
 'date_ouverture': '1967-01-23',
 'date_maj_ligne': '2025-03-03',
 'etat': 'OUVERT',
 'ministere_tutelle': "MINISTERE DE L'EDUCATION NATIONALE",
 'multi_uai': '0',
 'rpi_concentre': '0',
 'rpi_disperse': '',
 'code_nature': '300',
 'libelle_nature': 'LYCEE ENSEIGNT GENERAL ET TECHNOLOGIQUE',
 'Code_type_contrat_prive': '30',
 'PIAL': '0011067E',
 'etablissement_mere': '',
 'type_rattachement_etablissement_mere': '',
 'code_circonscription': '',
 'code_zone_animation_pedagogique': '',
 'libelle_zone_animation_pedagogique': '',
 'code_bassin_formation': '10013',
 'libelle_bassin_formation': 'AIN SUD'}

La fonction sorted permet de trier un tableau de valeur. Comme il n’existe pas de façon «naturelle» de comparer des dictionnaires, on utilise ici le Code_commune. C’est le rôle de l’argument optionnel key auquel on passe une fonction.

Ici, comme cette fonction n’est utilisé que dans ce contexte, on utilise une fonction spéciale non nommée : (lambda x: x['Code_commune']).

Écrire une fonction renvoie_champ(contenu: dict) -> str qui renvoie un champ du dictionnaire contenu.

contenu[0]
{'\ufeffIdentifiant_de_l_etablissement': '0595012C',
 'Nom_etablissement': "Institut d'enseignement technologique privé",
 'Type_etablissement': 'Lycée',
 'Statut_public_prive': 'Privé',
 'Adresse_1': 'Route de Warhem',
 'Adresse_2': 'BP 26',
 'Adresse_3': '',
 'Code_postal': '59492',
 'Code_commune': '59319',
 'Nom_commune': 'Hoymille',
 'Code_departement': '059',
 'Code_academie': '09',
 'Code_region': '32',
 'Ecole_maternelle': '',
 'Ecole_elementaire': '',
 'Voie_generale': '1',
 'Voie_technologique': '1',
 'Voie_professionnelle': '1',
 'Telephone': '03 28 68 67 75',
 'Fax': '03 28 68 65 01',
 'Web': 'https://iet-hoymille.fr/',
 'Mail': 'hoymille@cneap.fr',
 'Restauration': '1',
 'Hebergement': '1',
 'ULIS': '0',
 'Apprentissage': '1',
 'Segpa': '0',
 'Section_arts': '0',
 'Section_cinema': '0',
 'Section_theatre': '0',
 'Section_sport': '0',
 'Section_internationale': '0',
 'Section_europeenne': '0',
 'Lycee_Agricole': '1',
 'Lycee_militaire': '0',
 'Lycee_des_metiers': '0',
 'Post_BAC': '1',
 'Appartenance_Education_Prioritaire': '',
 'GRETA': '0',
 'SIREN_SIRET': '78352239400031',
 'Nombre_d_eleves': '',
 'Fiche_onisep': 'https://www.onisep.fr/http/redirection/etablissement/slug/ENS.5341',
 'position': '50.972959209250554, 2.4614002872998175',
 'Type_contrat_prive': 'SOUS CONTRAT ETABLISSEMENT AGRICOLE',
 'Libelle_departement': 'Nord',
 'Libelle_academie': 'Lille',
 'Libelle_region': 'Hauts-de-France',
 'coordX_origine': '662088.3',
 'coordY_origine': '7097579.1',
 'epsg_origine': 'EPSG:2154',
 'nom_circonscription': '',
 'latitude': '50.972959209250554',
 'longitude': '2.4614002872998175',
 'precision_localisation': 'Numéro de rue',
 'date_ouverture': '1976-12-10',
 'date_maj_ligne': '2025-03-03',
 'etat': 'OUVERT',
 'ministere_tutelle': 'AGRICULTURE',
 'multi_uai': '0',
 'rpi_concentre': '0',
 'rpi_disperse': '',
 'code_nature': '320',
 'libelle_nature': 'LYCEE PROFESSIONNEL',
 'Code_type_contrat_prive': '60',
 'PIAL': '',
 'etablissement_mere': '',
 'type_rattachement_etablissement_mere': '',
 'code_circonscription': '',
 'code_zone_animation_pedagogique': '',
 'libelle_zone_animation_pedagogique': '',
 'code_bassin_formation': '09105',
 'libelle_bassin_formation': 'DUNKERQUE FLANDRE'}
def renvoie_champ(contenu):
    return contenu['Code_commune']
renvoie_champ(contenu[0])
'59319'
(lambda etab: etab['Code_commune'])(contenu[0])
'59319'

Utiliser cette fonction dans la fonction sorted pour vérifier votre résultat.

sorted(contenu, key=renvoie_champ)[0]
{'\ufeffIdentifiant_de_l_etablissement': '0010069V',
 'Nom_etablissement': 'Lycée Lamartine',
 'Type_etablissement': 'Lycée',
 'Statut_public_prive': 'Privé',
 'Adresse_1': '41 rue Georges Girerd',
 'Adresse_2': 'BP 79',
 'Adresse_3': '',
 'Code_postal': '01302',
 'Code_commune': '01034',
 'Nom_commune': 'Belley',
 'Code_departement': '001',
 'Code_academie': '10',
 'Code_region': '84',
 'Ecole_maternelle': '',
 'Ecole_elementaire': '',
 'Voie_generale': '1',
 'Voie_technologique': '1',
 'Voie_professionnelle': '0',
 'Telephone': '04 79 81 01 44',
 'Fax': '04 79 81 06 51',
 'Web': 'https://institution-lamartine.fr/lycee-general-et-technologique/',
 'Mail': 'info@institution-lamartine.fr',
 'Restauration': '1',
 'Hebergement': '1',
 'ULIS': '0',
 'Apprentissage': '0',
 'Segpa': '0',
 'Section_arts': '1',
 'Section_cinema': '0',
 'Section_theatre': '0',
 'Section_sport': '0',
 'Section_internationale': '0',
 'Section_europeenne': '0',
 'Lycee_Agricole': '0',
 'Lycee_militaire': '0',
 'Lycee_des_metiers': '0',
 'Post_BAC': '0',
 'Appartenance_Education_Prioritaire': '',
 'GRETA': '0',
 'SIREN_SIRET': '77930082100013',
 'Nombre_d_eleves': '245',
 'Fiche_onisep': 'https://www.onisep.fr/http/redirection/etablissement/slug/ENS.13000',
 'position': '45.76116634137921, 5.684877551823519',
 'Type_contrat_prive': "CONTRAT D'ASSOCIATION TOUTES CLASSES",
 'Libelle_departement': 'Ain',
 'Libelle_academie': 'Lyon',
 'Libelle_region': 'Auvergne-Rhône-Alpes',
 'coordX_origine': '908652.2',
 'coordY_origine': '6521498.9',
 'epsg_origine': 'EPSG:2154',
 'nom_circonscription': '',
 'latitude': '45.76116634137921',
 'longitude': '5.684877551823519',
 'precision_localisation': 'Numéro de rue',
 'date_ouverture': '1967-01-23',
 'date_maj_ligne': '2025-03-03',
 'etat': 'OUVERT',
 'ministere_tutelle': "MINISTERE DE L'EDUCATION NATIONALE",
 'multi_uai': '0',
 'rpi_concentre': '0',
 'rpi_disperse': '',
 'code_nature': '300',
 'libelle_nature': 'LYCEE ENSEIGNT GENERAL ET TECHNOLOGIQUE',
 'Code_type_contrat_prive': '30',
 'PIAL': '0011067E',
 'etablissement_mere': '',
 'type_rattachement_etablissement_mere': '',
 'code_circonscription': '',
 'code_zone_animation_pedagogique': '',
 'libelle_zone_animation_pedagogique': '',
 'code_bassin_formation': '10013',
 'libelle_bassin_formation': 'AIN SUD'}

13.4.1. À vous de jouer#

Charger le fichier csv POPULATION_MUNICIPALE_COMMUNES_FRANCE.csv et trier les communes par population.

Vérifier le résultat en regardant quelle est la commune la plus peuplée.

import csv
with open('POPULATION_MUNICIPALE_COMMUNES_FRANCE.csv', 'r') as descripteur:
    contenu = list(csv.DictReader(descripteur, delimiter=";"))
contenu[0]
{'objectid': '115658',
 'reg': '52',
 'dep': '85',
 'cv': '8502',
 'codgeo': '85062',
 'libgeo': 'Châteauneuf',
 'p13_pop': '968',
 'p14_pop': '993',
 'p15_pop': '1013',
 'p16_pop': '1027',
 'p17_pop': '1056',
 'p18_pop': '1085',
 'p19_pop': '1114',
 'p20_pop': '1118',
 'p21_pop': '1134'}
pop=(lambda x: x['p21_pop'])
pop(contenu[0])
'1134'
def pop(x):
    if x['p21_pop'] == '':
        return 0
    else:
        return int(x['p21_pop'])
sorted(contenu, key=pop, reverse=True)[0:11]
[{'objectid': '114579',
  'reg': '73',
  'dep': '31',
  'cv': '3199',
  'codgeo': '31555',
  'libgeo': 'Toulouse',
  'p13_pop': '458298',
  'p14_pop': '466297',
  'p15_pop': '471941',
  'p16_pop': '475438',
  'p17_pop': '479553',
  'p18_pop': '486828',
  'p19_pop': '493465',
  'p20_pop': '498003',
  'p21_pop': '504078'},
 {'objectid': '139962',
  'reg': '93',
  'dep': '06',
  'cv': '0699',
  'codgeo': '06088',
  'libgeo': 'Nice',
  'p13_pop': '342295',
  'p14_pop': '343895',
  'p15_pop': '342522',
  'p16_pop': '342637',
  'p17_pop': '340017',
  'p18_pop': '341032',
  'p19_pop': '342669',
  'p20_pop': '343477',
  'p21_pop': '348085'},
 {'objectid': '128203',
  'reg': '52',
  'dep': '44',
  'cv': '4496',
  'codgeo': '44109',
  'libgeo': 'Nantes',
  'p13_pop': '292718',
  'p14_pop': '298029',
  'p15_pop': '303382',
  'p16_pop': '306694',
  'p17_pop': '309346',
  'p18_pop': '314138',
  'p19_pop': '318808',
  'p20_pop': '320732',
  'p21_pop': '323204'},
 {'objectid': '140072',
  'reg': '91',
  'dep': '34',
  'cv': '3499',
  'codgeo': '34172',
  'libgeo': 'Montpellier',
  'p13_pop': '272084',
  'p14_pop': '275318',
  'p15_pop': '277639',
  'p16_pop': '281613',
  'p17_pop': '285121',
  'p18_pop': '290053',
  'p19_pop': '295542',
  'p20_pop': '299096',
  'p21_pop': '302454'},
 {'objectid': '125844',
  'reg': '42',
  'dep': '67',
  'cv': '6799',
  'codgeo': '67482',
  'libgeo': 'Strasbourg',
  'p13_pop': '275718',
  'p14_pop': '276170',
  'p15_pop': '277270',
  'p16_pop': '279284',
  'p17_pop': '280966',
  'p18_pop': '284677',
  'p19_pop': '287228',
  'p20_pop': '290576',
  'p21_pop': '291313'},
 {'objectid': '127920',
  'reg': '72',
  'dep': '33',
  'cv': '3397',
  'codgeo': '33063',
  'libgeo': 'Bordeaux',
  'p13_pop': '243626',
  'p14_pop': '246586',
  'p15_pop': '249712',
  'p16_pop': '252040',
  'p17_pop': '254436',
  'p18_pop': '257068',
  'p19_pop': '260958',
  'p20_pop': '259809',
  'p21_pop': '261804'},
 {'objectid': '120640',
  'reg': '31',
  'dep': '59',
  'cv': '5997',
  'codgeo': '59350',
  'libgeo': 'Lille',
  'p13_pop': '231491',
  'p14_pop': '233897',
  'p15_pop': '232741',
  'p16_pop': '232440',
  'p17_pop': '232787',
  'p18_pop': '233098',
  'p19_pop': '234475',
  'p20_pop': '236234',
  'p21_pop': '236710'},
 {'objectid': '115582',
  'reg': '11',
  'dep': '75',
  'cv': '75',
  'codgeo': '75115',
  'libgeo': 'Paris 15e  Arrondissement',
  'p13_pop': '237120',
  'p14_pop': '235366',
  'p15_pop': '234994',
  'p16_pop': '233484',
  'p17_pop': '233392',
  'p18_pop': '232144',
  'p19_pop': '230981',
  'p20_pop': '229472',
  'p21_pop': '227746'},
 {'objectid': '138083',
  'reg': '53',
  'dep': '35',
  'cv': '3598',
  'codgeo': '35238',
  'libgeo': 'Rennes',
  'p13_pop': '211373',
  'p14_pop': '213454',
  'p15_pop': '215366',
  'p16_pop': '216268',
  'p17_pop': '216815',
  'p18_pop': '217728',
  'p19_pop': '220488',
  'p20_pop': '222485',
  'p21_pop': '225081'},
 {'objectid': '144614',
  'reg': '11',
  'dep': '75',
  'cv': '75',
  'codgeo': '75120',
  'libgeo': 'Paris 20e  Arrondissement',
  'p13_pop': '194771',
  'p14_pop': '195468',
  'p15_pop': '195556',
  'p16_pop': '195604',
  'p17_pop': '195814',
  'p18_pop': '195600',
  'p19_pop': '194994',
  'p20_pop': '192120',
  'p21_pop': '189805'},
 {'objectid': '119751',
  'reg': '11',
  'dep': '75',
  'cv': '75',
  'codgeo': '75118',
  'libgeo': 'Paris 18e  Arrondissement',
  'p13_pop': '199519',
  'p14_pop': '199135',
  'p15_pop': '197580',
  'p16_pop': '195060',
  'p17_pop': '195233',
  'p18_pop': '193665',
  'p19_pop': '192468',
  'p20_pop': '191135',
  'p21_pop': '188446'}]

13.5. Fusion de tables#

with open('fr-en-annuaire-education.csv', 'r') as descripteur:
    lycees_prives = list(csv.DictReader(descripteur, delimiter=";"))
with open('fr-en-annuaire-education-mili.csv', 'r') as descripteur:
    lycees_militaires = list(csv.DictReader(descripteur, delimiter=";"))

Pour fusionner les deux tableaux par addition des lignes, il faut que les colonnes soient les même. Dans ce cas, la fusion est une simple concaténation de liste.

lycees = lycees_prives + lycees_militaires
with open('lycees.csv', 'w') as out:
    ecrivain= csv.DictWriter(out,lycees[0].keys())
    ecrivain.writeheader()
    ecrivain.writerows(lycees)

13.5.1. Fusion de colonnes#

On dispose d’un fichier avec les noms des lycées dans lequel la commune est identifiée par le champ Code_commune. On dispose également d’un fichier avec la population par commune dans lequel le code commune est identifé par codegeo.

On souhaite afficher, pour chaque lycée, le nombre d’habitants dans la commune d’implantation du lycée.

def cherche_commune(communes: list, codegeo: str) -> int:
    index = 0
    for commune in communes:
        if commune['codgeo'] == codegeo:
            return index
        index = index + 1
with open('POPULATION_MUNICIPALE_COMMUNES_FRANCE.csv', 'r') as descripteur:
    communes = list(csv.DictReader(descripteur, delimiter=";"))
cherche_commune(communes, '01034')
23360
communes[23360]
{'objectid': '135847',
 'reg': '82',
 'dep': '01',
 'cv': '0104',
 'codgeo': '01034',
 'libgeo': 'Belley',
 'p13_pop': '8909',
 'p14_pop': '8983',
 'p15_pop': '9058',
 'p16_pop': '9133',
 'p17_pop': '9103',
 'p18_pop': '9122',
 'p19_pop': '9182',
 'p20_pop': '9207',
 'p21_pop': '9239'}
communes[cherche_commune(communes, '75118')]
{'objectid': '119751',
 'reg': '11',
 'dep': '75',
 'cv': '75',
 'codgeo': '75118',
 'libgeo': 'Paris 18e  Arrondissement',
 'p13_pop': '199519',
 'p14_pop': '199135',
 'p15_pop': '197580',
 'p16_pop': '195060',
 'p17_pop': '195233',
 'p18_pop': '193665',
 'p19_pop': '192468',
 'p20_pop': '191135',
 'p21_pop': '188446'}