Women Also Know Stuff, édition personnelle 2017/05

La suite de ce billet. Éditions précédentes : 2017/01, 2017/02, 2017/03, 2017/04.
Liste rédigée un peu à la va-vite par manque de temps, mais bonne lecture quand même, et spécial dédicace aux étudiantes de Licence 3 qui m’ont parlé de cette série de billets.

  1. Mary Beard, pour son texte « Death of a dictator. How Caesar’s murder set the template for political assassination ». Voir aussi ce billet de Daniel Little sur le récent ouvrage de Beard, SPQR: A History of Ancient Rome.

  2. Laura Kipnis, pour son texte « Eyewitness to a Title IX Witch Trial ». Son point de vue, provocateur, minoritaire, et superbement écrit, est également évoqué dans cet article de Salon qui évoque aussi Camille Paglia.

    Sur le fond, je n’ai aucune opinion ferme à partager au sujet des questions « trans-genre/ethnicité » évoquées dans l’article qui a suscité la controverse qu’a suivi Kipnis. En revanche, je trouve que le comité éditorial de la revue qui a publié l’article a été d’une lâcheté sans nom. Lisez et décidez par vous-même.

  3. Béatrice Cherrier, déjà mentionnée le mois dernier, au tout début de la série et dans d’autres billets, pour ses epic tweetstorms d’histoire de la pensée économique. S’il fallait n’en lire qu’un, je conseille celui sur William Baumol, auteur très utilisé en économie de la santé.

  4. Substencia, pour ce mix génial, qui commence gentiment mais qui contient aussi quelques passages bien martelés façon Bauhaus/industriel :

  5. Hanna Brooks Olsen, pour ce texte qui explore une perspective que j’utilise très souvent dans mes séances sur les « politiques morales » :

    Abortion is an Economic Issue.

  6. Grete Hermann donne son nom à un package R très intéressant :

    Grete Hermann wasn’t a probabilist, but she wrote the first algorithms for computer algebra; in the 1920s, well before the first electronic computer was built.

    This work laid the foundations for computer algebra libraries (like TensorFlow) that enable modern probabilistic modelling.

  7. Frida Boräng et ses collègues, pour leur article « Cooking the books: Bureaucratic Politicization and Policy Knowledge », qui rejoint tout de suite mon plan de cours sur la sociologie de la quantification et des statistiques officielles1 :

  8. Dawn Johnsen, pour son article « The Lawyers’ War. Counterterrorism From Bush to Obama to Trump ».

  9. Alice Coltrane (1937-2007), très bien chroniquée dans The Quietus. Ci-dessous, le morceau de référence, déjà mentionné il y a trois mois, mais on s’en fiche :

  10. « Older Woman » (qui est assez facile à identifier si vous y tenez), pour son texte « Asking the Wrong Questions about Protest ».

Mention spéciale à Carole Cadwalladr, pour cet article absolument sidérant : « The Great British Brexit Robbery: How our Democracy was Hijacked ». L’article explore le réseau d’élites, militaires et civiles, et de firmes (Cambridge Analytica, Palantir) ayant contribué à façonner, quasiment au sens propre du terme, une large partie de l’opinion publique britannique (mais aussi américaine) lors des votes « Brexit » et « Trump » de l’an dernier.

Le récit est parfaitement édifiant, et si les faits devaient (1) être confirmés et (2) être amenés à se reproduire, ils vont devenir incontournables dans l’étude des élections. Et si l’on rajoute à ça les diverses transgressions russes des dernières années et la géopolitique actuelle autour de la Corée du Nord, alors la Guerre Froide est au moins aussi morte que le punk, c’est-à-dire pas du tout.

  1. Je reparlerai, j’espère, de ce plan de cours dans pas trop longtemps ; si vous êtes curieux, écrivez-moi ou signalez-vous sur Twitter. Et en attendant que je réponde, allez donc lire l’excellent article de Dorothy Kronick, « How to Count Our Dead », sur la mortalité criminelle au Venezuela. []

Séminaire RUSS : Web scraping et APIs avec R

Sur la sympathique invitation de Timothée Giraud, dont je parlais il y a peu, j’interviens après-demain au séminaire RUSS – « R à l’usage des sciences sociales » – co-organisé par l’Ined et par l’EHESS.

Le séminaire a lieu dans le bâtiment Olympes de Gouges de Paris Diderot (salle M19), de 9 heures à midi.

Comme dans d’autres séances de formation telles que celle-ci, il s’agira de voir quels outils permettent de récupérer des données depuis Internet, soit par le biais d’extractions depuis des pages HTML, soit par le biais d’APIs dédiées à la diffusion de données par moyens programmatiques.

Vous avez déjà entendu parler de ces sujets ici : ce blog parle beaucoup de scraping, un peu moins d’APIs—il me semble que la dernière dont j’ai fourni un exemple d’utilisation est celle de Thèses.fr.

Les slides de ma présentation sont disponibles sur le site du séminaire RUSS. En voici un aperçu, que je poste uniquement pour pouvoir montrer ma slide « RTFM » (vers la fin) :

Quasiment toutes les images des slides sont cliquables pour obtenir les sources.

Bonne lecture, et/ou à bientôt si vous êtes inscrit(e) au séminaire !

Women Also Know Stuff, édition personnelle 2017/03

La suite de ce billet. Éditions précédentes : 2017/01, 2017/02. Cette édition contient beaucoup, beaucoup d’analyse de données.

  1. Ann Swidler, dont il est temps, comme l’a fait remarquer Kieran Healy, de relire le classique « Culture in Action: Symbols and Strategies » :

    swidler-culture-in-action

  2. J’ai déjà cité, dans l’édition 2017/01, Jennifer Bryan, pour ses slides sur la manipulation de données, et avant ça, j’avais cité, dans l’édition 2016, Julia Silge, pour l’ouvrage Tidy Text Mining qu’elle co-écrit avec David Robinson.

    En janvier, j’ai suivi de loin la première RStudio Conference via Twitter, et la forte présence féminine lors de la conférence m’a semblé faire partie de ses points forts. Jenny Bryan et Julia Silge en étaient, et l’on peut aussi mentionner Hilary Parker (lisez ses slides), Hilary Mason (qui a le meilleur t-shirt du monde), Amelia McNamara et Charlotte Wickham, qui a présenté une excellente démo de programmation fonctionnelle avec le package purrr.

    La forte présence féminine à la conférence ne doit pas grand chose au hasard : il y a une task force qui travaille sur le sujet, et des initiatives dans la communauté R.

  3. Meredith Monk, « Dawn », sur l’album Book of Days (1990) :

  4. Aperçue dans une autre conférence que celle citée plus haut, Haley Jeppson, qui a repris le flambeau du package productplots avec ggmosaic :

  5. Je reviendrai sur cette série d’entretiens, mais voici le sixième épisode de la série « DataChats », avec la statisticienne Jo Hardin, qui présente son cours sur le bootstrapping :

    … série dans laquelle on retrouve, à nouveau, Charlotte Wickham, qui y présente un cours de manipulation de données spatiales.

  6. Björk, « Unravel » (1997) ; la version jouée avec le Brodsky Quartet est ma favorite, mais le clip de l’originale est plus esthétique :

  7. Alice Bartlett, « Git for Humans » :

    git-for-designers

    Et sur le même thème, voir, à nouveau, Jenny Bryan et al., Happy Git and GitHub for the useR.

  8. Bonnie Stabile, pour son papier « Reproductive Policy and the Social Construction of Motherhood » :

    Findings. Women’s choices fell within social construction quadrants as being positively portrayed and powerful; negatively portrayed but powerful; positively portrayed but powerless; and negatively portrayed and powerless. Married heterosexual women embracing motherhood were likely to be viewed positively and to reap benefits. Women forgoing motherhood, poor women, and women seeking to form nontraditional families were likely to be viewed negatively and to bear burdens; critical among these burdens was restriction of access to technologies that could be used to support a decision to avoid motherhood or to achieve motherhood through nontraditional methods.

  9. Melt-Banana (Yasuko Onuki au chant, Ichirou Agata au reste), « Last Target On The Last Day », dernier morceau de l’album Bambi’s Dilemma (2007), ci-dessous en version live à Tokyo (2009) :

  10. Julia Lynch a formulé un point de vue que je rumine depuis longtemps :

    Medicalizing inequality is more appealing to most politicians than tackling income and wage inequality head-on, but it results in framing the problem of social inequality in a way that makes it technically quite difficult to solve. Policy-makers should consider adopting more traditional programs of taxation, redistribution and labor market regulation in order to reduce both health inequalities and the underlying social inequalities.

Mention spéciale : Mica Levi, pour l’intégralité de la bande originale du film Under the Skin. La bande-son, dont un extrait suit, est plus intéressante que le film lui-même, et devrait vous plaire si vous avez aimé la bande-son de Donnie Darko, par exemple.

Notes de travail sur les réseaux de collaboration législative

J’ai eu la chance d’intervenir, il y a dix jours, dans le séminaire interne du CEVIPOL, le laboratoire de science politique de l’Université Libre de Bruxelles. J’étais invité par Émilien Paulis, que je remercie au passage pour l’invitation, pour la logistique et pour l’accueil sur place.

Mon intervention portait sur l’étude des réseaux de collaboration législative. Les slides que j’ai utilisées sont proches de celles que j’avais présentées en juin 2016 dans une conférence d’utilisateurs de R, et que j’ai présentées à nouveau cette même année dans une conférence « quanti » à Lille et dans le séminaire du Médialab de Sciences Po.

Quelques extraits ci-dessous, à cliquer pour obtenir les slides au complet :

De Google My Maps à ggplot2 en quelques secondes

J’avais brièvement évoqué, en juin dernier, la version 1.0.0 du package R xml2, qui permet de lire du XML dans R en permettant d’y mobiliser la librairie libxml. Voici un petit bricolage basé sur cette chaîne d’outils.

Les données : Google My Maps

Au hasard d’une recherche sans rapport avec le schmilblick, je suis tombé sur cette carte des morts violentes à Barbès et à la Goutte d’Or. La carte a été réalisée par Jean-Raphaël Bourge, qui fait un superbe travail de recherche sur le quartier.

En fouillant un peu, j’ai également retrouvé cette carte des églises africaines qui font leur publicité à la Goutte d’Or. La carte a été réalisée par Baptiste Coulmont, qui a amplement documenté le phénomène, et qui a publié un très chouette article sur le sujet.

Enfin, en creusant encore un peu, je découvre une autre carte : « Gangs of Los Angeles« , et son complément sur les gangs hispaniques. Les graffiti que laissent les gangs de Los Angeles font l’objet d’une recension aussi systématique que possible sur Instagram, et il existe des tonnes de cartes très détaillées des territoires de ces gangs1.

Le problème : KML et ggplot2

Je me suis demandé comment je pouvais réutiliser les données de ces cartes. Google My Maps est un outil très pratique qui peut être utilisé sans compétence technique par un nombre illimité d’utilisateurs, ce qui en fait un excellent support pour le recueil de données géolocalisées ; mais comment réexploiter ces données ?

Google My Maps permet d’exporter les informations d’une carte au format KML, ce qui est pratique, mais l’utilisation de ces données par des outils tels que les packages R rgdal ou sf n’est pas facile, surtout si l’on souhaite utiliser les packages du « tidyverse » (dyplr et ggplot2 en particulier) pour manipuler les données et les visualiser.

La solution (limitée) : tidykml

Histoire de passer rapidement d’un fichier KML à un jeu de données qui puisse être utilisé avec ces packages, j’ai codé un petit package, tidykml, qui importe les éléments KML les plus simples (les géométries de base et leurs métadonnées). Tous les détails sont dans le README du package, et voici un exemple de résultat :

gangs

Le package est très limité : il ne gère pas les « géométries multiples » (les multi-polygones qui permettent de visualiser des îles, par exemple), et il n’a été testé que sur les cartes listées plus haut, plus quelques autres exemples de cartes issues de Google My Maps. En attendant mieux, le package permet de réaliser des cartes comme celle-ci :

sherman

L’exemple ci-dessus, qui ne demande que quelques lignes de code dont la plupart sont des réglages graphiques réalisés dans ggplot2, apparaît également dans ce billet en anglais, un peu plus technique.

Pour aller plus loin

Mon objectif, avec tidykml, était de raccourcir autant que possible le code allant de l’import d’un fichier KML à un graphique réalisé avec ggplot2, histoire de faciliter la réutilisation de données Google My Maps sur d’autres supports, et sans passer par des solutions de cartographie plus sophistiquées.

Pour aller plus loin, il faudrait avant tout que je trouve un moyen de prendre en compte les « géométries multiples » évoquées plus haut, et aussi que je documente l’énorme répertoire d’outils cartographiques pour R, comme par exemple l’excellent package cartography de Timothée Giraud et al..

Pas d’empressement toutefois : les outils de cartographie avec R sont en discussion et pourraient évoluer de manière à rendre mon package obsolète dans les mois à venir. Tant mieux.

  1. Voir notamment cette conversation sur Reddit. []

Collecte et visualisation de données législatives avec R

Le groupe d’utilisateurs R du Muséum national d’Histoire naturelle de Paris (le groupe “Sémin-R”) organise une conférence R demain. Cliquez sur l’image ci-dessous pour le programme complet :

JourneeR-2016-Programme

J’y présenterai les slides résumées ci-dessous (cliquez sur n’importe quelle image pour la version PDF complète, ou utilisez la version en ligne), et si tout se passe bien, j’aurai un court papier technique à partager sur le sujet dans moins d’un mois :

Briatte_R_MNHN_2016-2

Briatte_R_MNHN_2016-3

Briatte_R_MNHN_2016-4

La présentation reprend, en substance, une brève note que j’ai récemment publiée dans Network Science. Cliquez sur l’image ci-dessous pour accéder au preprint ou lisez directement son annexe pour le détail des données :

Briatte_NWS_published

Comme d’habitude, le code et les données sont en ligne — j’en ai déjà parlé à plusieurs occasions cette année, et vous risquez d’en entendre encore parler dans les années qui arrivent (plus de détails quand il y en aura à partager).

Affaire à suivre, donc, mais bon, c’est pas comme si je ne vous avais pas déjà un peu cassé les pieds avec R et la visualisation de réseaux de collaborations législatives depuis quelques temps déjà.

J’en profite pour saluer amicalement les collègues suisses, et Marion Deville en particulier, qui participent à la Semaine de la démocratie de Genève, et qui ont prévu d’utiliser certains de mes graphiques dans une présentation de leurs travaux lors d’un hackathon organisé le 23 septembre. Je n’ai pas beaucoup plus d’informations là-dessus, mais vous pouvez écrire à Marion si vous êtes intéressés.

En attendant, il reste quelques places pour la conférence de demain : écrivez aux gentils organisateurs (leurs coordonnées sont sur le site du Sémin-R), ou faîtes-moi très vite signe, et je ferai suivre. À demain !

Mise à jour, le jour même : malgré un léger gros problème qui m’a fait rater la matinée, je peux confirmer que la journée R du MNHN était, comme prévu, hyper-chouette, le cadre du Muséum d’Histoire Naturelle étant très agréable par ailleurs.

À noter dans les présentations, qui seront bientôt en ligne sur le site du RUG MNHN :

  • les dernières améliorations du package FactoMineR – et Factoshiny
  • l’utilisation de scripts R sur un serveur Apache
  • la visualisation de cartes auto-organisatrices
  • un exemple d’interfaçage R + Java
  • la sonification (!) de graphiques R/ggplot2

La dernière présentation, par Jérôme Sueur (l’un des deux organisateurs de la journée, avec Amandine Blin) était très divertissante. Pour comprendre pourquoi, jetez un coup d’oeil au package playitbyr.

Notes sur R et l’analyse de réseaux

Comme promis la semaine dernière, nouvelle annonce qui consacre mes deux obsessions pour la programmation statistique avec R et l’analyse de réseaux, toujours avec R :

r-notes

Le blog est syndiqué sur R-Bloggers, qui agrège plein de blogs sur R. Vous pouvez aussi vous y abonner par son flux Atom ou par son flux RSS.

Le moteur du blog est une version bidouillée de Dropplets.

Quelques notes déjà rédigées

J’ai commencé ce nouveau blog pour stocker des notes dont je suis le premier utilisateur, notamment sur les sujets suivants :

Je me suis aussi servi du blog pour documenter des résultats bizarres, faire des suggestions sur l’enseignement avec RStudio, et tenter des petites expériences avec jQuery, telles que celle-ci avec l’API Pinboard.

Il s’agit vraiment de notes plus que d’un blog : tout est rédigé dans un jargon pas très amusant, et il n’y a pas de commentaires, ni même de lien évident pour me contacter — d’où cette nouvelle publication en dehors du ‘bistro.

Dernière petite chose, vous pouvez désormais apercevoir les derniers billets du Polit’bistro et de R / Notes sur ma homepage universitaire, encore une fois grâce à jQuery, et plus précisément grâce au plugin FeedEk, qui permet de récupérer des contenus de fils RSS :

blogs-rss-feedek

Pour les fans, il y a aussi un peu de jQuery (avec beaucoup de JavaScript et un peu d’animations CSS3) sur la page où j’héberge ma frimousse.

Bonne(s) lecture(s) !

Notice technique, illustrée par la communication officielle du Front national

Suite aux séries de billets sur les “unes” de Charlie Hebdo, les revues de la sociologie française et les réseaux législatifs, j’ai reçu quelques emails – merci ! – me demandant de réexpliquer “la base” du truc :

  • comment est-ce que l’on fait pour récupérer les données ?
  • comment est-ce que l’on fait pour en sortir un réseau ?

Je vais prendre un petit exemple facile pour illustrer le principe : comment récupérer la communication officielle du Front national à partir de son site Internet, et comment en extraire un réseau de co-occurrences.

Pour cet exemple, je suppose que vous connaissez un minimum de langage HTML. Si ce n’est pas le cas, vous aurez besoin d’une semaine au maximum pour apprendre tout ce qu’il faut savoir. Le langage HTML servant à “écrire Internet”, c’est aussi le langage le mieux documenté sur Internet : commencez ici, par exemple.

Les outils

Commençons par la base.

Il vous faudra une bonne connexion Internet : idéalement de la fibre optique, mais plus généralement, une connexion qui ne va pas tomber en rade et rajouter des erreurs de téléchargement dans une procédure qui risque déjà d’en générer par elle-même. Votre connexion Ethernet universitaire, qui est probablement filtrée d’une manière ou d’une autre, n’est peut-être pas la candidate idéale ; le wifi de votre université, encore moins.

Ensuite, il vous faut un peu d’espace disque. Utiliser un disque externe pour télécharger des centaines de fichiers est une très mauvaise idée : la moindre erreur d’écriture peut envoyer l’intégralité du disque dans les Limbes. L’idéal est d’utiliser une clé USB pas chère mais de bonne qualité, histoire que le disque dur ne soit jamais menacé. Si votre disque dur est un SSD, le risque de le foutre en l’air est toutefois minime.

Enfin, il vous faut un langage de programmation, et si possible, un langage qui va vous permettre d’enchaîner les opérations (téléchargement, visualisation, modélisation) de manière fluide. J’utilise R, mais Python est un autre bon candidat. R est bien documenté, bien illustré, la communauté répond vite et bien aux questions, et les toutes dernières techniques de modélisation y sont très bien représentées.

Il est vivement conseillé d’utiliser RStudio pour coder en R. Il vous faudra aussi un navigateur Internet avec une interface de développement intégrée, pour visualiser le code source des pages HTML que vous voulez récupérer : Chrome, Firefox, Opera ou Safari feront l’affaire.

Les packages

Quel que soit votre choix de langage, vous allez devoir vous servir d’extensions pour accomplir les différentes opérations dont vous avez besoin. Pour ce petit exemple, on va utiliser les cinq packages R suivants :

  • rvest, pour récupérer les données
  • lubridate, pour en convertir les dates
  • stringr, pour manipuler les données textuelles
  • dplyr, pour manipuler les données
  • ggplot2, pour visualiser les données

Incidemment, tous ces packages ont été développés par la même personne, avec l’aide de plusieurs autres.

On rajoutera quelques packages quand on en arrivera à l’étape “réseaux”.

La source

Toutes les donnés que l’on va récupérer proviennent de la section “Actualités” du site Internet frontnational.com. La structure de l’information qui s’y trouve est régulière : la section contient une suite d’articles qui appartiennent à une ou plusieurs catégories, avec parfois un ou plusieurs mots-clés supplémentaires. Chaque article possède un titre, qui renvoie à une page individuelle, et une date, exprimée en français :

Screen Shot 2015-03-15 at 12.58.52

Jetez à présent un coup d’oeil à la source HTML de la page “Actualités” avec les Developer Tools de votre navigateur (j’utilise ceux de Chrome) : en quelques clics et recherches par mots-clés, vous allez y trouver le code HTML qui structure l’information. Ici, les articles de la page se trouvent dans le diviseur #pk_content, les titres des articles sont codés comme des titres de niveau 3 de classe .pk_entry_title, et chaque titre fait l’objet d’un lien a :

Screen Shot 2015-03-15 at 13.06.58

Vous savez à présent ce que vous allez chercher dans chaque page. Dernière étape : combien de pages va-t-on récupérer ? Le système de pagination du site est ultra-simple à identifier :

Screen Shot 2015-03-15 at 13.19.13

Chaque page est numérotée de 2 à X, l’adresse étant de type /actualites/page/4, par exemple. La page finale est identifiable par essai-erreur : si vous essayez d’accéder à la page /actualites/page/200, vous obtenez une erreur. Cherchez un peu, et vous allez trouver qu’à l’heure actuelle, il y a 179 pages qui vous ramènent jusqu’à l’actualité du Front national en avril 2013—soit presque deux ans de données.

Le code

Pour récupérer les titres, liens, dates, catégories et mots-clés de tous les articles de la section “Actualités” du site Internet du Front national :

  1. On crée une boucle qui va de 179 à 1 ;
  2. On télécharge la page correspondant à cette valeur ; et
  3. On extrait ces informations de la page.

La base du truc ressemble à ça :

for(i in 179:1) {

  # l'adresse de la page sur le site Internet
  p = paste0("http://www.frontnational.com/actualites/page/", i)

  # le nom de fichier de la page téléchargée
  f = paste0("page", i, ".html")

  # télécharger la page si le fichier est absent
  if(!file.exists(f))
    download.file(p, f, mode = "wb", quiet = TRUE)

}

La condition if(!file.exists(f)) permet de relancer le code en cas d’erreur—mais il n’y en aura pas dans cet exemple : le site ne pose pas de souci, et ma connexion Internet n’en a pas posé non plus.

On dispose à présent de toutes les pages HTML de la section “Actualités”, et à chaque itération, l’adresse du fichier de la page est stocké dans la variable f. Pour extraire les informations de cette page :

# lire la page
h = html(f)

# extraire le lien de chaque article
url = html_nodes(h, "#pk_content h3.pk_entry_title a") %>% 
  html_attr("href")

# extraire le titre de chaque article
title = html_nodes(h, "#pk_content h3.pk_entry_title a") %>% 
  html_text()

# extraire les dates, catégories et mots-clés
meta = html_nodes(h, ".pk_entry_meta p") %>% 
  html_text()

On utilise ici les fonctions du package rvest. Rapide explication de texte :

  • Les deux premiers appels de la fonction html_nodes extraient les titres ;
  • html_attr("href") en extrait le lien individuel, html_text() en extrait le titre; et
  • l’opérateur %>% permet d’enchaîner les opérations de manière lisible

Cette syntaxe est une simplification de la syntaxe XPath, qui sert à parcourir les documents XML, dont font partie les documents HTML. Le package XML permet de faire la même chose, mais de manière moins lisible.

On obtient trois différentes variables textuelles à partir de ces opérations :

  • La variable url va contenir des liens de ce type :
    [1] "http://www.frontnational.com/2015/03/lettre-ouverte-de-marine-le-pen-aux-acteurs-des-politiques-du-handicap/"                              
    [2] "http://www.frontnational.com/2015/03/document-de-campagne-departementales-22-et-29-mars-2015/"                                             
    [3] "http://www.frontnational.com/2015/03/lettre-de-marine-le-pen-a-lattention-de-monsieur-olivier-schrameck-president-du-csa/"
  • La variable title va contenir des titres :
    [1] "Lettre ouverte de Marine Le Pen aux acteurs des politiques du handicap"                                
    [2] "Document de campagne départementales 22 et 29 mars 2015"                                               
    [3] "Lettre de Marine Le Pen à l’attention de Monsieur Olivier Schrameck, Président du CSA"
  • La variable meta va contenir le reste :
    [1] "13 mars 2015/Tribunes libres/Mots-clefs: Handicap"                          
    [2] "12 mars 2015/Annonces/Mots-clefs: Départementales 2015"                     
    [3] "12 mars 2015/Tribunes libres/Mots-clefs: CSA, Injures"

La dernière variable contient plusieurs informations, il va donc falloir un peu plus de code pour la séparer dans ses différents éléments :

  • On commence par extraire le texte de la date à partir d’une expression régulière qui en repère l’année (élément \\d{4}, qui cherche quatre chiffres consécutifs), puis on la convertit du format français “jour mois année” vers un format générique :
    date = str_extract(meta, "(.*)\\d{4}/")
    date = parse_date_time(str_sub(date, end = -2), 
                           "%d %B %Y", locale = "FR_fr")
    date = as.Date(date)
  • On extrait ensuite la ou les catégorie(s), qui se situent toujours après le premier caractère / de la variable meta (c’est-à-dire après la date). Pour ce faire, on utilise le caractère / pour diviser la variable en plusieurs petits bouts de texte, et l’on sélectionne le second :
    category = sapply(str_split(meta, "/"), function(x) x[2])
  • Enfin, on répète l’opération pour le bloc de texte correspondant aux mots-clés, en prenant soin de virer le texte dont on n’a pas besoin au passage. Il n’y pas toujours de mots-clés : on se prémunit donc contre cette possibilité en prévoyant la possibilité d’une variable manquante NA.
    tags = sapply(str_split(meta, "/"), function(x) {
      x = x[ grepl("Mots-clefs", x) ]
      x = gsub("Mots-clefs: ", "", x)
      ifelse(length(x), x, NA)
    })

En mettant toutes ces opérations à la chaîne, et en stockant les informations que l’on extrait dans un jeu de données, on arrive à 42 lignes de code qui collectent 3 581 liens et titres d’articles de la source. Tous les articles sont catégorisés, mais 728 d’entre eux n’ont pas de mots-clés.

Visualisation hyper-basique

Cherchons à visualiser un aspect très simple du corpus : qui parle au nom du Front national auprès des médias, et dans quelles proportions ?

Pour cela, on retient les 977 articles qui appartiennent à la catégorie “Médias”, et l’on extrait les noms des intervenants, encore une fois à l’aide d’une expression régulière1. L’expression en question est élaborée en jetant un rapide coup d’oeil aux titres des articles, et en rassemblant leurs intervenants dans une même expression un peu longue :

"Marine (L|l)e Pen|Marion( |-)Maréchal|Nicolas Bay|Gollnisch|F(l)?(orian|\\.) (P|p)hilippot|Louis Aliot|Steeve Briois|Sébastien Chenu|Stéphane Ravier|Thibault de la Tocnaye|Wallerand de Saint( |-)Just|Marie-Christine Arnautu|Bousquet-Cassagne|Gilbert Collard|Julien Sanchez|Julien Rochedy|Jean-Marie Le Pen|Lacoste-Lareymondie|Philippe Murer|Sophie Montel|Laurent Lopez|Gaëtan Dussausaye|David Rachline|Bernard Monot|Aymeric Chauprade|Michel Guiniot|Edouard Cavin|Jean-Claude Otto-Bruc|Dominique Martin"

Cette expression repère tous les intervenants, et ne laisse que 16 articles sans intervenants de côté.

Il ne reste plus qu’à visualiser la quantité d’articles produites par le Front national pour sa catégorie “Médias” entre avril 2013 et aujourd’hui, en coloriant les articles par les noms des intervenants, et après avoir regroupé les intervenants avec moins de 10 articles (seuil arbitraire) dans une catégorie résiduelle. Ce qui nous donne :

fn_medias_bars

Florian Philippot est en brun, et Marine Le Pen est en bleu (clair). Je vous promets que je n’ai pas choisi les couleurs : il s’agit des couleurs par défaut de l’excellent ggplot2.

Un dernier petit coup d’oeil, pour terminer, aux mois qui ont donné le plus d’articles, et aux intervenants de ces articles. Cette fois-ci, on utilise les fonctions du package dplyr pour agréger le corpus (objet m) par mois (variable ym) et par intervenant (variable who2), puis pour compter “leurs” articles, puis pour voir les dix premiers mois classés par nombre d’articles :

filter(m, who2 != "(autres)") %>% 
  group_by(who2, ym) %>% 
  summarise(n = n()) %>% 
  group_by() %>% 
  arrange(-n)

Ce qui nous donne Florian Philippot et Marine Le Pen en tête, et très loin devant le reste du peloton. Leurs mois d’activité médiatique les plus intenses correspondent aux élections municipales de mars 2014 et à la formation du premier gouvernement Valls :

1  florian philippot  2014-5 27
2      marine le pen  2014-3 23
3  florian philippot 2013-10 21
4  florian philippot  2015-2 20
5  florian philippot 2014-11 19
6  florian philippot  2013-6 18
7  florian philippot  2015-1 18
8  florian philippot 2014-12 17
9      marine le pen  2013-9 17
10 florian philippot 2013-12 16

Enfin, si l’on répète l’opération avec la catégorie “Interventions”, on trouve les députés Gilbert Collard et Marion Maréchal-Le Pen en tête de cortège, suivis des eurodéputés frontistes, mais sur des quantités moindres (il n’y a que 336 articles, soit trois fois moins de données) et plus irrégulières :

fn_interventions_bars

Pour reproduire ces résultats, allez voir le code, il y en a pour même pas 100 lignes.

Visualisation en réseau

Revenons sur la totalité du corpus. Ce corpus contient 3 581 articles constituant les “actualités” du Front national, et 80% des articles possèdent des mots-clés. Il y a 699 mots-clés différents dans le corpus. Voici les premiers d’entre eux, qui apparaissent plus de 100 fois dans le corpus, c’est-à-dire dans plus de 3% des articles possédant des mots-clés :

Européennes 2014 118
Immigration      133
Insécurité       102
Islam radical    111
Municipales 2014 261
Paris            150
Valls            122

Aucune surprise. Voyons à présent quelles associations de mots-clés reviennent fréquemment dans ce corpus.

Première étape : créer un jeu de données à deux colonnes, où chaque ligne contient une association de deux mots-clés conjointement présents sur un même article. En langage réseau, ça s’appelle une edge list non dirigée, et en langage R, ça peut se construire comme ça, à partir de la variable b$tags contenant les mots-clés de chaque article :

# associations de mots-clés dans chaque article
e = lapply(b$tags, function(x) {
  
  y = unique(unlist(strsplit(x, ",\\s?")))
  y = expand.grid(i = y, j = y, stringsAsFactors = FALSE)
  y = filter(y, i != j)
  y = apply(y, 1, function(x) paste0(sort(x), collapse = "///"))
  y = unique(y)
  data.frame(i = gsub("(.*)///(.*)", "\\1", y),
             j = gsub("(.*)///(.*)", "\\2", y),
             stringsAsFactors = FALSE)
  
})

# assemblage des associations en une seule liste
e = bind_rows(e)

# pondération de chaque association par sa fréquence
e = group_by(e, i, j) %>% summarise(n = n())

Pour la suite, il va nous falloir utiliser le package network pour convertir cette liste en objet “réseau”, auquel on va rajouter la pondération de chaque association de mots-clés, c’est-à-dire la fréquence de chacune de ces associations dans le corpus, que l’on a calculée à la toute fin du bloc de code précédent :

n = network(e[, 1:2 ], directed = FALSE)
set.edge.attribute(n, "weight", e[, 3])

Bon, à ce stade, on a le réseau complet des co-occurrences de mots-clés dans les articles “Actualités” du site du Front national, d’avril 2013 à aujourd’hui. Ça fait beaucoup, ce dont on peut se rendre compte en visualisant le réseau à l’état brut. On produit cette visualisation avec la fonction ggnet, dont on a déjà parlé :

fn_network_0

L’épaisseur des liens entre deux mots-clés est ici proportionnelle à leur fréquence d’apparition dans le corpus, simplifiée en cinq catégories correspondant à des fréquences d’associations de 1 (co-occurrence unique), 2, 3, 4 et 5 ou plus. Le code de visualisation ressemble à ça :

# diviser les co-occurrences en 5 catégories : 1, 2, 3, 4 et 5+
w = as.numeric(cut(e[, 3], c(0, 1, 2, 3, 4, Inf)))
w = w / max(w)
# visualiser le réseau complet en faisant varier l'épaisseur des liens
ggnet(n, size = 1,
  segment.color = "black",
  segment.alpha = .5,
  segment.size = w)

Ce que l’on voit au centre, ce sont les associations de mots-clés qui reviennent fréquemment ; ce que l’on voit en périphérie, ce sont les associations de mots-clés beaucoup moins fréquentes. Concentrons-nous sur le centre en ne retenant que les associations de mots-clés apparaissant au moins cinq fois dans le corpus :

# sous-réseau des co-occurrences de fréquence 5+
nn = n
delete.edges(nn, which(w < 1))
delete.vertices(nn, isolates(nn))

ggnet(nn, size = 1,
      segment.alpha = .5, segment.color = "black",
      label.nodes = TRUE,
      label.size = 3 * as.numeric(cut(degree(nn), unique(quantile(degree(n))), 
                                      include.lowest = TRUE)))

On a ici rajouté le nécessaire pour faire apparaître les mots-clés en question, et pour leur donner une taille proportionnelle au nombre d’associations dans lesquelles ils apparaissent. Le résultat ne va pas non plus vous étonner :

fn_network_5

Visualisation animée

On introduit à présent un dernier package, animation, qui va nous permettre de montrer le réseau de co-occurrences de mots-clés à chaque étape de l’affinage entre le réseau complet, qui montre toutes les co-occurrences, jusqu’à la dernière, c’est-à-dire la co-occurrence de mots-clés la plus fréquente du corpus.

Le code ressemble à ce que l’on a déjà vu, mais dans une boucle qui élimine progressivement les associations de mots-clés les moins fréquentes :

# animation
saveGIF({
  
  w = sort(unique(e[, 3]))
  for(i in w[ -length(w) ]) {
    
    nn = n
    delete.edges(nn, which(e[, 3] <= i))
    delete.vertices(nn, isolates(nn))
    
    g = ggnet(nn, size = 0,
              segment.alpha = .5, segment.color = "black",
              label.nodes = TRUE,
              label.size = 3 * as.numeric(cut(degree(nn), 
                                              unique(quantile(degree(n))),
                                              include.lowest = TRUE))) +
      ggtitle(paste("Associations apparaissant au moins", i, "fois"))
    
    print(g)
    
  }
}, movie.name = "fn_network.gif", interval = 1)

Ce qui nous donne une suite de réseaux de plus en plus “vides”, où les mots-clés “Taubira” et “Paris” ont une assez longue durée de vie, et où les mots-clés “Paris” et “insécurité” survivent jusqu’en fin de chaîne :

fn_network

Voici le code complet de la partie “réseaux”.

Bilan technique

Dans ce billet, on a utilisé :

  • R et tout plein de packages R
  • Un navigateur Internet
  • De la syntaxe HTML et XPath
  • Des expressions régulières2
  • Un tout petit peu d’analyse de réseaux

Toutes ces technologies sont gratuites et bien documentées.

Le corpus “Actualités du Front national” a servi d’exemple parce qu’il ne présentait que des difficultés minimales, qu’il ne m’a fallu que quatre minutes pour le télécharger, et que je ne comptais en présenter que des aspects très simples. Je n’ai même pas téléchargé les articles complets, par exemple, ni envisagé leur analyse textuelle.

Les exemples que je montre sur ce blog sont souvent plus larges : le corpus des revues et articles de la plateforme Cairn.info, par exemple, que j’ai utilisé pour parler des revues de sociologie, contient plus de 400 revues et à peu près 20 000 articles. Mais la logique de base reste proche de celle détaillée ci-dessus.

Mise à jour, 18 décembre 2015 : le Front national ayant légèrement modifié les réglages de son serveur, il faut désormais faire semblant d’utiliser un navigateur pour accéder à son site Internet de manière programmatique. Le code de ce billet a été mis à jour pour ce faire, ce qui permet au passage d’étendre les données jusqu’à décembre 2015, soit 228 pages d’actualités contenant 1 329 interventions de représentants du Front national dans les médias.

Le Canard enchaîné de cette semaine s’est par ailleurs fait le relais des conflits internes au Front national qui opposent Florian Philippot aux soutiens de Marion Maréchal-Le Pen, une source indiquant à cette occasion que Nicolas Bay était de plus en plus envoyé dans les médias par le parti pour infléchir la représentation de ce dernier par Florian Philippot.

On peut vérifier cette affirmation de plein de manières, mais l’on se contentera ici de la plus simple, qui consiste à calculer, à partir de notre source (le seul site Internet du Front national), le pourcentage d’interventions médias du Front national représenté par Florian Philippot. Les barres en rouge indiquent les mois d’élection (municipales, européennes, départementales et régionales), et l’on a retiré les mois de juillet/août pour ne pas inclure de ratios calculés sur des petits dénominateurs :

fn_medias_philippot_bars_updated

Ce graphique permet de constater qu’avec moins d’une invention média sur cinq, Florian Philippot est effectivement à son plus bas taux de représentation médiatique du Front national en décembre 2015. Une diminution similaire était observable au moment des élections municipales. Jugé sur le même critère, Nicolas Bay reste une figure moins médiatique du parti sur la période observée, sauf justement à quelques occasions, dont le mois de décembre 2015 :

fn_medias_bay_bars

Je profite de cette mise à jour pour signaler que Joël est apparu dans l’émission Envoyé spécial du 17 décembre 2015, pour parler justement de Marion Maréchal-Le Pen.

  1. Attention, celle-ci n’extrait que le premier intervenant : s’il y en a plusieurs, le deuxième passe à la trappe. Il n’y a que cinq articles où le problème se pose. []
  2. Alexandre fait remarquer qu’on devrait les appeler “expressions rationnelles”. S’il vous faut d’autres exemples, en voici quelques-uns. []

Extraire un réseau de coauteurs depuis la base PubMed

La base MEDLINE contient environ 23 millions d’articles scientifiques, accessibles via le moteur de recherche PubMed depuis une vingtaine d’années. Ces articles sont utilisés pour toutes sortes d’analyse, des méta-analyses aux analyses de communautés sémantiques. La base PubMed, c’est très littéralement du big data, et les chercheurs comme les entreprises le savent depuis un bail1.

Le sujet vous donne une idée de ce que je vais faire de mes vacances, mais la phase données devrait être indolore : MEDLINE est une base extrêmement bien entretenue, et les opérations ci-dessous font moins saigner des yeux que, par exemple, au hasard (p < .0001), les fichiers du Ministère de l’Intérieur. De plus, on va travailler sur des requêtes précises plutôt que sur la base intégrale.

Allez découvrir PubMed si vous n’avez jamais fait un tour, c’est un tour de force du point de vue de la science archivistique et documentaire, et un fleuron discret de la médecine scientifique contemporaine, “basée sur les preuves” (id est publiée dans une revue scientifique avec un impact factor aussi élevé que possible ; pour les preuves, la maison demande un délai d’environ quinze années supplémentaires) :

Screen Shot 2014-06-14 at 5.26.38 PM

Télécharger une requête PubMed

Les articles en accès ouvert via PubMed Central (PMC) sont facilement téléchargeables depuis un serveur FTP, mais pour obtenir les résultats d’une requête sur la base intégrale, c’est un peu plus long. Heureusement, grâce à Kristoffer Magnusson, il y a ce bout de code vieux de deux ans, qui méritait un petit remix.

La première étape consiste à envoyer une requête PubMed du même type que celle que l’on rentre dans le moteur de recherche en ligne2, et à récupérer en retour un fichier XML qui contient la requête développée en plusieurs mots-clés, après vérification de leur disponibilité dans les mots-clés du thesaurus MeSH (Medical Subject Headings) de la National Library of Medicine. La requête health (inequalit*) donne ainsi :

("health"[MeSH Terms] OR "health"[All Fields]) AND (inequalites[All Fields] OR inequaliti[All Fields] OR inequalities[All Fields] OR inequalities'[All Fields] OR inequalitiies[All Fields] OR inequalitiy[All Fields] OR inequality[All Fields] OR inequality'[All Fields] OR inequality's[All Fields] OR inequalityin[All Fields] OR inequalitys[All Fields])

Mais vous avez plutôt intérêt à formuler la requête health AND (inequality or inequalities), qui va identifier les mots-clés correspondant à l’entrée MeSH consacrée aux facteurs socio-économiques, le nom donné par PubMed aux recherches sur les inégalités de santé. La requête devient alors, sans l’antislash de formatage3 :

("health"[MeSH Terms] OR "health"[All Fields]) AND \(("socioeconomic factors"[MeSH Terms] OR ("socioeconomic"[All Fields] AND "factors"[All Fields]) OR "socioeconomic factors"[All Fields] OR "inequality"[All Fields]) OR ("socioeconomic factors"[MeSH Terms] OR ("socioeconomic"[All Fields] AND "factors"[All Fields]) OR "socioeconomic factors"[All Fields] OR "inequalities"[All Fields]))

Le nombre total d’articles correspondant à la requête se trouve dans le même fichier XML et ne demande que peu d’efforts pour être récupéré, mais c’est surtout le “numéro unique” de la requête qui va nous intéresser : la variable NCID est une chaîne unique qui permet de récupérer les résultats de notre recherche (métadonnées et résumés des articles) sans se fatiguer, une fois placée dans une boucle récupérant n articles k fois.

C’est la seconde et dernière étape : en quelques lignes, on écrit une boucle de téléchargement qui demande les mille premiers articles PubMed correspondant à la requête, qu’on sauvegarde dans un fichier XML, puis les mille suivants, et ainsi de suite. Un fichier XML, c’est du contenu entouré de balises de marquage sémantique, comme dans cet exemple :

Screen Shot 2014-06-14 at 5.04.11 PM

La boucle de téléchargement écrit un rapport qui contient la datation des fichiers, histoire que vous puissiez la lancer en plusieurs fois si nécessaire sans recommencer au début. Le code, qui fait 300 lignes à tout casser, permet aussi de compter le nombre d’articles par année, par revue, ou les deux, ou par nombre d’auteurs.

Démo : la Convention-cadre OMS FCTC

La démo du code télécharge 236 articles en rapport avec la Convention-cadre de l’OMS pour la lutte antitabac. Quand on jette un coup d’oeil aux auteurs les plus fréquents dans le corpus, on trouve par exemple J. Collin et H. M. Mamudu, des noms connus dans ce segment de la littérature :

> pubmed_names('pubmed_fctc', min = 5)
538 Warren CW    14
30     Asma S    13
169 Glantz SA    13
225  Jones NR    13
414     Raw M     8
479  Sinha DN     8
150   Fong GT     7
316 McNeill A     7
67  Borland R     6
87  Chapman S     6
98   Collin J     6
298 Mamudu HM     6

Si l’on regarde les dates, le plus intéressant est au début : les premiers articles apparaissent trois ans avant l’adoption du texte, dans une revue de l’OMS et sous la plume de chargés de mission affectés à son élaboration. Celui-ci bénéficie ensuite d’une couverture exceptionnelle en 2005, son année d’application, et sa couverture reste élevée dans les années récentes4.

> head(pubmed_years('pubmed_fctc'))
  year count
1 2000     1
2 2001     2
3 2002     3
4 2004     1
5 2005    16
6 2006     3

Faites-vous une idée des articles téléchargés en allant lire le plus ancien, qui évoque la Convention-cadre et surtout les accords du GATT : la perspective d’une remise à plat des règles du commerce mondial offre une fenêtre d’opportunité à l’OMS pour produire son propre corpus de normes, en s’inspirant d’autres conventions comme celle de Basel5.

Screen Shot 2014-06-14 at 7.59.48 PM

Voici à présent le nombre d’articles publiés chaque année en lien avec la Convention-cadre par année. Les couleurs soulignent les revues qui ont le publié le plus d’articles (sans surprise, des revues de santé publique comme Tobacco Control et Addiction), ainsi que le Bulletin de l’OMS, le BMJ et le Lancet (il n’y a pas d’articles NEJM dans le corpus).

example

Comme il n’y a pas trop de données, on peut assez bien voir les petites aberrations du corpus, comme par exemple, ci-dessous en 2005, le numéro spécial d’un institut indépendant. La revue était alors basée à Vanves et publiée majoritairement en français ; elle a changé de nom et est à présent publiée par Sage Publications.

pubmed_fctc_lang

Mais… mais où est le réseau ?

Ah, je suis content que vous posiez la question. Pour les habitués, voici donc le réseau des co-auteurs dans le corpus « Convention-cadre OMS anti-tabac », où l’on retrouve les auteurs cités avec une de leurs collègues, plus des connexions entre chercheurs américains et britanniques, le tout entouré de beaucoup d’isolats.

pubmed_fctc_net

Le code pour créer le réseau produit un réseau non dirigé, où chaque lien indique un article co-signé par les deux auteurs. Le poids du lien est inversement proportionnel au nombre de coauteurs par article, additionné pour chaque paire de coauteurs (méthode “Newman-Fowler” ; appellation non contrôlée)6.

Le code du graphique lui-même, qui utilise ggnet (actuellement en soldes !), tient en dix lignes une fois les dépendances installées (packages devtools pour lire la fonction depuis GitHub sans vous embêter, network, sna et intergraph pour les réseaux, et RColorBrewer et ggplot2 pour le graphe).

source_url("https://raw.githubusercontent.com/briatte/ggnet/master/ggnet.R")
d = pubmed_edges("pubmed_fctc")
n = network(d[, 1:2])
n %e% "w" = d[, 3] / max(d[ , 3])
n %e% "q" = as.numeric(cut(n %e% "w", quantile(n %e% "w"), include.lowest = TRUE)) / 4
ggnet(n, segment.alpha = n %e% "q",
      segment.color = "black", size = 1) + 
  geom_text(label = ifelse(degree(n) > quantile(degree(n), .9),
                           network.vertex.names(n), NA), size = 4)
ggsave("pubmed_fctc_net.pdf", width = 11, height = 11)

Les données sont quasi-exhaustives, si l’on en croit le tests initiaux de 2011-2012. En revanche, le graphe peut éventuellement contenir plusieurs fois le même auteur s’il a été identifié par plusieurs combinaisons d’initiales et/ou de noms de famille (par exemple, “C Marquez” et “CR Marquez”).

Plus tard

On ira plus loin une prochaine fois, en regardant les mots-clés et les auteurs de plus près. La méthode de construction du réseau utilisée dans la demo est très basique : d’une part, elle ne collecte aucun attribut sur les auteurs, d’autre part, elle aplanit un réseau bipartite auteur-article où le mode secondaire (l’article) est très intéressant. À suivre, donc.

  1. L’industrie pharmaceutique , par exemple, a largement investi le champ de l’édition scientifique à des fins de légitimation de ses produits. []
  2. L’opérateur par défaut est AND. Les connecteurs logiques doivent être rentrés en majuscules et en anglais. Le reste des consignes est donné dans l’aide de PubMed. []
  3. L’antislash ne sert qu’à éviter un problème d’affichage avec le moteur de formatage du blog ; il ne doit pas figurer dans le code. []
  4. Il y a eu jusqu’à 44 articles sur le sujet en 2012, année d’adoption d’un protocole supplémentaire. Pour rappel, la recherche initiale n’utilise que les résumés (et les titres) des articles. []
  5. Le problème étant, bien évidemment, que jamais l’OMS n’a pu appliquer le genre de sanctions très dissuasives que l’OMC peut employer sur les marchés mondiaux. []
  6. La méthode Newman-Fowler étant additive, ses liens peuvent donc représenter un ou plusieurs articles co-signés. Le code renvoie aussi la version brute des liens au format CSV. []

Utiliser les résultats électoraux du ministère de l’intérieur

Toux ceux qui ont eu à utiliser un jour ou l’autre les fichiers de résultats électoraux diffusés par le ministère de l’Intérieur français savent que ceux-ci nécessitent un assez lourd travail de mise en forme afin d’être exploitables, en tout cas pour les élections pour lesquelles l’offre électorale n’est pas homogène sur le territoire (c’est-à-dire toutes sauf les présidentielles). En effet, les fichiers Excel diffusés par le ministère comprennent une ligne par territoire (commune, par exemple), et autant de colonnes que nécessaires pour mettre les résultats de tous les candidats. Il serait pourtant tellement simple de mettre le fichier en format « long », c’est-à-dire une ligne par combinaison territoire/candidat… Mais il faut croire que personne au ministère n’a jamais eu à lire un de leur fichier dans R ou un autre logiciel de statistiques (ou de cartographie). Au passage, on peut regretter que le site data.gouv ne demande ni même ne suggère à ses contributeurs de fournir les données en format tabulaire…

Quoi qu’il en soit, ceux qui ont à utiliser ces données ont généralement créé leurs petites routines pour traiter ces données. Sous Excel, le processus est particulièrement douloureux. Je me rappelle avoir fait planté des ordinateurs en faisant tourner des macros VBA…

Ayant eu à bricoler un script sous R pour importer ce genre de fichiers, j’ai décidé de le diffuser – ce qui a le mérite de m’obliger à le nettoyer un peu, et ce qui permettra, je l’espère, que d’autres l’améliorent. J’ai donc créé un tout petit package (il n’a qu’une fonction !) que j’ai mis sur mon compte Github.

Précision importante : le script, à l’heure actuelle, agrège les résultats en fonction des étiquettes attribuées par le ministère de l’Intérieur. C’est une limite importante, mais qui suffit à la plupart des utilisations courantes.

C’est une version 0.1 mais qui est fonctionnelle. À l’heure actuelle, traiter le fichier de résultat des européennes par communes (36762+ lignes, 227 colonnes) prend de l’ordre de cinq minutes sur un ordinateur de bureau classique. Ce n’est pas dramatique mais c’est un peu long. À l’avenir, je vais essayer d’accélérer cela – a priori en codant le cœur du script en C++, ce qui me forcera à m’y mettre. Mais peut-être d’autres auront-ils d’autres pistes – je ne suis pas sûr que mon algorithme soit optimal.

Sur ma todolist également : construire une application Shiny autour du package, pour que ceux qui n’utilisent pas R puissent quand même l’utiliser pour transformer leurs données.
Autre idée : permettre d’agréger les résultats autrement que par étiquette. C’est techniquement assez trivial, mais ça pose des problèmes de fond, du fait de l’hétérogénéité territoriale de l’offre électorale. Mais on pourrait imaginer la possibilité, par exemple, que l’utilisateur fournisse au script une sorte de « dictionnaire » associant les listes ou candidats à une nomenclature spécifique.

Je suis preneur en tout cas de tous les retours et suggestions des utilisateurs ! Et j’espère que ce sera utile à quelques uns !