L'âge moyen des sénateurs français

Cette semaine, après avoir travaillé sur l'âge moyen des députés français, je vous propose de nous intéresser à celui des sénateurs.

Premier constat : la tâche ne va pas être aussi facile que dans le cas des députés. En effet, je n'ai pas réussi à trouver une base de données avec les dates de naissance des sénateurs ou de fichier PDF comme dans le cas des députés avec toutes les données d'un coup. Il va donc falloir travailler un peu plus afin d'extraire les données du site web du sénat et son index alphabétique.

Afin de faire ceci, nous allons utiliser les outils Python classique pour ce genre de tâche : requests et beautiful soup.

Comment extraire la date de naissance d'un sénateur de sa notice bibliographique ?

Tout part de la notice bibliographique du sénateur. Par exemple, celle de Michel Berson, sénateur de l'Essonne.

On peut télécherger le contenu de cette page à l'aide du code suivant :

In [1]:
import requests
In [2]:
r = requests.get("http://www.senat.fr/senateur/berson_michel11068s.html")
r
Out[2]:
<Response [200]>

La réponse 200 signifie que le téléchargement de la page s'est bien passé.

Pour extraire la date de naissance, il faut regarder le code HTML de la page et utiliser beautiful soup. On construit notre soupe :

In [3]:
from bs4 import BeautifulSoup
soup = BeautifulSoup(r.text, 'html.parser')

La date de naissance se trouve dans un tag 'dd' lui-même contenu dans un tag 'dl'. On peut trouver ces éléments ainsi :

In [4]:
items = soup.find('dl').find_all('dd')
items
Out[4]:
[<dd>
 <a class="link-color-01" href="mailto:m.berson@senat.fr">m.berson@senat.fr</a> 
 </dd>, <dd>
 <ul class="list-contact-01">
 <li><a href="http://www.michelberson.fr" target="_blank"><img alt="http://www.michelberson.fr" src="/fileadmin/templates/images/data/picto_contact_blog.png"/></a></li>
 <li><a href="http://www.facebook.com/michel.berson" target="_blank"><img alt="Profil Facebook" src="/fileadmin/templates/images/data/picto_contact_facebook.png"/></a></li>
 </ul>
 <ul class="list-contact-01">
 <li><a href="http://twitter.com/michel_berson" target="_blank"><img alt="Compte Twitter" src="/fileadmin/templates/images/data/picto_contact_twitter.png"/></a></li>
 </ul>
 </dd>, <dd>Né le 21 avril 1945</dd>, <dd>Cadre dans le secteur bancaire</dd>, <dd><img alt="Place dans l'hémicycle" src="/fileadmin/templates/images/senateurs/hemicycle/place-hemicycle_311.jpg" width="170">
 </img></dd>, <dd><a href="/senateurs/sencir.html#c265"><img alt="Circonscription" src="/fileadmin/templates/images/senateurs/dpt/circonscription_91.jpg"/></a>
 <div class="link link-type-02">
 <a href="/senateurs/sencir.html#c265">Tous les Sénateurs de la
 circonscription</a>
 </div>
 </dd>]

La date de naissance qui nous intéresse est dans le deuxième item :

In [5]:
[item.text for item in items if item.text.startswith('Né')]
Out[5]:
['Né le 21 avril 1945']

On peut, sur le même principe, également écrire une fonction qui extrait le nom du sénateur de la page :

In [6]:
soup.find('h1','title-01').text
Out[6]:
'M. Michel Berson'

Maintenant que nous savons faire ça, nous pouvons écrire un fonction qui extrait la date de naissance de l'url de la page d'un sénateur, de même que son nom :

In [7]:
def url2data(url):
    """Télécharge la page de l'url et extrait la date de naissance du sénateur."""
    r = requests.get(url)
    if r.ok:
        soup = BeautifulSoup(r.text, 'html.parser')
        birthdate = [item.text for item in soup.find('dl').find_all('dd') if item.text.startswith('Né')][0]
        name = soup.find('h1','title-01').text
        return (name, birthdate)
    else:
        raise("Something went wrong with the web request")

On peut tester la fonction :

In [8]:
url2data("http://www.senat.fr/senateur/berson_michel11068s.html")
Out[8]:
('M. Michel Berson', 'Né le 21 avril 1945')

Pour avoir toutes les dates de naissances, il nous faut maintenant appliquer cette procédure à toutes les urls que l'on trouve sur l'index alphabétique du sénat.

Répéter l'opération d'extraction pour chaque sénateur

A partir de la page d'index biographique, nous pouvons, de la même manière que précédemment, extraire les liens vers les différentes pages de sénateurs :

In [11]:
r = requests.get("http://www.senat.fr/senateurs/senatl.html")
r
Out[11]:
<Response [200]>

On fait une petite sousoupe :

In [12]:
soup = BeautifulSoup(r.text, 'html.parser')

Et maintenant on cherche des liens qui sont dans des balises du type ul li a. Tant qu'à faire, on ne garde que ceux qui pointen vers une page de sénateur :

In [13]:
urls = [link.get('href') for link in soup.select('ul li a') if link.get('href').startswith('/senateur/')]
In [14]:
len(urls)
Out[14]:
348

Nous dénombrons bien 348 sénateurs. Passons à l'extraction des dates de naissance.

In [15]:
birthdates = {}
for url in urls:
    name, bd = url2data("http://www.senat.fr" + url)
    birthdates[name] = bd

Regardons le résultat :

In [16]:
birthdates
Out[16]:
{'M. Abdourahamane Soilihi': 'Né le 4 octobre 1959',
 'M. Alain Anziani': 'Né le 30 mai 1951',
 'M. Alain Bertrand': 'Né le 23 février 1951',
 'M. Alain Chatillon': 'Né le 15 mars 1943',
 'M. Alain Dufaut': 'Né le 2 janvier 1944',
 'M. Alain Duran': 'Né le 2 janvier 1958',
 'M. Alain Fouché': 'Né le 4 décembre 1942',
 'M. Alain Gournac': 'Né le 13 septembre 1943',
 'M. Alain Houpert': 'Né le 13 août 1957',
 'M. Alain Joyandet': 'Né le 15 janvier 1954',
 'M. Alain Marc': 'Né le 29 janvier 1957',
 'M. Alain Milon': 'Né le 16 septembre 1947',
 'M. Alain Néri': 'Né le 1er mai 1942',
 'M. Alain Richard': 'Né le 29 août 1945',
 'M. Alain Vasselle': 'Né le 27 juin 1947',
 'M. Albéric de Montgolfier': 'Né le 6 juillet 1964',
 'M. Alex Türk': 'Né le 25 janvier 1950',
 'M. André Gattolin': 'Né le 24 juin 1960',
 'M. André Reichardt': 'Né le 5 décembre 1949',
 'M. André Trillard': 'Né le 24 octobre 1947',
 'M. Antoine Karam': 'Né le 21 février 1950',
 'M. Antoine Lefèvre': 'Né le 18 février 1966',
 'M. Benoît Huré': 'Né le 5 juin 1953',
 'M. Bernard Cazeau': 'Né le 27 avril 1939',
 'M. Bernard Delcros': 'Né le 12 février 1953',
 'M. Bernard Fournier': 'Né le 13 septembre 1946',
 'M. Bernard Lalande': 'Né le 6 avril 1954',
 'M. Bernard Saugey': 'Né le 3 mars 1943',
 'M. Bruno Gilles': 'Né le 26 décembre 1960',
 'M. Bruno Retailleau': 'Né le 20 novembre 1960',
 'M. Bruno Sido': 'Né le 19 février 1951',
 'M. Charles Guené': 'Né le 6 avril 1952',
 'M. Charles Revet': 'Né le 9 novembre 1937',
 'M. Christian Cambon': 'Né le 8 mars 1948',
 'M. Christian Favier': 'Né le 20 février 1951',
 'M. Christian Manable': 'Né le 19 juin 1948',
 'M. Christian Namy': 'Né le 19 octobre 1938',
 'M. Christophe Béchu': 'Né le 11 juin 1974',
 'M. Christophe-André Frassa': 'Né le 4 février 1968',
 'M. Claude Bérit-Débat': 'Né le 19 février 1946',
 'M. Claude Haut': 'Né le 22 décembre 1944',
 'M. Claude Kern': 'Né le 13 mars 1959',
 'M. Claude Malhuret': 'Né le 8 mars 1950',
 'M. Claude Nougein': 'Né le 4 décembre 1946',
 'M. Claude Raynal': 'Né le 10 octobre 1957',
 'M. Cyril Pellevat': 'Né le 18 février 1981',
 'M. Cédric Perrin': 'Né le 20 janvier 1974',
 'M. Daniel Chasseing': 'Né le 10 avril 1945',
 'M. Daniel Dubois': 'Né le 5 février 1952',
 'M. Daniel Gremillet': 'Né le 31 juillet 1953',
 'M. Daniel Laurent': 'Né le 4 février 1949',
 'M. Daniel Percheron': 'Né le 31 août 1942',
 'M. Daniel Raoul': 'Né le 28 juillet 1941',
 'M. Daniel Reiner': 'Né le 17 janvier 1941',
 'M. David Assouline': 'Né le 16 juin 1959',
 'M. David Rachline': 'Né le 2 décembre 1987',
 'M. Didier Guillaume': 'Né le 11 mai 1959',
 'M. Didier Mandelli': 'Né le 7 août 1964',
 'M. Didier Marie': 'Né le 19 mai 1960',
 'M. Didier Robert': 'Né le 26 avril 1964',
 'M. Dominique Bailly': 'Né le 2 janvier 1960',
 'M. Dominique Watrin': 'Né le 14 juin 1953',
 'M. Dominique de Legge': 'Né le 18 février 1952',
 'M. Francis Delattre': 'Né le 11 septembre 1946',
 'M. Franck Montaugé': 'Né le 14 septembre 1961',
 'M. François Baroin': 'Né le 21 juin 1965',
 'M. François Bonhomme': 'Né le 5 mai 1969',
 'M. François Calvet': 'Né le 1er avril 1953',
 'M. François Commeinhes': 'Né le 10 novembre 1949',
 'M. François Fortassin': 'Né le 2 août 1939',
 'M. François Grosdidier': 'Né le 25 février 1961',
 'M. François Marc': 'Né le 19 mars 1950',
 'M. François Patriat': 'Né le 21 mars 1943',
 'M. François Pillet': 'Né le 13 mai 1950',
 'M. François Zocchetto': 'Né le 14 décembre 1958',
 'M. François-Noël Buffet': 'Né le 28 août 1963',
 'M. Félix Desplan': 'Né le 22 février 1943',
 'M. Gaëtan Gorce': 'Né le 2 décembre 1958',
 'M. Georges Labazée': 'Né le 16 juin 1943',
 'M. Georges Patient': 'Né le 1er avril 1949',
 'M. Gilbert Barbier': 'Né le 3 mars 1940',
 'M. Gilbert Bouchet': 'Né le 8 janvier 1947',
 'M. Gilbert Roger': 'Né le 9 novembre 1953',
 'M. Guillaume Arnell': 'Né le 20 janvier 1958',
 'M. Guy-Dominique Kennel': 'Né le 14 avril 1952',
 'M. Gérard Bailly': 'Né le 28 janvier 1940',
 'M. Gérard Collomb': 'Né le 20 juin 1947',
 'M. Gérard Cornu': 'Né le 6 février 1952',
 'M. Gérard César': 'Né le 19 décembre 1934',
 'M. Gérard Dériot': 'Né le 1er novembre 1944',
 'M. Gérard Larcher': 'Né le 14 septembre 1949',
 'M. Gérard Longuet': 'Né le 24 février 1946',
 'M. Gérard Miquel': 'Né le 17 juin 1946',
 'M. Gérard Roche': 'Né le 29 décembre 1942',
 'M. Henri Cabanel': 'Né le 9 mars 1959',
 'M. Henri Tandonnet': 'Né le 14 décembre 1949',
 'M. Henri de Raincourt': 'Né le 17 novembre 1948',
 'M. Hervé Marseille': 'Né le 20 août 1954',
 'M. Hervé Maurey': 'Né le 7 mai 1961',
 'M. Hervé Poher': 'Né le 19 mai 1952',
 'M. Hilarion Vendegou': 'Né le 4 septembre 1941',
 'M. Hubert Falco': 'Né le 15 mai 1947',
 'M. Hugues Portelli': 'Né le 22 décembre 1947',
 'M. Jackie Pierre': 'Né le 27 mai 1946',
 'M. Jacques Bigot': 'Né le 31 juillet 1952',
 'M. Jacques Chiron': 'Né le 3 octobre 1949',
 'M. Jacques Cornano': 'Né le 18 novembre 1956',
 'M. Jacques Gautier': 'Né le 18 septembre 1946',
 'M. Jacques Genest': 'Né le 6 août 1950',
 'M. Jacques Gillot': 'Né le 4 mars 1948',
 'M. Jacques Grosperrin': 'Né le 17 octobre 1955',
 'M. Jacques Legendre': 'Né le 2 décembre 1941',
 'M. Jacques Mézard': 'Né le 3 décembre 1947',
 'M. Jacques-Bernard Magner': 'Né le 1er juin 1952',
 'M. Jean Bizet': 'Né le 30 août 1947',
 'M. Jean Desessard': 'Né le 6 septembre 1952',
 'M. Jean Louis Masson': 'Né le 25 mars 1947',
 'M. Jean Pierre Vogel': 'Né le 7 août 1956',
 'M. Jean-Baptiste Lemoyne': 'Né le 15 septembre 1977',
 'M. Jean-Claude Boulard': 'Né le 28 mars 1943',
 'M. Jean-Claude Carle': 'Né le 9 juin 1948',
 'M. Jean-Claude Frécon': 'Né le 3 septembre 1944',
 'M. Jean-Claude Gaudin': 'Né le 8 octobre 1939',
 'M. Jean-Claude Lenoir': 'Né le 27 décembre 1944',
 'M. Jean-Claude Leroy': 'Né le 3 juin 1952',
 'M. Jean-Claude Luche': 'Né le 7 août 1952',
 'M. Jean-Claude Requier': 'Né le 4 octobre 1947',
 'M. Jean-François Husson': 'Né le 17 avril 1961',
 'M. Jean-François Longeot': 'Né le 27 décembre 1956',
 'M. Jean-François Mayet': 'Né le 30 janvier 1940',
 'M. Jean-François Rapin': 'Né le 11 mai 1966',
 'M. Jean-Jacques Filleul': 'Né le 22 juin 1943',
 'M. Jean-Jacques Lasserre': 'Né le 11 mars 1944',
 'M. Jean-Jacques Lozach': 'Né le 8 février 1954',
 'M. Jean-Jacques Panunzi': 'Né le 5 avril 1956',
 'M. Jean-Louis Carrère': 'Né le 4 décembre 1944',
 'M. Jean-Louis Tourenne': 'Né le 25 août 1944',
 'M. Jean-Léonce Dupont': 'Né le 31 janvier 1955',
 'M. Jean-Marc Gabouty': 'Né le 17 mai 1949',
 'M. Jean-Marie Bockel': 'Né le 22 juin 1950',
 'M. Jean-Marie Morisset': 'Né le 18 août 1947',
 'M. Jean-Marie Vanlerenberghe': 'Né le 29 mars 1939',
 'M. Jean-Noël Cardoux': 'Né le 18 décembre 1946',
 'M. Jean-Noël Guérini': 'Né le 1er janvier 1951',
 'M. Jean-Paul Emorine': 'Né le 20 mars 1944',
 'M. Jean-Paul Fournier': 'Né le 16 octobre 1945',
 'M. Jean-Pierre Bosino': 'Né le 15 janvier 1959',
 'M. Jean-Pierre Caffet': 'Né le 8 novembre 1951',
 'M. Jean-Pierre Cantegrit': 'Né le 2 juillet 1933',
 'M. Jean-Pierre Godefroy': 'Né le 23 septembre 1944',
 'M. Jean-Pierre Grand': 'Né le 18 novembre 1950',
 'M. Jean-Pierre Leleux': 'Né le 8 mai 1947',
 'M. Jean-Pierre Masseret': 'Né le 23 août 1944',
 'M. Jean-Pierre Raffarin': 'Né le 3 août 1948',
 'M. Jean-Pierre Sueur': 'Né le 28 février 1947',
 'M. Jean-Pierre Vial': 'Né le 17 février 1951',
 'M. Jean-Vincent Placé': 'Né le 12 mars 1968',
 'M. Jean-Yves Leconte': 'Né le 31 octobre 1966',
 'M. Jean-Yves Roux': 'Né le 18 janvier 1970',
 'M. Jeanny Lorgeoux': 'Né le 2 janvier 1950',
 'M. Joseph Castelli': 'Né le 4 juin 1948',
 'M. Joël Guerriau': 'Né le 9 novembre 1957',
 'M. Joël Labbé': 'Né le 18 octobre 1952',
 'M. Jérôme Bignon': 'Né le 1er janvier 1949',
 'M. Jérôme Durain': 'Né le 2 juin 1969',
 'M. Ladislas Poniatowski': 'Né le 10 novembre 1946',
 'M. Louis Duvernois': 'Né le 17 mai 1941',
 'M. Louis Nègre': 'Né le 8 février 1947',
 'M. Louis Pinton': 'Né le 24 octobre 1948',
 'M. Louis-Jean de Nicolaÿ': 'Né le 18 septembre 1949',
 'M. Loïc Hervé': 'Né le 8 juin 1980',
 'M. Luc Carvounas': 'Né le 8 juin 1971',
 'M. Marc Daunis': 'Né le 22 avril 1955',
 'M. Marc Laménie': 'Né le 11 juillet 1956',
 'M. Martial Bourquin': 'Né le 23 juillet 1952',
 'M. Mathieu Darnaud': 'Né le 11 juillet 1975',
 'M. Maurice Antiste': 'Né le 22 juin 1953',
 'M. Maurice Vincent': 'Né le 20 septembre 1955',
 'M. Michel Amiel': 'Né le 3 juillet 1954',
 'M. Michel Berson': 'Né le 21 avril 1945',
 'M. Michel Billout': 'Né le 19 février 1958',
 'M. Michel Boutant': 'Né le 23 novembre 1956',
 'M. Michel Bouvard': 'Né le 17 mars 1955',
 'M. Michel Canevet': 'Né le 14 décembre 1960',
 'M. Michel Delebarre': 'Né le 27 avril 1946',
 'M. Michel Fontaine': 'Né le 6 mai 1952',
 'M. Michel Forissier': 'Né le 12 septembre 1943',
 'M. Michel Houel': 'Né le 8 novembre 1942',
 'M. Michel Le Scouarnec': 'Né le 12 juillet 1949',
 'M. Michel Magras': 'Né le 6 janvier 1954',
 'M. Michel Mercier': 'Né le 7 mars 1947',
 'M. Michel Raison': 'Né le 5 novembre 1949',
 'M. Michel Savin': 'Né le 25 novembre 1958',
 'M. Michel Vaspart': 'Né le 22 février 1948',
 'M. Michel Vergoz': 'Né le 10 janvier 1950',
 'M. Nuihau Laurey': 'Né le 29 décembre 1964',
 'M. Olivier Cadic': 'Né le 22 avril 1962',
 'M. Olivier Cigolotti': 'Né le 16 août 1963',
 'M. Pascal Allizard': 'Né le 19 décembre 1962',
 'M. Patrick Abate': 'Né le 28 décembre 1956',
 'M. Patrick Chaize': 'Né le 22 mars 1963',
 'M. Patrick Masclet': 'Né le 31 mai 1952',
 'M. Paul Vergès': 'Né le 5 mars 1925',
 'M. Philippe Adnot': 'Né le 25 août 1945',
 'M. Philippe Bas': 'Né le 20 juillet 1958',
 'M. Philippe Bonnecarrère': 'Né le 12 juillet 1955',
 'M. Philippe Dallier': 'Né le 8 décembre 1962',
 'M. Philippe Dominati': 'Né le 12 avril 1954',
 'M. Philippe Esnol': 'Né le 2 avril 1954',
 'M. Philippe Kaltenbach': 'Né le 9 janvier 1966',
 'M. Philippe Leroy': 'Né le 3 février 1940',
 'M. Philippe Madrelle': 'Né le 21 avril 1937',
 'M. Philippe Mouiller': 'Né le 20 septembre 1969',
 'M. Philippe Nachbar': 'Né le 26 septembre 1950',
 'M. Philippe Paul': 'Né le 25 janvier 1965',
 'M. Pierre Camani': 'Né le 19 février 1952',
 'M. Pierre Charon': 'Né le 1er mars 1951',
 'M. Pierre Frogier': 'Né le 16 novembre 1950',
 'M. Pierre Laurent': 'Né le 1er juillet 1957',
 'M. Pierre Médevielle': 'Né le 17 avril 1960',
 'M. Pierre-Yves Collombat': 'Né le 18 juillet 1945',
 'M. Rachel Mazuir': 'Né le 12 février 1940',
 'M. Raymond Vall': 'Né le 13 janvier 1942',
 'M. René Danesi': 'Né le 30 août 1947',
 'M. René Vandierendonck': 'Né le 1er avril 1951',
 'M. René-Paul Savary': 'Né le 3 janvier 1953',
 'M. Richard Yung': 'Né le 22 septembre 1947',
 'M. Robert Hue': 'Né le 19 octobre 1946',
 'M. Robert Laufoaulu': 'Né le 7 juillet 1947',
 'M. Robert Navarro': 'Né le 1er mai 1952',
 'M. Robert del Picchia': 'Né le 10 novembre 1942',
 'M. Roger Karoutchi': 'Né le 26 août 1951',
 'M. Roger Madec': 'Né le 27 octobre 1950',
 'M. Roland Courteau': 'Né le 24 février 1943',
 'M. Ronan Dantec': 'Né le 5 août 1963',
 'M. Rémy Pointereau': 'Né le 30 mars 1953',
 'M. Serge Dassault': 'Né le 4 avril 1925',
 'M. Serge Larcher': 'Né le 17 octobre 1945',
 'M. Simon Sutour': 'Né le 18 août 1952',
 'M. Stéphane Ravier': 'Né le 4 août 1969',
 'M. Thani Mohamed Soilihi': 'Né le 20 juin 1972',
 'M. Thierry Carcenac': 'Né le 19 décembre 1950',
 'M. Thierry Foucaud': 'Né le 18 janvier 1954',
 'M. Vincent Capo-Canellas': 'Né le 4 mai 1967',
 'M. Vincent Delahaye': 'Né le 23 août 1959',
 'M. Vincent Eblé': 'Né le 15 octobre 1957',
 'M. Xavier Pintat': 'Né le 15 mars 1954',
 'M. Yannick Botrel': 'Né le 9 décembre 1951',
 'M. Yannick Vaugrenard': 'Né le 25 juin 1950',
 'M. Yves Daudigny': 'Né le 23 février 1947',
 'M. Yves Détraigne': 'Né le 21 décembre 1954',
 'M. Yves Pozzo di Borgo': 'Né le 3 mai 1948',
 'M. Yves Rome': 'Né le 25 avril 1950',
 'M. Yvon Collin': 'Né le 10 avril 1944',
 'M. Éric Bocquet': 'Né le 8 novembre 1957',
 'M. Éric Doligé': 'Né le 25 mai 1943',
 'M. Éric Jeansannetas': 'Né le 21 octobre 1962',
 'Mme Agnès Canayer': 'Née le 21 septembre 1965',
 'Mme Aline Archimbaud': 'Née le 2 novembre 1948',
 'Mme Anne Chain-Larché': 'Née le 11 avril 1958',
 'Mme Anne Emery-Dumas': 'Née le 30 août 1959',
 'Mme Anne-Catherine Loisier': 'Née le 13 mars 1969',
 'Mme Annick Billon': 'Née le 3 août 1967',
 'Mme Annie David': 'Née le 17 janvier 1963',
 'Mme Annie Guillemot': 'Née le 27 janvier 1956',
 'Mme Bariza Khiari': 'Née le 3 septembre 1946',
 'Mme Brigitte Gonthier-Maurin': 'Née le 23 avril 1956',
 'Mme Brigitte Micouleau': 'Née le 10 septembre 1951',
 'Mme Caroline Cayeux': 'Née le 1er novembre 1948',
 'Mme Catherine Deroche': 'Née le 24 février 1953',
 'Mme Catherine Di Folco': 'Née le 30 novembre 1960',
 'Mme Catherine Génisson': 'Née le 22 avril 1949',
 'Mme Catherine Morin-Desailly': 'Née le 6 juillet 1960',
 'Mme Catherine Procaccia': 'Née le 13 octobre 1949',
 'Mme Catherine Tasca': 'Née le 13 décembre 1941',
 'Mme Catherine Troendlé': 'Née le 20 février 1961',
 'Mme Chantal Deseyne': 'Née le 29 janvier 1957',
 'Mme Chantal Jouanno': 'Née le 12 juillet 1969',
 'Mme Christiane Hummel': 'Née le 8 mai 1942',
 'Mme Christiane Kammermann': 'Née le 10 juillet 1932',
 'Mme Christine Prunaud': 'Née le 4 septembre 1950',
 'Mme Claire-Lise Campion': 'Née le 27 juillet 1951',
 'Mme Claudine Lepage': 'Née le 10 août 1949',
 'Mme Colette Giudicelli': 'Née le 24 novembre 1943',
 'Mme Colette Mélot': 'Née le 20 avril 1947',
 'Mme Corinne Bouchoux': 'Née le 5 janvier 1964',
 'Mme Corinne Féret': 'Née le 17 septembre 1961',
 'Mme Corinne Imbert': 'Née le 20 novembre 1958',
 'Mme Cécile Cukierman': 'Née le 26 avril 1976',
 'Mme Danielle Michel': 'Née le 3 avril 1947',
 'Mme Delphine Bataille': 'Née le 16 septembre 1969',
 'Mme Dominique Estrosi Sassone': 'Née le 14 novembre 1958',
 'Mme Dominique Gillot': 'Née le 11 juillet 1949',
 'Mme Esther Benbassa': 'Née le 27 mars 1950',
 'Mme Evelyne Yonnet': 'Née le 9 octobre 1954',
 'Mme Fabienne Keller': 'Née le 20 octobre 1959',
 'Mme Françoise Cartron': 'Née le 27 mars 1949',
 'Mme Françoise Férat': 'Née le 5 mars 1949',
 'Mme Françoise Gatel': 'Née le 14 mars 1953',
 'Mme Françoise Laborde': 'Née le 8 juillet 1958',
 'Mme Frédérique Espagnac': 'Née le 19 avril 1972',
 'Mme Gisèle Jourda': 'Née le 24 mars 1955',
 'Mme Hermeline Malherbe': 'Née le 18 février 1969',
 'Mme Hélène Conway-Mouret': 'Née le 13 septembre 1960',
 'Mme Isabelle Debré': 'Née le 23 mai 1957',
 'Mme Jacky Deromedi': 'Née le 15 juin 1944',
 'Mme Jacqueline Gourault': 'Née le 20 novembre 1950',
 'Mme Josette Durrieu': 'Née le 20 mars 1937',
 'Mme Joëlle Garriaud-Maylam': 'Née le 20 mars 1955',
 'Mme Karine Claireaux': 'Née le 15 novembre 1963',
 'Mme Lana Tetuanui': 'Née le 23 février 1970',
 'Mme Laurence Cohen': 'Née le 15 janvier 1953',
 'Mme Leila Aïchi': 'Née le 14 mai 1970',
 'Mme Marie Mercier': 'Née le 16 juin 1958',
 'Mme Marie-Annick Duchêne': 'Née le 23 août 1940',
 'Mme Marie-Christine Blandin': 'Née le 22 septembre 1952',
 'Mme Marie-France Beaufils': 'Née le 22 novembre 1946',
 'Mme Marie-Françoise Perol-Dumont': 'Née le 26 mai 1952',
 'Mme Marie-Hélène Des Esgaulx': 'Née le 26 mai 1950',
 'Mme Marie-Noëlle Lienemann': 'Née le 12 juillet 1951',
 'Mme Marie-Pierre Monier': 'Née le 28 février 1958',
 'Mme Maryvonne Blondin': 'Née le 20 janvier 1947',
 'Mme Michelle Demessine': 'Née le 18 juin 1947',
 'Mme Michelle Meunier': 'Née le 24 janvier 1956',
 'Mme Michèle André': 'Née le 6 février 1947',
 'Mme Mireille Jouve': 'Née le 30 décembre 1960',
 'Mme Nathalie Goulet': 'Née le 24 mai 1958',
 'Mme Nelly Tocqueville': 'Née le 2 mai 1950',
 'Mme Nicole Bonnefoy': 'Née le 11 août 1958',
 'Mme Nicole Bricq': 'Née le 10 juin 1947',
 'Mme Nicole Duranton': 'Née le 13 octobre 1958',
 'Mme Odette Herviaux': 'Née le 6 janvier 1948',
 'Mme Pascale Gruny': 'Née le 18 février 1960',
 'Mme Patricia Morhet-Richaud': 'Née le 28 juillet 1961',
 'Mme Patricia Schillinger': 'Née le 18 janvier 1963',
 'Mme Samia Ghali': 'Née le 10 juin 1968',
 'Mme Sophie Joissains': 'Née le 25 octobre 1969',
 'Mme Sophie Primas': 'Née le 6 juin 1962',
 'Mme Stéphanie Riocreux': 'Née le 20 mai 1966',
 'Mme Sylvie Goy-Chavent': 'Née le 23 mai 1963',
 'Mme Sylvie Robert': 'Née le 28 août 1963',
 'Mme Valérie Létard': 'Née le 13 octobre 1962',
 'Mme Vivette Lopez': 'Née le 27 décembre 1954',
 'Mme Éliane Assassi': 'Née le 2 octobre 1958',
 'Mme Éliane Giraud': 'Née le 12 mars 1952',
 'Mme Élisabeth Doineau': 'Née le 7 avril 1961',
 'Mme Élisabeth Lamure': 'Née le 20 novembre 1947',
 'Mme Évelyne Didier': 'Née le 14 mars 1948'}

On peut facilement construire une dataframe pandas avec ces données :

In [17]:
import pandas as pd
In [18]:
df = pd.DataFrame(data=[(key, birthdates[key]) for key in birthdates], 
             columns=('Nom', 'Date de naissance'))
df.head()
Out[18]:
Nom Date de naissance
0 Mme Catherine Génisson Née le 22 avril 1949
1 Mme Anne Chain-Larché Née le 11 avril 1958
2 M. Georges Patient Né le 1er avril 1949
3 Mme Corinne Bouchoux Née le 5 janvier 1964
4 M. Martial Bourquin Né le 23 juillet 1952

On peut, comme dans mon billet précédent, calculer des dates de naissance numériques à l'aide de ces données :

In [19]:
def convert2date(date_str):
    d = {'janvier': 1, 'février': 2, 'mars': 3, 'avril': 4,
         'mai': 5, 'juin': 6, 'juillet': 7, 'août': 8, 
         'septembre': 9, 'octobre': 10, 'novembre': 11, 'décembre':12}
    splits = date_str.split(' ')[2:]
    
    if splits[0].startswith('1er'):
        splits.pop(0)
        splits.insert(0, '1')
    
    return pd.Timestamp(splits[2] + '/' + str(d[splits[1]]) + '/' + splits[0])
In [20]:
df['Date de naissance2'] = df['Date de naissance'].map(convert2date)
In [21]:
df.head()
Out[21]:
Nom Date de naissance Date de naissance2
0 Mme Catherine Génisson Née le 22 avril 1949 1949-04-22
1 Mme Anne Chain-Larché Née le 11 avril 1958 1958-04-11
2 M. Georges Patient Né le 1er avril 1949 1949-04-01
3 Mme Corinne Bouchoux Née le 5 janvier 1964 1964-01-05
4 M. Martial Bourquin Né le 23 juillet 1952 1952-07-23

Enfin, on peut calculer l'âge de chaque sénateur :

In [22]:
import datetime
In [23]:
df['Âge'] = pd.Timestamp(datetime.date.today()) - df['Date de naissance2']
df['Âge (années)'] = [x.days / 365.25 for x in df['Âge']]
In [24]:
df.head()
Out[24]:
Nom Date de naissance Date de naissance2 Âge Âge (années)
0 Mme Catherine Génisson Née le 22 avril 1949 1949-04-22 24379 days 66.746064
1 Mme Anne Chain-Larché Née le 11 avril 1958 1958-04-11 21103 days 57.776865
2 M. Georges Patient Né le 1er avril 1949 1949-04-01 24400 days 66.803559
3 Mme Corinne Bouchoux Née le 5 janvier 1964 1964-01-05 19008 days 52.041068
4 M. Martial Bourquin Né le 23 juillet 1952 1952-07-23 23191 days 63.493498

Analyse des données recueillies

On peut maintenant tracer de jolis histogrammes :

In [25]:
%matplotlib inline
import matplotlib.pyplot as plt
plt.style.use('ggplot')
In [26]:
df['Âge (années)'].hist()
plt.xlabel('âge')
plt.title('histogramme des âges des sénateurs')
Out[26]:
<matplotlib.text.Text at 0x8c08908>

On peut demander à pandas de nous calculer les données statistiques usuelles pour ces âges :

Afin de comparer ces âges à la population française, nous réutilisons le code de mon post précédent :

In [27]:
df_pop = pd.read_excel('http://www.insee.fr/fr/ppp/bases-de-donnees/donnees-detaillees/bilan-demo/fichiers-xls/pop-1janvier-fm.xls',
                      skiprows=7,
                      header=1,
                      skipfooter=3)
In [28]:
decimation_factor = 1000
french_pop_ages = []
for ind, value in enumerate(df_pop['Ensemble']):
    french_pop_ages += [ind for _ in range(int(value / decimation_factor))]
In [29]:
import numpy as np
import statsmodels.api as sm # recommended import according to the docs

age_grid = np.linspace(0, 100)
ecdf_mp = sm.distributions.ECDF(df['Âge (années)'].values)
ecdf_french_pop = sm.distributions.ECDF(french_pop_ages)
y_mp = ecdf_mp(age_grid)
y_french_pop = ecdf_french_pop(age_grid)
plt.step(age_grid, y_mp, label='sénateurs')
plt.step(age_grid, y_french_pop, label='population française')
plt.legend(loc='upper left')
Out[29]:
<matplotlib.legend.Legend at 0xb220a90>

Finalement, on peut passer à la comparaison des statistiques par quartiles :

In [30]:
df['Âge (années)'].describe()
Out[30]:
count    348.000000
mean      62.791947
std        9.050571
min       28.134155
25%       57.147844
50%       63.954825
75%       68.805613
max       90.877481
Name: Âge (années), dtype: float64
In [31]:
pd.Series(french_pop_ages).describe()
Out[31]:
count    64461.000000
mean        40.705931
std         24.080480
min          0.000000
25%         20.000000
50%         41.000000
75%         60.000000
max        105.000000
dtype: float64

Finalement, on peut produire le tableau récapitulatif suivant :

population âge médian âge minimal âge maximal 25% de la population a moins de 50% a moins de 50% a plus de 25% a plus de
les Français 41 ans 0 ans 105 ans 20 ans 41 ans 41 ans 59 ans
les sénateurs français 64 ans 28 ans 91 ans 57 ans 64 ans 64 ans 69 ans

Conclusions

Cette nouvelle analyse consolide l'idée selon laquelle les français sont représentés par des élus dans une tranche d'âge bien éloignée d'une répartition comparable à la population française.

Evidemment, il est difficile de tirer des conclusions générales à partir de ce chiffre, mais il est frappant à quel point les sénateurs sont vieux par rapport disons, l'âge de la retraite. D'une certaine manière, la moitié des sénateurs ont plus que l'âge de la retraite.

Comments