27 avril 2022
Ce texte fait partie d’une petite collection de notes mise à disposition selon les termes de la Licence Creative Commons Attribution - Pas d’Utilisation Commerciale - Partage dans les Mêmes Conditions 2.0 France.
Sur les réseaux sociaux, on trouve régulièrement des messages promouvant l’usage des machines à voter, ou du vote en ligne.
Pour faire bref, je suis contre les deux, mais ce n’est pas le point. L’objet de cette note c’est de réfuter l’affirmation à propos du vote “papier” :
Ok, on peut surveiller le vote et le dépouillement (en étant présent dans les bureaux) , mais pour la totalisation nationale, on ne peut pas faire faire confiance.
en montrant
Su l’exemple de la présidentielle 2022.
Pour ça, on verra comment
Pourquoi Python ? Parce que c’est un langage de programmation
Une recherche Google, “open data vote présidentielle 2022” donne comme second résultat2 le lien https://www.data.gouv.fr/fr/datasets/resultats-du-premier-tour-de-lelection-presidentielle-2022-par-commune-et-par-departement/
Puisqu’on tient à vérifier les totaux, voyons grand : on part du fichier presidentielle-2022-t1-resultats-par-commune.csv
qui pèse 104Mo et a été télé-chargé 2905 fois à ce jour.
En cliquant sur le lien https://www.data.gouv.fr/fr/datasets/r/54782507-e795-4f9d-aa70-ed06feba22e3 (bouton bleu à droite), ça nous ramène un fichier qui s’appelle en fait 04-resultats-par-commune.csv
.
On le place dans un répertoire de travail, où il sera rejoint plus tard par le programme Python.
C’est un fichier CSV classique, qui présente les données sous forme de table. On peut l’importer avec un tableau, sans problème.
La première ligne fournit les noms des colonnes, et permet aussi de voir que les données d’une ligne sont séparées par des virgules
C’est une très longue ligne, pour la lisibilité, elle est coupée en lignes de 5 champs ci-dessous
En regardant les deux premières lignes de données
on constate que chaque ligne montre le nombre de voix obtenues par un candidat dans une commune. Et que les lignes reprennent les informations de la commune (identification, nombre d’inscrits etc.)
En regardant la fin du fichier, on voit que les données vont jusqu’à la dernière ligne.
Bref, on va simplement faire les totaux de la colonne “cand_nb_voix
” en les différenciant sur le “cand_nom
”3, à partir de la seconde ligne. Ce sont les colonnes 26 et 29 respectivement.
Une autre chose : ce sont bien des résultats par commune. Le fichier comporte 420961 lignes. 360000 communes à peu près, multiplié par 12 candidats, ça fait 432000, qui est de cet ordre (les lignes avec 0 voix n’y figurent pas).
Si on sait se servir des commandes, on peut vérifier qu’il n’y a que 12 lignes pour Bordeaux4, par exemple
$ grep ,Bordeaux, Calculs-Elections/04-resultats-par-commune.csv | wc -l
12
donc il s’agit bien de chiffres par commune, pas par bureau. Autre moyen de vérifier : regarder avec un tableur.
L’objectif est de totaliser, selon le nom des candidats, les voix qu’ils ont obtenues.
Ce programme va être développé par étapes, pour vérifier plus facilement qu’il n’y a pas d’erreurs. Il sera testé sur un échantillon (un certain nombre de lignes du fichier).
Pour faire ce travail on va employer
csv
de Python pour lire les données,La première étape consiste à lire le fichier ligne par ligne et isoler, puis afficher, les noms des candidats et leur nombre de voix.
limite = 5 # nb de lignes pour le tesst
pour chaque ligne:
si c'est la ligne 1:
rien
sinon si c'est la ligne limite + 1:
sortir de la boucle
sinon
extraire et afficher le nom et le nombre de voix
Normalement, il devrait s’afficher limite-1 résultats puisque la ligne 1 est ignorée.
L’exécution de ce code
#
# Phase 1 : vérifier qu'on arrive à extraire
# correctement les noms et nombre de voix obtenus
import csv
= '04-resultats-par-commune.csv'
nom_fichier = 26-1
col_nom = 29-1
col_nb_voix
= 5
limite_ligne
with open(nom_fichier) as fichier:
= csv.reader(fichier)
lecteur = 0
numero_ligne for ligne in lecteur:
+= 1
numero_ligne if numero_ligne > limite_ligne:
break
if numero_ligne > 1:
print ("nom =", ligne[col_nom], "voix =", ligne[col_nb_voix])
Notes :
ligne
est indicé à partir de 0, la 26ième colonne est à l’indice 26-1.L’exécution produit l’affichage
nom = ARTHAUD voix = 3
nom = ROUSSEL voix = 6
nom = MACRON voix = 150
nom = LASSALLE voix = 18
dont on peut vérifier (avec un tableur) qu’il correspond bien aux 5 premières lignes du fichier.
Pour la comptabilisation, on totalise les voix de chaque candidat
Pour tester il faudra avoir au moins deux communes, une vingtaine de lignes devraient suffire
limite = 20 # nb de lignes pour le test
totaux_voix = { } # dictionnaire vide
pour chaque ligne:
si c'est la ligne 1:
rien
sinon si c'est la ligne limite + 1:
sortir de la boucle
sinon
extraire et afficher le nom et le nombre de voix
ajouter nombre de voix à totaux_voix[nom]
afficher totaux_voix
afficher total_voix (final)
Une grande partie du code vient du programme précédent :
#
# Phase 2 : extraire les noms et nombre de voix obtenus
# vérifier le cumul
import csv
= '04-resultats-par-commune.csv'
nom_fichier = 26-1
col_nom = 29-1
col_nb_voix
= 20
limite_ligne = {}
totaux_voix
with open(nom_fichier) as fichier:
= csv.reader(fichier)
lecteur = 0
numero_ligne for ligne in lecteur:
+= 1
numero_ligne if numero_ligne > limite_ligne:
break
if numero_ligne > 1:
= ligne[col_nom]
nom = int(ligne[col_nb_voix])
nb_voix print ("nom =", nom, "voix =", nb_voix)
= totaux_voix.setdefault(nom, 0) + nb_voix
totaux_voix[nom] print ("=", totaux_voix)
print ("totaux", totaux_voix)
Notes :
nom
et nb_voix
sont introduites pour ne pas avoir à répéter des sous-expressions ;setdefault
est employée pour retourner la valeur présente pour un nom présent, et 0 si il est absent ;Avec 20 lignes, on obtient au début :
nom = ARTHAUD voix = 3
= {'ARTHAUD': 3}
nom = ROUSSEL voix = 6
= {'ARTHAUD': 3, 'ROUSSEL': 6}
nom = MACRON voix = 150
= {'ARTHAUD': 3, 'ROUSSEL': 6, 'MACRON': 150}
...
qui montre le remplissage avec des noms qui n’ont pas encore été rencontrés.
À la fin, les dernières lignes
...
= {'ARTHAUD': 5, 'ROUSSEL': 13, 'MACRON': 200, 'LASSALLE': 28, 'LE PEN': 172, 'ZEMMOUR': 57,
'MÉLENCHON': 66, 'HIDALGO': 5, 'JADOT': 30, 'PÉCRESSE': 26, 'POUTOU': 3, 'DUPONT-AIGNAN': 21}
nom = MÉLENCHON voix = 41
= {'ARTHAUD': 5, 'ROUSSEL': 13, 'MACRON': 200, 'LASSALLE': 28, 'LE PEN': 172, 'ZEMMOUR': 57,
'MÉLENCHON': 107, 'HIDALGO': 5, 'JADOT': 30, 'PÉCRESSE': 26, 'POUTOU': 3, 'DUPONT-AIGNAN': 21}
totaux {'ARTHAUD': 5, 'ROUSSEL': 13, 'MACRON': 200, 'LASSALLE': 28, 'LE PEN': 172, 'ZEMMOUR': 57,
'MÉLENCHON': 107, 'HIDALGO': 5, 'JADOT': 30, 'PÉCRESSE': 26, 'POUTOU': 3, 'DUPONT-AIGNAN': 21}
font voir l’ajout de 41 voix au score de Mélenchon, qui passe de 66 à 107.
Pour le programme final, on retire
et on soigne la présentation du résultat.
#
# Totalisation des voix au premier tour de l'élection présidentielle 2022
#
import csv
= '04-resultats-par-commune.csv'
nom_fichier = 26-1
col_nom = 29-1
col_nb_voix
= {}
totaux_voix
print ("= totaux voix premier tour présidentielle 2022")
with open(nom_fichier) as fichier:
= csv.reader(fichier)
lecteur = 0
numero_ligne for ligne in lecteur:
+= 1
numero_ligne if numero_ligne > 1:
= ligne[col_nom]
nom = int(ligne[col_nb_voix])
nb_voix = totaux_voix.setdefault(nom, 0) + nb_voix
totaux_voix[nom]
# affichage final
for (nom, nb_voix) in totaux_voix.items():
print ('{:10d} {}'.format(nb_voix, nom))
L’exécution, qui porte maintenant sur l’ensemble des données, ne prend que quelques secondes. On voit s’afficher :
= totaux voix premier tour présidentielle 2022
200662 ARTHAUD
827497 ROUSSEL
10087245 MACRON
1116933 LASSALLE
8261595 LE PEN
2585422 ZEMMOUR
8104784 MÉLENCHON
635705 HIDALGO
1700458 JADOT
1751714 PÉCRESSE
274938 POUTOU
735698 DUPONT-AIGNAN
Avec un effort, on pourrait classer par ordre alphabétique, ou par score, selon les besoins. Le besoin n’étant pas précisé, il est jugé inutile de s’en occuper.
Ces chiffres diffèrent un petit peu https://fr.wikipedia.org/wiki/%C3%89lection_pr%C3%A9sidentielle_fran%C3%A7aise_de_2022#R%C3%A9sultats_nationaux des résultats nationaux affichés sur Wikipedia, par exemple.
Possibilités
Il est assez probable que les chiffres de Wikipédia, ainsi que l’annonce officielle des résultats au soir du premier tour, aient été établis à partir de données incomplètes.
Rien d’anormal : il faut en réalité quelques jours pour que le Conseil Constitutionnel se prononce sur la validité des resultats dans certains bureaux litigieux.
pour comptabiliser d’autres élections, il faudra le modifier un peu, chaque élection donnant lieu à une présentation légèrement différente des données dans le fichier.↩︎
Le premier donne les résultats pour Paris uniquement.↩︎
par chance, on n’a pas d’homonymes à la présidentielle. On pourrait aussi utiliser le numéro de panneau, qui est attribué nationalement, pour identifier les candidats.↩︎
Ville assez grande pour avoir plusieurs bureaux, et assez de gens qui votent n’importe que quoi pour qu’il soit très probable que chaque candidat a obtenu au moins une voix.↩︎