pandas est une des librairies de référence pour le traitement de données avec le langage Python. En tant que journaliste de données, elle constitue une alternative sérieuse à des logiciels comme Excel ou Libre Calc.
La preuve avec ce carnet de notes qui détaille plusieurs manipulations d'un csv rempli de données électorales !
J'ai pris volontairement un fichier assez classique, pour pouvoir faire des manipulations très basiques comme :
- des calculs de pourcentages
- des sélections d'échantillons
- des créations de nouvelles données à l'aide de tables de correspondance
Les choses un peu plus complexes comme les tableaux croisés dynamiques ne sont pas abordées dans ce carnet de notes. Mais j'essayerais de m'y pencher ultérieurement !
Serie et DataFrame
Avant d'entrer dans le vif du sujet, il faut présenter rapidement les deux format de données prépondérant dans pandas : les Series et les DataFrames.
Pour résumer :
- les Series correspondent en gros à des tableaux à une dimension (soit à une seule et unique colonne d'un tableur).
- les DataFrames correspondent quant à elles à des tableaux à plusieurs dimensions, ce qui nous intéresse particulièrement ici
On peut créer une DataFrame à partir de plusieurs Series ou transformer une colonne d'une DataFrame en série, mais ce type de manip' ne constituera pas le coeur de ce carnet de notes ! On va plutôt partir d'un bon vieux fichier csv à l'ancienne :-)
Lire un fichier csv
Commençons par importer le module pandas :
import pandas as pd
from pandas import DataFrame # comme on va bouffer du DataFrame, autant l'importer direct pour gagner en lisibilité
On va ensuite lire un csv avec la fonction read_csv() pour pouvoir le manipuler :
reg015 = pd.read_csv("reg015_grandest.csv")
On peut de suite vérifier que la variable reg015 correspond bien à une DataFrame :
type(reg015)
pandas.core.frame.DataFrame
On peut également obtenir le gabarit de notre DataFrame avec la fonction shape :
reg015.shape
(5189, 8)
Nous avons donc une DataFrame de 5 189 lignes sur huit colonnes.
Pour avoir un rapide aperçu de reg015, on peut utiliser les fonctions head() ou tail(), pour afficher respectivement les cinq premières ou dernières lignes du fichier.
reg015.head()
code insee | ville | inscrits | abstentions | exprimes | LDVG | LFN | LUD | |
---|---|---|---|---|---|---|---|---|
0 | 8001 | Acy-Romance | 367 | 120 | 241 | 40 | 97 | 104 |
1 | 8003 | Aiglemont | 1279 | 447 | 803 | 171 | 313 | 319 |
2 | 8004 | Aire | 150 | 46 | 99 | 16 | 18 | 65 |
3 | 8005 | Alincourt | 87 | 25 | 60 | 6 | 12 | 42 |
4 | 8006 | Alland'Huy-et-Sausseuil | 184 | 70 | 108 | 22 | 37 | 49 |
Manipulation de colonnes
Sélections
Pour afficher une seule colonne de reg015, il suffit de raisonner par nom de colonne :
reg015["ville"].tail() # cette commande affiche les cinq dernières valeurs de 'ville'
5184 Xamontarupt
5185 Xaronval
5186 Xertigny
5187 Xonrupt-Longemer
5188 Zincourt
Name: ville, dtype: object
On peut s'assurer en deux temps trois mouvements qu'une colonne d'une DataFrame est bien considérée comme une Serie :
type(reg015["ville"])
pandas.core.series.Series
Pour sélectionner plusieurs colonnes, la syntaxe est la suivante :
reg015[['code insee','ville','abstentions']].iloc[:15] # iloc sert à sélectionner une partie des données à partir de leur index
code insee | ville | abstentions | |
---|---|---|---|
0 | 8001 | Acy-Romance | 120 |
1 | 8003 | Aiglemont | 447 |
2 | 8004 | Aire | 46 |
3 | 8005 | Alincourt | 25 |
4 | 8006 | Alland'Huy-et-Sausseuil | 70 |
5 | 8007 | Les Alleux | 31 |
6 | 8008 | Amagne | 189 |
7 | 8009 | Amblimont | 47 |
8 | 8010 | Ambly-Fleury | 30 |
9 | 8011 | Anchamps | 69 |
10 | 8013 | Angecourt | 108 |
11 | 8014 | Annelles | 23 |
12 | 8015 | Antheny | 44 |
13 | 8016 | Aouste | 72 |
14 | 8017 | Apremont | 23 |
Tri par colonnes
Il peut être intéressant de trier une colonne d'une DataFrame. On va pas se mentir, c'est même une des manipulations les plus souvent répétées sur ce bon vieil Excel !
Dans notre exemple, si l'on veut trier les communes dans l'ordre décroissant des votes FN, il suffit d'utiliser la fonction sort_values() comme ceci :
reg015 = reg015.sort_values('LFN',ascending=0)
reg015.iloc[:15]
code insee | ville | inscrits | abstentions | exprimes | LDVG | LFN | LUD | |
---|---|---|---|---|---|---|---|---|
1319 | 51454 | Reims | 98837 | 47077 | 50010 | 9750 | 14686 | 25574 |
4222 | 67482 | Strasbourg | 146166 | 63471 | 80337 | 11458 | 14268 | 54611 |
3479 | 57463 | Metz | 71132 | 34191 | 35671 | 6512 | 9812 | 19347 |
4516 | 68224 | Mulhouse | 53177 | 26584 | 25372 | 4011 | 7144 | 14217 |
4359 | 68066 | Colmar | 42485 | 20330 | 21212 | 2580 | 6089 | 12543 |
2341 | 54395 | Nancy | 50991 | 20515 | 29459 | 5413 | 5269 | 18777 |
838 | 10387 | Troyes | 29096 | 13443 | 15123 | 2805 | 4656 | 7662 |
96 | 8105 | Charleville-Mézières | 29398 | 14411 | 14420 | 3046 | 4331 | 7043 |
996 | 51108 | Châlons-en-Champagne | 24982 | 11188 | 13224 | 2431 | 4314 | 6479 |
3940 | 67180 | Haguenau | 22896 | 10009 | 12380 | 1084 | 3952 | 7344 |
3683 | 57672 | Thionville | 26250 | 11325 | 14435 | 2748 | 3760 | 7927 |
1871 | 52448 | Saint-Dizier | 16547 | 8495 | 7729 | 1300 | 3352 | 3077 |
4831 | 88160 | Epinal | 21185 | 9321 | 11389 | 2228 | 2785 | 6376 |
3976 | 67218 | Illkirch-Graffenstaden | 17901 | 7464 | 10061 | 1215 | 2628 | 6218 |
3496 | 57480 | Montigny-lès-Metz | 15638 | 6985 | 8348 | 1355 | 2564 | 4429 |
On peut également prendre en compte plusieurs colonnes pour un tri.
Si on veut par exemple trier l'abstention et le FN par ordre décroissant, on peut écrire :
reg015 = reg015.sort_values(['abstentions','LFN'],ascending=[0,0])
reg015.iloc[:15]
code insee | ville | inscrits | abstentions | exprimes | LDVG | LFN | LUD | |
---|---|---|---|---|---|---|---|---|
4222 | 67482 | Strasbourg | 146166 | 63471 | 80337 | 11458 | 14268 | 54611 |
1319 | 51454 | Reims | 98837 | 47077 | 50010 | 9750 | 14686 | 25574 |
3479 | 57463 | Metz | 71132 | 34191 | 35671 | 6512 | 9812 | 19347 |
4516 | 68224 | Mulhouse | 53177 | 26584 | 25372 | 4011 | 7144 | 14217 |
2341 | 54395 | Nancy | 50991 | 20515 | 29459 | 5413 | 5269 | 18777 |
4359 | 68066 | Colmar | 42485 | 20330 | 21212 | 2580 | 6089 | 12543 |
96 | 8105 | Charleville-Mézières | 29398 | 14411 | 14420 | 3046 | 4331 | 7043 |
838 | 10387 | Troyes | 29096 | 13443 | 15123 | 2805 | 4656 | 7662 |
3683 | 57672 | Thionville | 26250 | 11325 | 14435 | 2748 | 3760 | 7927 |
996 | 51108 | Châlons-en-Champagne | 24982 | 11188 | 13224 | 2431 | 4314 | 6479 |
3940 | 67180 | Haguenau | 22896 | 10009 | 12380 | 1084 | 3952 | 7344 |
4831 | 88160 | Epinal | 21185 | 9321 | 11389 | 2228 | 2785 | 6376 |
1871 | 52448 | Saint-Dizier | 16547 | 8495 | 7729 | 1300 | 3352 | 3077 |
4188 | 67447 | Schiltigheim | 17461 | 8129 | 8968 | 1320 | 2052 | 5596 |
3256 | 57227 | Forbach | 14059 | 7591 | 6276 | 1087 | 2545 | 2644 |
Création de nouvelles colonnes
On va compléter la DataFrame, par exemple en ajoutant les pourcentages de l'abstention et de chaque liste. La formule pour créer ces nouvelles Series rappelle beaucoup l'incrémentation d'un dictionnaire Python :
reg015['pabs'] = ((reg015['abstentions']/reg015['inscrits'])*100).round(2)
reg015['pldvg'] = ((reg015['LDVG']/reg015['exprimes'])*100).round(2)
reg015['plfn'] = ((reg015['LFN']/reg015['exprimes'])*100).round(2)
reg015['plud'] = ((reg015['LUD']/reg015['exprimes'])*100).round(2)
On peut tout de suite vérifier que la manip' a fonctionné en réutilisant la fonction shape...
reg015.shape
(5189, 12)
...et en affichant les premières valeurs :
reg015 = reg015.sort('code insee')
reg015.head()
code insee | ville | inscrits | abstentions | exprimes | LDVG | LFN | LUD | pabs | pldvg | plfn | plud | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 8001 | Acy-Romance | 367 | 120 | 241 | 40 | 97 | 104 | 32.70 | 16.60 | 40.25 | 43.15 |
1 | 8003 | Aiglemont | 1279 | 447 | 803 | 171 | 313 | 319 | 34.95 | 21.30 | 38.98 | 39.73 |
2 | 8004 | Aire | 150 | 46 | 99 | 16 | 18 | 65 | 30.67 | 16.16 | 18.18 | 65.66 |
3 | 8005 | Alincourt | 87 | 25 | 60 | 6 | 12 | 42 | 28.74 | 10.00 | 20.00 | 70.00 |
4 | 8006 | Alland'Huy-et-Sausseuil | 184 | 70 | 108 | 22 | 37 | 49 | 38.04 | 20.37 | 34.26 | 45.37 |
Résumé statistique
pandas inclut une fonction describe(), qui fournit un résumé statistique d'une DataFrame.
reg015.describe()
code insee | inscrits | abstentions | exprimes | LDVG | LFN | LUD | pabs | pldvg | plfn | plud | |
---|---|---|---|---|---|---|---|---|---|---|---|
count | 5189.000000 | 5189.000000 | 5189.000000 | 5189.000000 | 5189.000000 | 5189.000000 | 5189.000000 | 5189.000000 | 5189.000000 | 5189.000000 | 5189.000000 |
mean | 52218.089420 | 748.866448 | 306.898054 | 422.042976 | 65.476200 | 152.277125 | 204.289651 | 35.063469 | 14.315629 | 41.653419 | 44.030798 |
std | 22246.978603 | 3288.345087 | 1495.242562 | 1739.999508 | 289.796553 | 441.425121 | 1044.662815 | 7.601217 | 6.859461 | 9.639802 | 10.584106 |
min | 8001.000000 | 6.000000 | 0.000000 | 3.000000 | 0.000000 | 0.000000 | 1.000000 | 0.000000 | 0.000000 | 0.000000 | 6.450000 |
25% | 51432.000000 | 111.000000 | 36.000000 | 70.000000 | 9.000000 | 30.000000 | 29.000000 | 30.530000 | 9.380000 | 35.290000 | 36.880000 |
50% | 55058.000000 | 236.000000 | 82.000000 | 144.000000 | 20.000000 | 61.000000 | 61.000000 | 35.230000 | 13.640000 | 41.320000 | 43.330000 |
75% | 67127.000000 | 553.000000 | 203.000000 | 336.000000 | 45.000000 | 136.000000 | 153.000000 | 40.000000 | 18.540000 | 47.830000 | 50.790000 |
max | 88532.000000 | 146166.000000 | 63471.000000 | 80337.000000 | 11458.000000 | 14686.000000 | 54611.000000 | 62.790000 | 50.000000 | 87.100000 | 100.000000 |
Valeurs minimale et maximale, déviation standard, moyenne, nombre d'unités (assez inutile pour le coup)... Y a pas mal de choses !
Par défaut, le tableau descriptif comprend les quartiles, mais on peut les changer à l'envie.
Par exemple, si on veut directement paramétrer des cartes par déciles avec neuf classes de couleurs, on peut procéder comme suit :
reg015.describe(percentiles=[.11, .22, .33, .44, .55, .66, .77, .88]) # chaque niveau représente un seuil de classe sur la carte
code insee | inscrits | abstentions | exprimes | LDVG | LFN | LUD | pabs | pldvg | plfn | plud | |
---|---|---|---|---|---|---|---|---|---|---|---|
count | 5189.000000 | 5189.000000 | 5189.000000 | 5189.000000 | 5189.000000 | 5189.000000 | 5189.000000 | 5189.000000 | 5189.000000 | 5189.000000 | 5189.000000 |
mean | 52218.089420 | 748.866448 | 306.898054 | 422.042976 | 65.476200 | 152.277125 | 204.289651 | 35.063469 | 14.315629 | 41.653419 | 44.030798 |
std | 22246.978603 | 3288.345087 | 1495.242562 | 1739.999508 | 289.796553 | 441.425121 | 1044.662815 | 7.601217 | 6.859461 | 9.639802 | 10.584106 |
min | 8001.000000 | 6.000000 | 0.000000 | 3.000000 | 0.000000 | 0.000000 | 1.000000 | 0.000000 | 0.000000 | 0.000000 | 6.450000 |
11% | 10113.680000 | 68.000000 | 20.000000 | 44.000000 | 5.000000 | 18.000000 | 17.000000 | 26.050000 | 6.546800 | 30.430000 | 31.966800 |
22% | 51263.360000 | 101.000000 | 33.000000 | 64.000000 | 8.000000 | 27.000000 | 27.000000 | 29.770000 | 8.790000 | 34.480000 | 35.900000 |
33% | 52247.040000 | 141.000000 | 48.000000 | 88.000000 | 12.000000 | 38.000000 | 36.000000 | 32.140000 | 10.710000 | 37.290000 | 39.040000 |
44% | 54333.720000 | 196.000000 | 68.000000 | 121.000000 | 17.000000 | 52.000000 | 50.000000 | 34.170000 | 12.500000 | 40.000000 | 41.764400 |
50% | 55058.000000 | 236.000000 | 82.000000 | 144.000000 | 20.000000 | 61.000000 | 61.000000 | 35.230000 | 13.640000 | 41.320000 | 43.330000 |
55.0% | 55369.400000 | 272.000000 | 95.000000 | 166.000000 | 23.000000 | 70.000000 | 71.000000 | 36.080000 | 14.544000 | 42.494000 | 44.584000 |
66% | 57403.080000 | 396.000000 | 143.000000 | 239.000000 | 32.000000 | 99.000000 | 104.000000 | 38.040000 | 16.570000 | 45.340800 | 47.834800 |
77% | 67238.760000 | 612.520000 | 221.000000 | 366.000000 | 50.000000 | 150.000000 | 168.000000 | 40.487600 | 18.970000 | 48.337600 | 51.750000 |
88% | 68274.440000 | 1189.000000 | 447.440000 | 712.000000 | 98.000000 | 269.000000 | 323.000000 | 43.838800 | 22.284400 | 52.602000 | 56.850000 |
max | 88532.000000 | 146166.000000 | 63471.000000 | 80337.000000 | 11458.000000 | 14686.000000 | 54611.000000 | 62.790000 | 50.000000 | 87.100000 | 100.000000 |
Sélections et expressions logiques
pandas offre également la possibilité de faire des sélections sur une DataFrame pour renvoyer une nouvelle DataFrame en résultat.
Par exemple, si on veut sélectionner les villes où le FN obtient la majorité absolue, il suffira d'entrer :
fn_vainqueur = reg015[reg015['plfn']>50] # cette syntaxe ne marchera qu'avec une seule et unique expression logique
fn_vainqueur.head()
code insee | ville | inscrits | abstentions | exprimes | LDVG | LFN | LUD | pabs | pldvg | plfn | plud | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
9 | 8011 | Anchamps | 164 | 69 | 89 | 26 | 51 | 12 | 42.07 | 29.21 | 57.30 | 13.48 |
12 | 8015 | Antheny | 98 | 44 | 50 | 3 | 27 | 20 | 44.90 | 6.00 | 54.00 | 40.00 |
13 | 8016 | Aouste | 167 | 72 | 89 | 17 | 46 | 26 | 43.11 | 19.10 | 51.69 | 29.21 |
20 | 8023 | Artaise-le-Vivier | 59 | 13 | 44 | 3 | 23 | 18 | 22.03 | 6.82 | 52.27 | 40.91 |
23 | 8026 | Aubigny-les-Pothées | 224 | 69 | 148 | 18 | 83 | 47 | 30.80 | 12.16 | 56.08 | 31.76 |
Rien n'empêche de pimenter la chose en accumulant les sélections. Si on veut ne retenir que les villes où :
- la liste de droite obtient la majorité absolue
- la liste de gauche est seconde
On peut écrire :
ud_victoire = reg015['plud']> 50
dvg_second = reg015['pldvg']> reg015['plfn']
tierce = reg015[ud_victoire & dvg_second]
tierce.head()
code insee | ville | inscrits | abstentions | exprimes | LDVG | LFN | LUD | pabs | pldvg | plfn | plud | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
16 | 8019 | Les Grandes-Armoises | 42 | 14 | 26 | 6 | 4 | 16 | 33.33 | 23.08 | 15.38 | 61.54 |
111 | 8123 | Chuffilly-Roche | 58 | 15 | 41 | 13 | 7 | 21 | 25.86 | 31.71 | 17.07 | 51.22 |
394 | 8432 | Sury | 84 | 20 | 62 | 17 | 10 | 35 | 23.81 | 27.42 | 16.13 | 56.45 |
529 | 10071 | Chacenay | 55 | 29 | 26 | 7 | 1 | 18 | 52.73 | 26.92 | 3.85 | 69.23 |
1172 | 51294 | Hourges | 67 | 23 | 44 | 9 | 5 | 30 | 34.33 | 20.45 | 11.36 | 68.18 |
A noter qu'on peut aussi rassembler les sélections directement ainsi (attention aux parenthèses) :
tierce = reg015[(reg015['plud']>50) & (reg015['pldvg']> reg015['plfn'])]
Chacune des DataFrames ainsi créées peut être par la suite enregistrée dans un nouveau fichier. Mais avant cela...
Quelques fonctions intermédiaires
Il est très courant lors d'une soirée électorale de vouloir très rapidement avoir le nom du candidat ou de la liste arrivée en tête dans tel territoire.
Une fonction de pandas toute désignée pour ça est idxmax(). On va l'utiliser en prenant en compte les voix brutes de la droite, de la gauche et de l'extrême droite pour remplir une nouvelle colonne de la DataFrame nommée 'vainqueur' :
reg015['vainqueur'] = reg015[['LDVG','LFN','LUD']].idxmax(axis=1)
reg015.iloc[:6]
code insee | ville | inscrits | abstentions | exprimes | LDVG | LFN | LUD | pabs | pldvg | plfn | plud | vainqueur | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 8001 | Acy-Romance | 367 | 120 | 241 | 40 | 97 | 104 | 32.70 | 16.60 | 40.25 | 43.15 | LUD |
1 | 8003 | Aiglemont | 1279 | 447 | 803 | 171 | 313 | 319 | 34.95 | 21.30 | 38.98 | 39.73 | LUD |
2 | 8004 | Aire | 150 | 46 | 99 | 16 | 18 | 65 | 30.67 | 16.16 | 18.18 | 65.66 | LUD |
3 | 8005 | Alincourt | 87 | 25 | 60 | 6 | 12 | 42 | 28.74 | 10.00 | 20.00 | 70.00 | LUD |
4 | 8006 | Alland'Huy-et-Sausseuil | 184 | 70 | 108 | 22 | 37 | 49 | 38.04 | 20.37 | 34.26 | 45.37 | LUD |
5 | 8007 | Les Alleux | 63 | 31 | 31 | 5 | 13 | 13 | 49.21 | 16.13 | 41.94 | 41.94 | LFN |
Les plus observateurs auront remarqué un souci : la dernière ville donne le FN vainqueur, alors qu'il est à égalité avec la droite. Moyen moins...
Il faut tricher un peu pour inclure le cas d'égalité. Voici une manip' gracieusement proposée sur StackOverflow, qui consiste en gros à appliquer un calque sur les valeurs initiales de 'vainqueur'.
Les étapes pour y arriver seront :
- créer une nouvelle Serie, disons 'somme', pour paramétrer le calque
- additionner à l'intérieur de cette Serie le nombre de maximum (!) de chaque commune
Une fois que la Serie sera prête, on la superposera à la Serie 'vainqueur' pour que :
- si la valeur de somme est égale à 1, le calque ne s'applique pas
- en revanche, si cette valeur est supérieure à 1, on pose un masque dessus en la remplaçant par 'Egalite'
Concrètement, ça donne :
somme = reg015[['LDVG','LFN','LUD']].eq(reg015[['LDVG','LFN','LUD']].max(axis=1), axis=0).sum(axis=1)
somme[:6]
0 1
1 1
2 1
3 1
4 1
5 2
dtype: int64
On voit bien qu'à l'indice 5, celui correspondant aux Alleux, le nombre de maximum est supérieur à 1.
On peut alors procéder au changement de valeurs comme suit :
reg015['vainqueur'] = reg015['vainqueur'].mask(somme > 1, 'Egalite')
reg015[:6]
code insee | ville | inscrits | abstentions | exprimes | LDVG | LFN | LUD | pabs | pldvg | plfn | plud | vainqueur | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 8001 | Acy-Romance | 367 | 120 | 241 | 40 | 97 | 104 | 32.70 | 16.60 | 40.25 | 43.15 | LUD |
1 | 8003 | Aiglemont | 1279 | 447 | 803 | 171 | 313 | 319 | 34.95 | 21.30 | 38.98 | 39.73 | LUD |
2 | 8004 | Aire | 150 | 46 | 99 | 16 | 18 | 65 | 30.67 | 16.16 | 18.18 | 65.66 | LUD |
3 | 8005 | Alincourt | 87 | 25 | 60 | 6 | 12 | 42 | 28.74 | 10.00 | 20.00 | 70.00 | LUD |
4 | 8006 | Alland'Huy-et-Sausseuil | 184 | 70 | 108 | 22 | 37 | 49 | 38.04 | 20.37 | 34.26 | 45.37 | LUD |
5 | 8007 | Les Alleux | 63 | 31 | 31 | 5 | 13 | 13 | 49.21 | 16.13 | 41.94 | 41.94 | Egalite |
Une fois ceci fait, pourquoi ne pas ajouter une couleur en fonction du parti arrivé en tête dans chaque commune ?
pandas est une librairie Python, on pourrait donc règler l'affaire en utilisant des boucles if/elif/else... mais on peut aussi vouloir utiliser une table de correspondance, par exemple :
correspondance = pd.read_csv("table_couleurs.csv")
correspondance
vainqueur | couleur | |
---|---|---|
0 | LFN | #454552 |
1 | LUD | #4ea1d3 |
2 | LDVG | #e85a71 |
Pour être parfaitement raccord à la colonne 'vainqueur' de notre grosse DataFrame, il faudrait ajouter une ligne avec le cas d'égalité.
Une DataFrame fonctionne à peu près comme une liste Python classique, à l'intérieur de laquelle on range un dictionnaire.
La commande sera plus parlante :
correspondance = correspondance.append([{'vainqueur':'Egalite','couleur':'#c0c0c0'}])
correspondance
vainqueur | couleur | |
---|---|---|
0 | LFN | #454552 |
1 | LUD | #4ea1d3 |
2 | LDVG | #e85a71 |
0 | Egalite | #c0c0c0 |
Pour faire la correspondance, la fonction merge() fait le job (ça rappellera sûrement des trucs aux utilisateurs de Google Fusion Table).
Dans notre cas, ça va donner :
reg015 = pd.merge(reg015, correspondance, how='left')
reg015[:6]
code insee | ville | inscrits | abstentions | exprimes | LDVG | LFN | LUD | pabs | pldvg | plfn | plud | vainqueur | couleur | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 8001 | Acy-Romance | 367 | 120 | 241 | 40 | 97 | 104 | 32.70 | 16.60 | 40.25 | 43.15 | LUD | #4ea1d3 |
1 | 8003 | Aiglemont | 1279 | 447 | 803 | 171 | 313 | 319 | 34.95 | 21.30 | 38.98 | 39.73 | LUD | #4ea1d3 |
2 | 8004 | Aire | 150 | 46 | 99 | 16 | 18 | 65 | 30.67 | 16.16 | 18.18 | 65.66 | LUD | #4ea1d3 |
3 | 8005 | Alincourt | 87 | 25 | 60 | 6 | 12 | 42 | 28.74 | 10.00 | 20.00 | 70.00 | LUD | #4ea1d3 |
4 | 8006 | Alland'Huy-et-Sausseuil | 184 | 70 | 108 | 22 | 37 | 49 | 38.04 | 20.37 | 34.26 | 45.37 | LUD | #4ea1d3 |
5 | 8007 | Les Alleux | 63 | 31 | 31 | 5 | 13 | 13 | 49.21 | 16.13 | 41.94 | 41.94 | Egalite | #c0c0c0 |
Transformer une DataFrame en fichier
Un instinct primaire encouragerait à tenter une fonction to_csv() pour transformer une DataFrame, et il aurait raison !
reg015.to_csv("reg015_def.csv")
Pandas obéit par défaut à une logique anglo-saxonne : les séparateurs de données sont des virgules, ce qui tombe bien puisque les décimales sont représentées par des points.
Mais rien n'interdit d'ajouter quelques paramètres pour avoir à l'arrivée un csv lisible avec une configuration francophone !
reg015.to_csv("reg015_deffr.csv", sep = ";", decimal = ",")
C'est tout pour aujourd'hui !
Point Github
Les CSV utilisés pour cette démo ont été publiés via mon compte Github, avec un carnet de notes qui en détaille les grandes lignes !