Tous les articles par Ash_Crow

Bon anniversaire, Wikidata !

Wikidata a quatre ans aujourd’hui, et il me semble que c’est le bon moment pour faire un petit retour sur mon expérience avec ce projet[1]Et puis, Auregann m’a demandé de le faire ;)..

Wikidata est un projet qui m’intéresse vivement depuis bien longtemps avant sa création effective. Si j’avais lu le nom ici et là sur le bistro de Wikipédia depuis que j’ai commencé à contribuer en 2005, la première fois qu’il a retenu mon attention, pour autant que je m’en souvienne, est cette discussion  en novembre 2006[2]Au passage, en cherchant à la retrouver, je suis tombé sur la plus ancienne mention de Wikidata que j’aie vu sur la Wikipédia en français, qui remonte quand même à août 2004! : un dépôt commun pour les données, fonctionnant de la même façon que Commons, c’était exactement ce qui manquait à Wikipédia !

Et je n’étais apparemment pas le seul à avoir cet avis : c’était à l’époque l’opinion générale sur le bistro. Un autre avantage qui y était mentionné à l’époque, c’était que cela pourrait remplacer avantageusement le système de catégories foireux de l’époque (enfin… l’actuel quoi.) Une fonctionnalité que je suis toujours impatient de voir arriver.

Avec le temps, je suis devenu de plus en plus impliqué dans la communauté, et pour finir j’ai sauté dans le wiki-train pour Gdańsk en 2010 pour participer à ma première Wikimania.

1280px-wiki-train_poznan_dinner
*Record scratch* Yup, that’s me. You’re probably wondering how I ended up in this situation.

Là, l’une des présentations dont je me souviens le plus[3]Enfin à part celles avec de l’alcool. était celle d’un système centralisé pour la gestion des liens interwiki. Cette présentation ne faisait à l’époque aucune mention d’autre (méta-)données que les interwikis et éventuellement des libellés lisibles dans plusieurs langues, et ne parlait pas du tout de Wikidata. Pourtant, ces deux choses sont ce qui est devenu la « phase l » du développement de Wikidata le 29 octobre 2012. Quand j’ai commencé à y contribuer, le 17 décembre de la même année, le projet était encore naissant et ne permettait toujours de faire que ces deux choses : gérer les interwikis de Wikipédia, et mettre des libellés. C’est donc ce que j’ai fait : J’ai créé un nouvel élément, lui ai donné une paire de libellés et ait déplacé les liens externes depuis Wikipédia.

capture-du-2016-10-28-01-26-15
Ta-da !

Je me suis arrêté là à l’époque. Il n’y avait alors aucun moyen d’ajouter des déclarations plus utiles, et n’ayant pas la passion de la gestion des interwikis, j’ai laissé cette tâche aux robots et à leurs dresseurs. Pendant longtemps après ça, j’ai simplement fait des modifications par-ci par-là, mais sans m’atteler à un gros projet. J’avais cependant envie de passer au cran supérieur, et je me suis donc demandé à quoi m’atteler… En 2006 ou 2007, j’avais refait entièrement la liste des empereurs du Japon sur Wikipédia, et je me suis dit que ça pourrait être une bonne idée d’avoir les mêmes données de base (c’est-à-dire noms, dates de naissance/règne/mort, lieux de naissance et de mort, etc.) sur Wikidata également.

À l’époque, j’utilisais très peu d’outils ou de gadgets, et ça a donc été assez long et fastidieux (et sans l’outil missingprops.js de Magnus[4]Personnalisé pour mes besoins, ça l’aurait été encore plus), mais j’ai fini par en voir le bout.

capture-du-2016-10-28-21-33-36

Mon pic d’activité suivant a eu lieu quelques temps plus tard, quand j’ai décidé de créer chaque corps céleste de l’univers de Serenity/Firefly[5]Oui, pour info, je suis un Browncoat.. Le faire uniquement avec l’interface de Wikidata aurait relevé de la folie pure, et j’ai donc utilisé un autre outil de Magnus : QuickStatements. Si vous vous en êtes déjà servi, vous savez qu’une simple textarea où coller un blob de tab separated values n’est pas l’interface la plus pratique du monde… Du coup, j’ai décidé à l’époque de créer un outil moi-même pour résoudre le problème  : un  convertisseur CSV vers QuickStatements convertor qui permet de travailler avec un tableur organisé de façon plus traditionnelle.

Après ça, parmi d’autres choses, j’ai décidé d’importer tous les épisodes d’xkcd, et également aidé Harmonia Amanda dans son travail avec les courses de chiens de traîneaux puis les écoles d’art dramatique. Cela m’a incité à me plonger plus avant dans Python et écrire des scripts pour récupérer et traiter les données.

I know you all are xkcd fans.
Je sais que vous êtes tous fans d’xkcd.

 

Dans l’intervalle, j’ai également suivi la première édition du MOOC d’Inria sur le web sémantique, durant lequel j’ai appris plein de choses, et en particulier le langage SPARQL. Et là, c’est vraiment parti en roue libre : quand le point d’accès SPARQL pour Wikidata a été mis à disposition, j’ai écrit un billet ici à ce sujet. Des gens ont commencé à me poser des questions dessus, ou à me demander d’écrire des requêtes pour eux, et cet article est devenu le premier d’une longue série qui continue encore avec les #SundayQuery.

En résumé, en quatre ans :

  • J’ai commencé à coder des outils et les mettre à disposition de la communauté
  • J’ai écrit des scripts d’extraction et conversion de données en Python
  • J’ai beaucoup appris sur le web sémantique
  • Je suis devenu un ninja du SPARQL.

Et tout ça à cause de Wikidata. Et j’espère bien que ça va continuer sur cette lancée !

Image d’en-tête: Wikidata Birthday Cake par Jason Krüger (CC-BY-SA 4.0)

Enregistrer

Enregistrer

Enregistrer

Enregistrer

Enregistrer

Notes   [ + ]

1. Et puis, Auregann m’a demandé de le faire ;).
2. Au passage, en cherchant à la retrouver, je suis tombé sur la plus ancienne mention de Wikidata que j’aie vu sur la Wikipédia en français, qui remonte quand même à août 2004!
3. Enfin à part celles avec de l’alcool.
4. Personnalisé pour mes besoins
5. Oui, pour info, je suis un Browncoat.

Sunday Query : où meurent les Bretons ?

Cette #SundayQuery part d’une question de @belett sur Twitter : comment afficher des points de différentes couleurs sur une carte générée sur le point d’accès SPARQL de Wikidata ?

Première requête

En l’occurrence, il cherchait à afficher le lieu de mort des personnes nées à Rennes ou à Brest, avec une couleur différente selon leur lieu de naissance. À ma connaissance, on ne peut pas spécifier directement la couleur des points d’une carte avec un paramètre ?rgb comme on peut le faire avec un graphe. En revanche, si la requête comporte un paramètre ?layer, la carte l’utilisera pour gérer des couches avec des points de couleurs différentes et, encore mieux, qu’on peut afficher et masquer à volonté.

Voici donc ma première réponse, en donnant à mes couches le nom de la ville via la fonction BIND, qui permet de définir à la main le contenu d’une variable :

http://tinyurl.com/jyzaa9o

Carte d'Europe, avec des points surtouts concentrés sur l'Ouest de la France
Carte avec deux couches, une pour Rennes et une pour Brest, et montrant le sélecteur.

Avec VALUES

Mais je ne suis pas fan des UNION quand je peux les éviter, ou de mettre le nom des ?layer à la main avec un BIND : tout ça est so SPARQL 1.0 ! Heureusement, SPARQL 1.1 apporte un mot-clef pratique pour définir une liste de valeurs autorisées pour une variable[1]Ou plusieurs d’ailleurs. : VALUES. Voici la requête améliorée pour l’utiliser, et au passage chercher les gens nés à Nantes, tant qu’à y être :

http://tinyurl.com/zgr6lle

Carte d'Europe, avec des points surtouts concentrés sur l'Ouest de la France
Les points de Rennes et Brest sont toujours là, Nantes est venue s’y rajouter

J’en ai profité pour ajouter l’image si elle existe, qu’on voit en cliquant sur un point.

Dans toute la Bretagne

Mais pourquoi s’arrêter à quelques villes ? Autant y aller carrément avec toutes les personnes nées en Bretagne, par lieu de naissance.

http://tinyurl.com/zx7rww7

Il suffit de remplacer la liste de valeurs autorisées par la propriété disant que le lieu est situé en Bretagne[2]Administrative sur cette requête.… Seulement, suivant les éléments, plusieurs propriétés peuvent être utilisées : localisation administrative (P131), localisation géographique (P706), ou tout simplement lieu (P276)… Heureusement, SPARQL permet d’interroger toutes ces propriétés à la fois, en les séparant par des « | ». Les parenthèses sont optionnelles, on aurait aussi bien pu écrire   ?placeOfBirth wdt:P131*|wdt:P706*|wdt:P276* wd:Q12130 .  qui donne les mêmes résultats. Notez au passage qu’il faut alors mettre l’étoile au niveau de chaque propriété. Cette étoile sert à dire qu’il faut si besoin remonter plusieurs niveaux de résultats jusqu’à atterrir sur Q12130.

Carte d'Europe, avec de nombreux points de toutes les couleurs
Tiens, un sapin de Noël.

Oups : comme il y a une couche par lieu de naissance, ça fait beaucoup de calques, ce qui fait que la carte devient illisible… Et que le sélecteur de calques ne peut pas tout afficher à l’écran.

Optimisation

Heureusement, il est possible d’arranger ça facilement: il suffit de demander au passage le département de naissance[3]Il y a les cinq départements cette fois, puisque la requête porte sur la Bretagne historique cette fois. et l’utiliser comme ?layer à la place du lieu. Histoire de rester concis, je profite du fait qu’on peut utiliser la virgule pour plusieurs valeurs partageant le même sujet et la même propriété, de la même façon qu’on peut utiliser le point virgule pour des couples propriété-valeur ayant le même sujet.

http://tinyurl.com/z3cttt3

Résultat final

capture-du-2016-10-09-13-54-30

La carte montre deux résultats intéressants : beaucoup de gens meurent dans leur département de naissance et encore plus meurent à Paris[4]Le gros tas de points autour de la gare Montparnasse..

Ces deux remarques rappellent la question de savoir quelle est la distance moyenne entre le lieu de naissance et celui de décès des gens. Plusieurs études se sont plongées dessus, notamment celle-ci, publiée dans Science en 2014 et qui se base sur Freebase[5]Ainsi que sur deux bases d’artistes célèbres, non nommées dans l’article du Boston Globe., qui a depuis été intégrée dans Wikidata, et a des caractéristiques similaires, notamment le biais de sélection inhérent[6]Il faut être notoire pour une raison ou une autre pour être dans la base..

De fait, l’étude ne visait pas tant à mesurer la distance moyenne globale pour l’ensemble de l’humanité[7]Je n’arrive pas à retrouver les chiffres, mais il me semble me souvenir que la majeure partie de la population mondiale vit et meurt à moins de 30 km de son lieu de naissance… Le livre The Limits to Travel de David Metz ne donne pas de chiffres pour les décès mais note que de nos jours, l’écart moyen entre les lieux de naissance de deux mariés britanniques est d’un peu plus de 50 mi., mais à s’appuyer sur ce biais de sélection pour identifier des « attracteurs de mort », c’est à dire des lieux où il meurt plus de gens notables qu’il n’en naît, et par ricochet identifier des capitales culturelles. C’est le cas de Paris, où Wikidata recense 18 532 naissances contre 22 205 décès.

Ils constataient cependant qu’au cours du temps, la distance moyenne entre le lieu de naissance et celui de décès des personnes étudiées augmentait, passant de 215 km au 14e siècle à 380 km au 21e. Les Bretons présents sur Wikidata, toutes époques confondues, semblent encore plus voyageurs, avec une distance moyenne de 473 km, mais pas mal de variation entre les départements : cela va de 420 km pour les Morbihannais⋅e⋅s à 510 pour les Brétilien⋅ne⋅s.

Image d’en-tête : Les Merveilles de la nuit de Noël / Burzudou Nedellek (détail), par Émile Souvestre, 1844.

Enregistrer

Enregistrer

Enregistrer

Enregistrer

Enregistrer

Enregistrer

Enregistrer

Enregistrer

Notes   [ + ]

1. Ou plusieurs d’ailleurs.
2. Administrative sur cette requête.
3. Il y a les cinq départements cette fois, puisque la requête porte sur la Bretagne historique cette fois.
4. Le gros tas de points autour de la gare Montparnasse.
5. Ainsi que sur deux bases d’artistes célèbres, non nommées dans l’article du Boston Globe.
6. Il faut être notoire pour une raison ou une autre pour être dans la base.
7. Je n’arrive pas à retrouver les chiffres, mais il me semble me souvenir que la majeure partie de la population mondiale vit et meurt à moins de 30 km de son lieu de naissance… Le livre The Limits to Travel de David Metz ne donne pas de chiffres pour les décès mais note que de nos jours, l’écart moyen entre les lieux de naissance de deux mariés britanniques est d’un peu plus de 50 mi.

Sunday Query : utiliser SPARQL et Python pour corriger des coquilles sur Wikidata

À mon tour de faire une #SundayQuery! Comme Harmonia Amanda l’a dit dans son propre billet, j’envisageais de faire un article expliquant comment créer un script Python permettant de corriger les résultats de sa requête.. Finalement, j’ai préféré en faire un autre, au fonctionnement similaire mais plus court et plus simple à comprendre. Le script pour Harmonia est cependant disponible en ligne ici.

Jeudi, j’ai publié un article au sujet des  batailles du Moyen Âge, et depuis, j’ai commencé à corriger les éléments correspondants sur Wikidata

L’une des corrections les plus répétitives était la capitalisation des libellés en français : comme ils ont été importés de Wikipédia, ils ont une majuscule inutile au début ( « Bataille de Saint-Pouilleux en Binouze » instead of « bataille de Saint-Pouilleux en Binouze »…)

La requête

Commençons par trouver tous les éléments présentant cette coquille.

http://tinyurl.com/jljf6xr

Quelques explications de base :

  • ?item wdt:P31/wdt:P279* wd:Q178561 .  cherche les éléments qui sont des batailles ou des sous-classes de batailles, pour être bien sûr que je ne vais pas virer sa majucule à un bouquin intitulé  « Bataille de Perpète-les-Olivettes »…
  • Sue la ligne suivante, je demande les libellés pour les éléments en question  ?item rdfs:label ?label .  et les filtre pour ne garder que ceux en français FILTER(LANG(?label) = "fr") . . Comme j’ai besoin d’utiliser le libellé dans la requête et pas juste de l’afficher (et comme Harmonia Amanda l’a expliqué dans son billet de dimanche), je ne peux pas utiliser le servicce wikibase:label, et je me rabats donc sur le standard du web sémantique rdfs:label.
  • La dernière ligne est un FILTER  (filtre), qui ne garde que les résultats qui répondent à la fonction à l’intérieur. Ici, STRSTARTS  vérifie si ?label  commence avec "Bataille " .

Au moment où j’ai écrit la version anglaise de ce texte, la requête renvoyait 3521 résultats. Beaucoup trop pour les corriger à la main, et je ne connais aucun outil déjà existant qui pourrait faire ça pour moi… Je suppose qu’il est temps de dégainer Python, du coup !

Le script Python

J’aime Python. J’adore carrément Python, même. Ce langage est génial pour créer une une application utile en une poignée de minutes, facile à lire (pour peu qu’on lise l’anglais) et pas constellé de séries d’accolades ou de points-virgules, et a des libs géniales pour les choses que je fais le plus avec : récupérer le contenus de pages web, trier des données, vérifier des ISBNs [1]J’espère pouvoir bientôt quelque chose ici sur ce sujet. et faire des sites web. Oh, et pour faire des requêtes SPARQL et traiter les résultats [2]En plus, les exemples dans la doc officielle sont basés sur Firefly. Yes sir, Captain Tightpants..

Deux charmeurs de serpent avec un python et deux cobras.
Et puis le nom du langage a un petit côté « charmeur de serpents » 😉

Premières remarques

Si vous ne connaissez pas du tout le Python, cet article n’est pas le bon endroit pour ça, mais il y a de nombreuses ressources disponibles en ligne [3]Par exemple, https://www.codecademy.com/learn/python ou https://docs.python.org/3.5/tutorial/.. Assurez-vous juste qu’elles sont à jour et pensées pour Python 3. La suite de cet article part du principe que vous avez une connaissance basique de Python (indentation, variables, chaînes de caractères, listes, dictionnaires, imports et boucles for.), et que Python 3 et pip sont installés sur votre machine.

Pourquoi Python 3 ? Parce que nous allons manipuler des chaînes qui viennent de Wikidata et sont donc encodées en UTF-8 et que Python 2 n’est pas hyper pratique pour ça. Et puis mince, on est en 2016, par Belenos !

Pourquoi pip ? Parce qu’on a besoin d’une libraire non-standard pour faire des requêtes SPARQL, appelée SPARQLwrapper, et que cette commande est le moyen le plus simple de l’installer :

Allez, on commence à scripter !

Pour commencer, un script qui fait une requête Sparql retournant la liste des sièges à corriger [4]Oui, les sièges, j’ai déjà corrigé les batailles avant d’écrire le billet 😉 :

Ça fait un bon petit paquet de lignes, mais que font-elles ? Comme on va le voir, la plupart vont en fait être incluses à l’identique dans tout script qui fait une requête  SPARQL.

  • Pour commencer, on importe deux choses du module  SPARQLWrapper : la classe SPARQLWrapper elle-même et la constante « JSON » qu’elle va utiliser plus tard (pas d’inquiétude, on n’aura pas à manipuler du json directement.)
  • On import aussi le module « Pretty printer » pour afficher les résultats de manière plus lisible.
  • Ensuite, on crée une variable qu’on nomme « endpoint », qui contient l’URL complète vers le point d’accès SPARQL de Wikidata [5]Et non son accès web qui est simplement « https://query.wikidata.org/ ».
  • Ensuite, on crée une instance de la classe SPARQLWrapper qui utilisera ce point d’accès pour faire des requêtes, et on les met dans une variable simplement appelée  « sparql ».
  • On applique à cette variable la fonction setQuery, qui est l’endroit où l’on rentre la requête de tout à l’heure. Attention, il faut doublonner les accolades (remplacer { et } par {{ et }}, car elles sont des caractères réservés dans les chaînes Python.
  • sparql.setReturnFormat(JSON)  dit au script que le résultat sera retourné en json.
  • results = sparql.query().convert() , enfin, fait la requête elle-même et convertit la réponse dans un dictionnaire Python appelé  « results ».
  • Et pour l’instant, on va juste afficher le résultat à l’écran pour voir ce qu’on obtient.

Ouvrons un terminal et lançons le script :

C’est un gros paquet de résultats mais on peut voir que c’est un dictionnaire qui contient deux entrées :

  • « head », qui contient les noms des deux variables renvoyées par la requête,
  • et « results », qui contient lui-même un autre dictionnaire avec la clef « bindings », associée avec la liste des résultats eux-mêmes, chacun d’entre eux étant lui-même un dictionnaire  Python. Pfiou…

Examinons un desdits résultats :

C’est un dictionnaire avec deux clefs (label et item), chacune ayant pour valeur un autre dictionnaire qui à son tour a une clef « value » associée avec, cette fois, la valeur qu’on veut au final. Enfin !

Parcourir les résultats

Parcourons la liste « bindings » avec une boucle « for » de Python, pour pouvoir en extraire les résultats.

Rapide explication sur la ligne  qid = result['item']['value'].split('/')[-1]  : comme l’identifiant de l’élément est en fait stocké sous la forme d’une URL complète (« https://www.wikidata.org/entity/Q17627724 » et pas juste « Q17627724 »), il nous faut séparer cette chaîne à chaque caractère ‘/’, ce qu’on fait à l’aide de la fonction « split()« , qui transforme la chaîne en une liste Python contenant ceci :

Nous ne voulons que le dernier élément de cette liste. En Python, c’est celui avec l’index -1, d’où le [-1] à la fin de la ligne. Enfin, nous stockons cette valeur dans la variable qid.

Lançons le script ainsi modifié :

Corriger le problème

On y est presque ! Maintenant, il reste à remplacer cet orgueilleux « S » majuscule par un plus modeste « s » minuscule :

Que se passe-t-il ici ? Une chaîne Python fonctionne comme une liste, on peut donc lui demander de prendre la partie située entre le début de la chaîne « label » et la position qui suit le premier caractère (« label[:1] ») et forcer celui-ci en bas-de-casse (« .lower() »). Ensuite, on y concatène le reste de la chaîne (de la position 1 à la fin, donc « label[1:] ») et on réassigne ce résultat à la variable « label ».

Dernière chose, formater le résultat de manière compatible à QuickStatements:

Cette ligne semble barbare ? Elle est en fait assez simple : "{}\tLfr\t{}"  est une chaîne qui contient un premier emplacement pour le résultat d’une variable (« {} »), puis une tabulation, (« \t »), puis le mot-clef Quickstatements pour le libellé français (« Lfr »), une autre tabulation et enfin le second emplacement pour une variable. Ensuite, la fonction « format() » se charge de mettre le contenu des variables « qid » et « label » dedans. Le script final devrait ressembler à ça :

C’est parti :

On est bons ! Il ne reste plus qu’à copier-coller le résultat dans QuickStatements et attendre qu’il fasse le boulot tout seul.

Image à la une : Photographie de fontes de caractères par Andreas Praefcke (domaine public)

Enregistrer

Enregistrer

Notes   [ + ]

1. J’espère pouvoir bientôt quelque chose ici sur ce sujet.
2. En plus, les exemples dans la doc officielle sont basés sur Firefly. Yes sir, Captain Tightpants.
3. Par exemple, https://www.codecademy.com/learn/python ou https://docs.python.org/3.5/tutorial/.
4. Oui, les sièges, j’ai déjà corrigé les batailles avant d’écrire le billet 😉
5. Et non son accès web qui est simplement « https://query.wikidata.org/ »

De la classification sur Wikidata

Quand on classe des trucs, on a grosso-modo deux approches possibles : des cases hyper-pointues allant aussi loin que possible dans le détail, ou au contraire des cases très larges en laissant à l’utilisa⋅teur⋅trice le soin de croiser pour trouver ce qui l’intéresse. Wikimedia Commons a grosso-modo choisi la première approche, avec des catégories comme « [[Category:Castles in Andalusia at night]] [1]Je suis déçu : il n’y a pas de sous-catégorie [[Category:Castles in Andalusia at night facing left]]. », alors que Wikidata a plutôt choisi l’approche inverse, avec un grand nombre de propriétés que l’on peut croiser par le biais de requêtes SPARQL (entre autres), ce qui donne pour l’Alhambra de Grenade : « Nature de l’élément (P31) → château fort (Q23413) » et « Pays (P17) → Espagne (Q29) » et tout un tas d’autres déclarations [2]Wikipédia, quant à elle, hésite entre ces deux approches, selon les catégories..

Un château en Espagne (allégorie)
Un château en Espagne (satire)

Je dis « plutôt choisi » parce qu’il arrive qu’on tombe sur des cas où une classe tente de mélanger plusieurs axes, et qui suffisent généralement à démontrer pourquoi cette approche est une mauvaise idée. En l’espèce, je vais me pencher sur l’élément « bataille du Moyen Âge (Q15991159) » : ça tombe bien, c’est un domaine qui me botte.

Le problème des classes aux limites arbitraires

Le premier problème qui vient à l’esprit, c’est les limites de la classe : si on se fie à sa description en français, la seule présente lors de sa création, cette classe est censée contenir des « bataille[s] ayant eu lieu pendant la période du moyen âge, en occident ». Bon, la description précise explicitement l’Occident qui n’était qu’implicitement défini par le fait que le Moyen Âge est une notion d’historiographie occidentale, mais les limites restent assez floues.

  • Bataille en soi est discutable (on peut se poser la question d’y inclure ou non les sièges, par exemple), mais partons du principe que l’on a la même définition que pour l’élément « bataille (Q178561) » tout court qu’il remplace en tant que nature de l’élément (P31).
  • Par contre, « la période du moyen âge », c’est largement plus subjectif. Les dates varient pas mal. Si la plupart des historiens s’accordent à situer le début à l’année 476 [3]En revanche, la culture populaire a tendance à ignorer complètement le haut Moyen Âge. Tous les jeux de stratégie médiévale que je connais commencent en 1066 avec l’expédition de Guillaume le Conquérant. Si la période précédente est abordée, c’est dans des extensions, comme Crusader Kings II avec Charlemagne., la fin est plus floue. Même en ignorant le « long Moyen Âge » de Jacques Le Goff qui s’étend en gros de Justinien à la Révolution française, les dates généralement admises varient par pays mais sont situées dans la seconde moitié du XVe siècle.
  • Enfin, comme dit plus haut, le Moyen Âge est un concept occidental, ce qui recouvre une zone aux contours flous, aussi bien à l’époque actuelle que si on se limite au Moyen Âge : au début de la période, c’est l’Empire romain d’Occident, celui qui vient de s’effondrer sous les coups des barbares assoiffés de sang qui, etc., vous connaissez le roman national. À la fin, c’est, pour faire simple, la Chrétienté [4]enfin pas l’Éthiopie non plus, faut pas déconner., ce qui pose d’autres questions : à partir de quand peut-on inclure les batailles dans les pays orthodoxes ? Et dans les pays scandinaves/germaniques/nordiques ? Et les batailles impliquant des forces européennes mais se passant ailleurs, comme les Croisades, on les compte ? Autrement dit pour ce dernier cas, on définit « Occident » par le lieu de l’action ou par l’origine des belligérants ?

Par comparaison, l’approche standard de Wikidata (en utilisant « nature de l’élément (P31)bataille (Q178561) », date (P585) [5]ou « date de début (P580) » et « date de fin (P582) » si besoin., « lieu (P276) » et « participant (P710) » pour les cas abordés dans la liste ci-dessus) se révèle à la fois plus souple (on peut être très précis⋅e sur la date comme sur le lieu) et moins subjective que l’apposition de la classe bataille du moyen Âge…

Les données réelles

Du coup, avec des définitions aussi floues, on peut se demander comment les données sont utilisées…

Cherchons donc ça.

On a donc 687 éléments ayant cette nature, dont voici la liste par ordre alphabétique.

Répartition géographique

Plaçons donc les résultats sur une carte :

bataillesmoyenagecarte

http://tinyurl.com/jf4kvzw

Ouch, ça pique. Je veux bien admettre qu’on compte les batailles au Proche Orient, probablement liées aux Croisades, mais des chevaliers médiévaux dans le Golfe de Guinée ? au Mexique ? au Japon ? Il semblerait que la limitation de la classe à l’Occident ne soit pas une évidence pour tout le monde. Argh. Mais on est au moins raccord sur la période alors ?

Répartition temporelle

bataillesmoyenagefrisehttp://tinyurl.com/hkb6cqf

Si on place les résultats sur une frise, c’est nettement meilleur que sur la carte, avec seulement deux résultats manifestement erronés : la bataille d’Andrinople en 378 et celle de Szikszó en 1588 (vous ne devriez pas les voir ressurgir dans les résultats, j’ai corrigé ça.) Reste que la limite de fin reste arbitraire, contrairement à une requête normale où l’on peut choisir celle qui nous intéresse, que ça soit 1453 [6]Quand les Bretons sont venus sauver le cul des Français une énième fois à la bataille de Castillon. Ou alors c’est pour l’invention de l’imprimerie mobile par Gutenberg, ou la chute de Constantinople, allez savoir., 1492 [7]Quand les Français, ingrats (cf. note précédente), s’emparent de « la ville de Rennes et la fille qui est dedans », à moins que ça n’ait trait à la fin de la Reconquista et à l’expédition de Christophe Colomb…, ou n’importe quelle autre.

Si on résume, l’arbitraire des choix impliqués par une classe croisant de multiples critères la rend inutilisable en pratique, tout en compliquant la recherche des batailles « normales » puisque qu’on doit du coup inclure les sous-classes, juste pour récupérer les batailles ayant eu lieu en Europe (ou pas) entre 476 et 1453, ou 1492, ou 1500 (enfin on l’espère).

Ma conclusion ? Comme disait Jeanne la Flamme au siège d’Hennebont, foutez-y-moi le feu.

jeanne_flamme
Jeanne la Flamme, par Jeanne Malivel (1926)

Image d’en-tête : Le Combat des Trente (détail), par Pierre Le Baud (1480-1482)

Enregistrer

Enregistrer

Enregistrer

Enregistrer

Enregistrer

Enregistrer

Enregistrer

Enregistrer

Enregistrer

Enregistrer

Enregistrer

Enregistrer

Enregistrer

Enregistrer

Enregistrer

Notes   [ + ]

1. Je suis déçu : il n’y a pas de sous-catégorie [[Category:Castles in Andalusia at night facing left]].
2. Wikipédia, quant à elle, hésite entre ces deux approches, selon les catégories.
3. En revanche, la culture populaire a tendance à ignorer complètement le haut Moyen Âge. Tous les jeux de stratégie médiévale que je connais commencent en 1066 avec l’expédition de Guillaume le Conquérant. Si la période précédente est abordée, c’est dans des extensions, comme Crusader Kings II avec Charlemagne.
4. enfin pas l’Éthiopie non plus, faut pas déconner.
5. ou « date de début (P580) » et « date de fin (P582) » si besoin.
6. Quand les Bretons sont venus sauver le cul des Français une énième fois à la bataille de Castillon. Ou alors c’est pour l’invention de l’imprimerie mobile par Gutenberg, ou la chute de Constantinople, allez savoir.
7. Quand les Français, ingrats (cf. note précédente), s’emparent de « la ville de Rennes et la fille qui est dedans », à moins que ça n’ait trait à la fin de la Reconquista et à l’expédition de Christophe Colomb…

À la recherche des communes françaises sur Wikidata

J’ai eu besoin récemment d’obtenir la liste des communes françaises avec leur identifiant Wikidata. Cette liste change constamment : si la France compte toujours un peu plus de 35 000 communes, le nombre exact change plusieurs fois par an, les communes fusionnant ou étant séparées à un rythme difficile à suivre. Il y a même un article de Wikipédia dédié aux nombre de communes en France. Si on peut s’y fier, il y en a donc très exactement 35 884 au moment où j’écris ces lignes, et une autre fusion entrant en vigueur mardi 1er mars (entre Binic et Étables-sur-Mer), il y aura à ce moment une commune de moins.

L’article n’est cependant pas clair sur ce qui est supposé être inclus dans ce décompte : la métropole uniquement ? Les DOM sont-ils inclus ? Et les COM ? Avant de me pencher plus en détails là-dessus, allons-voir combien ce qu’en disent d’autres sources.

Une liste officielle des communes de la métropole et des DOM [1]excluant donc les 48 communes de Polynésie française et les deux de Saint-Pierre-et-Miquelon est publiée chaque année par l’Insee dans le Code officiel géographique (COG) mais la dernière version publiée est celle de 2015. Le fichier, dont on voit un extrait ci-dessous, compte 36 658 entrées , ce qui est cohérent avec les données annoncées par l’article de Wikipédia pour 2015…

Par curiosité, je regarde aussi du côté d’OpenStreetMap qui, de son côté, fournit sur data.gouv.fr un export du découpage des communes françaises. D’après sa description, il est à jour au 1er février 2016, et contient le titre des articles Wikipédia. C’est un fichier shapefile dont il est très simple d’extraire la liste des codes Insee et le titre des articles Wikipédia correspondants grâce à la librairie python qui va bien et un tout petit bout de code. Surprises, il contient 35 888 communes, soit deux de trop comparé à Wikipédia [2]deux et non quatre, car le fichier inclut les deux communes de Saint-Pierre-et-Miquelon qui ne sont pas dans le COG. Pourquoi Saint-Pierre-et-Miquelon et pas la Polynésie française, mystère., et pour 282 d’entre elles, il manque le lien vers l’article de Wikipédia.

Mais revenons à Wikidata, qui devrait avoir 35 934 communes, en comptant les TOM. Vérifions avec SPARQL :

http://tinyurl.com/gm4xdyt

Le résultat que j’obtiens est de 38 663 communes. C’est 2729 de trop… C’est dû aux anciennes communes, fusionnées ou supprimées depuis. Pour obtenir la liste à jour, il me faudrait donc faire un filtre sur la présence d’un qualificateur « Date de fin (P582) » sur la déclaration « wdt:P31 wd:Q484170 ».  Sauf qu’en faisant ça… J’obtiens 37 475 résultats : la date de fin n’est manifestement pas correctement indiquée de manière systématique. Il semble également y avoir quelques îles marquées comme commune alors qu’un élément séparé existe pour celle-ci.

Bon, plus qu’à se retrousser les manches et corriger tout ça…

Histoire de dégrossir le travail, je vais commencer par passer sur toutes les communes sans code Insee ni date de fin et corriger ce qui cloche :

http://tinyurl.com/hkoqlho

Pour chaque commune : je vérifie la date de fusion ou suppression indiquée dans Wikipédia, et je reporte l’info dans Wikidata. Si c’est devenu une commune associée, je l’indique également et j’en profite aussi pour supprimer la nature « ancienne commune française » qui est présente sur une poignée d’éléments et ne devrait tout simplement même pas exister… Ça donne un résultat comme ça et si vous voulez venir me filer un coup de main, vous êtes les bienvenus 🙂

(Image à la une : Le port de Binic, ou plutôt maintenant Binic-Étables-sur-Mer, CC-BY-SA-3.0 Semnoz)

Notes   [ + ]

1. excluant donc les 48 communes de Polynésie française et les deux de Saint-Pierre-et-Miquelon
2. deux et non quatre, car le fichier inclut les deux communes de Saint-Pierre-et-Miquelon qui ne sont pas dans le COG. Pourquoi Saint-Pierre-et-Miquelon et pas la Polynésie française, mystère.

Wikidata, SPARQL et dynasties électives

La dernière fois, j’avais dit que je continuerais avec les chiens de traîneau mais entre-temps, Fralambert a posé la question suivante sur le bistro de Wikidata :

Bonjour, avec l’élection de Justin Trudeau (Q3099714) comme premier ministre du Canada, et suite à une petite discussion sur IRC. Je me demandais comment on pourrait avoir:

  • Tous les fils ou filles de ministres devenu ministre
  • Et tant qu’à y être, quel est le pays le plus népotique (qui regroupe le plus de ces cas)

On ma suggérer que l’on pourrait le faire à partir de SPARQL, mais je n’ai aucune idée de la façon de programmer ça. Le plus près que je me suis rendu sur Query est Query: CLAIM[39:(Tree[83307][][279])] and claim[40]. Bon mon petit défi est lancé, bonne chance. 😉 —Fralambert (discussion) 01:31, 22 October 2015 (UTC)

La seconde question me permet aussi de faire ce que j’avais prévu pour cet article, la réutilisation des données extraites pour faire une carte, donc, au revoir les chiens…

INC_2009_Justin_Trudeau2
À la place des huskies, vous avez donc droit à un premier ministre avec une tête de prince Disney. C’est bien aussi, non ?

Première question

Sans plus attendre, la requête répondant à la première question :

https://tinyurl.com/py3jzsb

Capture du 2015-10-23 20:29:59

J’ai commenté la requête directement pour éviter d’avoir à tout recopier. On voit que je fais deux requêtes sur les parents ayant occupé une fonction étant une sous-classe de ministre : une pour les pères, une pour les mères. Il me semble qu’on devrait pouvoir utiliser schema:parent pour s’éviter la jointure, mais soit ce n’est pas encore implémenté, soit je m’y prends mal, parce que ça ne renvoie aucun résultat.

Je remarque aussi au passage que l’auto-complétion a été activée : il suffit de taper le début du label (ou d’un alias) en anglais d’un élément ou d’une propriété et faire <Ctrl>+<Espace> pour le remplacer par son identifiant Wikidata :

Capture du 2015-10-23 19:47:05

Voilà qui devrait faciliter l’utilisation au quotidien.

Et par pays ?

La deuxième requête nécessite juste de regrouper par pays et de compter le nombre de résultats plutôt qu’en afficher la liste.

https://tinyurl.com/pcmht2u

Mais on peut faire mieux : cette requête se prête parfaitement à un affichage sous forme de carte. Direction un autre outil de requêtes SPARQL, http://demo.seco.tkk.fi/visu/#/.

Comme il n’est pas spécifique à Wikidata, il faut cette fois indiquer, en plus de la requête, l’URL complète du endpoint SPARQL de Wikidata : https://query.wikidata.org/bigdata/namespace/wdq/sparql/

C’est également une bonne idée d’adapter un peu la requête pour utiliser les codes standards des pays plutôt que leur nom, en l’occurrence le code FIPS 10-4 (pays et régions) (P901).

https://tinyurl.com/nepotsmap

Capture du 2015-10-23 21:09:56

Limites

Cependant, cette requête montre clairement les limites de Wikidata dans son état actuel : on manque encore cruellement de données et surtout de liens entre elles. En effet, à en croire le résultat, il n’y aurait de toute éternité dans le monde entier que cent ministres dont le père ou la mère* a été ministre également, et près de la moitié en Grèce. Outre le biais évident de la demande d’origine de ne considérer que le népotisme que pour les ministres et non l’ensemble des personnalités politiques (présidents, parlementaires, et même pourquoi pas diplomates, officiers, évêques…), le problème est que pour qu’une entrée ressorte, il faut que pour le parent comme pour l’enfant :

  1. l’élément existe (ben oui…)
  2. les relations généalogiques soient correctement renseignées
  3. la fonction soit renseignée (et correctement, il est encore fréquent de trouver la fonction remplie avec « ministère de XXX » au lieu de « Ministre »)
  4. et enfin qu’il y ait une chaîne ininterrompue de sous-classes entre l’élément indiqué comme fonction et l’élément « Ministre » (Q83307)

Visiblement, ce travail a été fait correctement pour la Grèce (environ 900 ministres depuis l’indépendance du pays ne me semble pas déconnant), mais reste à faire pour les autres pays.

* À ce sujet, la seule femme ministre qui a eu un enfant ministre également (d’après ces résultats du moins) est Indira Gandhi.

Image d’en-tête : L’Adoration des mages, par Botticelli, montre Cosme de Médicis, fondateur de la dynastie politique du même nom, accompagné de plusieurs de ses enfants et petits enfants.

Enregistrer

Wikidata, SPARQL et chiens de traîneaux

Bon, puisque le dernier billet semble avoir plu, je vais continuer de poster ici mes bidouillages avec SPARQL. L’hiver arrive à grands pas et la saison des courses de chiens de traîneaux aussi par la même occasion, donc c’est parti pour des requêtes un peu plus touchy avec des photos de chiots, parce qu’il n’y a pas de raison de ne pas en profiter.

UNION

Pour commencer, j’aimerais bien avoir toutes les courses de chiens de traîneaux pour lesquelles des participants sont enregistrés. Problème : il y a des courses pour lesquelles la nature de l’élément (P31) est course de chiens de traîneaux (Q1968664), d’autres pour lesquelles la nature est un élément concernant une course qui est elle-même une sous-classe (P279) de course de chiens de traîneaux, et enfin d’autres pour lesquelles la nature est un élément concernant une course qui n’est pas marquée comme sous-classe de course de chiens de traîneaux… Mais pour lequel « course de chiens de traîneaux » est indiqué comme sport (P641). Bref, c’est le bordel. On va donc faire les deux requêtes en même temps et en joindre les résultats avec la commande UNION, comme ci-dessous.

https://tinyurl.com/q74e9ve

Comme dit ci-dessus, quand la même chose peut être décrite sous deux formes, on peut faire une union pour joindre les résultats des deux requêtes :

La ligne suivante :

sert à restreindre aux courses ayant un ou des valeurs pour la propriété  « participant » (P710)

Pour finir, je trie par ordre alphabétique des noms en français des courses :

Capture du 2015-10-19 22:54:09

Husky puppy, CC-BY Tony Pham

Qualificatifs

J’aimerais maintenant chercher, dans les participants à des courses de chiens de traîneau, ceux qui n’ont pas de rang à l’arrivée d’indiqué, ni d’événement-clef expliquant pourquoi ils ne sont pas arrivés (par exemple, abandon ou disqualification). Ces informations sont mises en qualificatifs de la déclaration :

Capture du 2015-10-19 23:37:46

Ici, dans les participants de l’Iditarod 2015, on voit que Brent Sass a été disqualifié (il y a même un article de Wikinews expliquant pourquoi), et que Jason Mackey est arrivé 42e.

On ne peut pas chercher ça avec wdt:, qui renvoie une valeur. Il nous faut utiliser une autre des ontologies proposées par défaut, p:, qui renvoie une déclaration en entier, avec tous ses qualificatifs. La requête est donc la suivante :

La première ligne du WHERE n’a pas changé par rapport à la requête précédente.

Dans la deuxième, en revanche, on voit que wdt: a été remplacé par p:.

J’ai aussi renommé ?musher par ?musherS pour me rappeler que c’est une déclaration (statement) et non une valeur directement. Pour pouvoir afficher le nom des mushers, je vais devoir chercher ladite valeur en utilisant le préfixe v: et la même propriété, avec la déclaration comme sujet :

Enfin, deux filtres sur les qualificatifs (on utilise donc q: et non p: cette fois) me permettent de remonter les lignes qui n’ont pas (FILTER NOT EXISTS) de rang (P1352) ni d’événement-clef (P793).

Capture du 2015-10-19 23:26:42

Samoyède, CC-BY-SA Sp..andreea

Je crois que je vais continuer à m’amuser un peu avec les courses de chiens la prochaine fois, et voir dans quoi on peut réinjecter les résultats des requêtes, pour générer des graphiques ou des cartes…

Photo d’en-tête : Brent Sass et Allen Moore campent l’un à côté de l’autre à un checkpoint durant la Yukon Quest 2015. Photo CC-BY Public Affairs Office Fort Wainwright

Enregistrer

Enregistrer

Mais combien y a-t-il de femmes scientifiques sur Wikipédia ? (this time with SPARQL)

Dans mon dernier billet, j’explorais les possibilités d’exploiter les données de Wikidata avec Autolist. Il est maintenant possible d’interroger Wikidata en utilisant le langage standard du web sémantique, SPARQL. Je ne vais pas faire un cours de SPARQL sur ce blog, mais je vais détailler une requête étape par étapes.

Comme c’est à nouveau le jour de l’éditathon Femmes de sciences, je vais reprendre la même requête que la dernière fois : combien y-a-t-il de femmes scientifiques sur les projets Wikimedia, et quel taux par rapport aux hommes ?

Pour commencer, ça se passe par là : https://query.wikidata.org/

Et comme première requête, on va demander de lister 10 êtres humains, sans préoccupation de genre ou de profession. Cela se formule comme ça :

https://tinyurl.com/qhhzdsz

Les deux préfixes au début permettent d’éviter d’avoir à taper en entier les URL des ontologies qu’on utilise. On en ajoutera au fur et à mesure qu’on en aura besoin. Vous pouvez cliquer sur le bouton « Add prefixes » pour en ajouter un paquet d’un coup mais pour les besoins de ce tutorial, je ne vais inclure dans chaque requête que ceux qu’on utilise vraiment.

passons à la requête elle-même :

Ceux pour qui le langage SQL est familier ne seront pas trop dépaysés : « select » est la commande pour demander au serveur de retourner un liste de résultats, « distinct » demande au serveur d’éliminer les doublons éventuels dans les résultats. « ?personne » est une variable qu’on va préciser plus bas, mais remarquez juste pour l’instant que les variables commencent par des points d’interrogation en SPARQL.

On continue avec la clause « where » où on va détailler au serveur ce qu’est cette fameuse variable ?personne qu’on lui demande.

Pour rappel, on cherche en fait des éléments Wikidata. Sur Wikidata, un élément est composé de déclarations dont la structure est la suivante :
2014-06_Introduction_à_Wikidata.pdf

Ici, la structure

peut se lire, dans le jargon du web sémantique :

ou dans celui de Wikidata :

Comme ce sont des éléments qu’on cherche,  on remplace cette partie par notre variable. La propriété qu’on cherche est P31 (nature de l’élément) et la valeur Q5 (être humain), et pour éviter de mettre les URL en entier on va utiliser les préfixes définis plus haut. On a donc wd: pour un élément wikidata et wdt: pour une propriété.

Enfin, le « LIMIT 10 » permet d’éviter de sortir une liste interminable de résultats qui prendrait un temps fou et dont l’affichage mettrait probablement à mal le navigateur.

Lançons maintenant la requête.

Résultats requete SPARQL 1

On a bien 10 résultats, mais ce qui serait bien, c’est d’afficher le label à côté, parce que de tête, je ne sais pas qui sont wd:Q260 ou wd:Q272.

https://tinyurl.com/pfnomxs

On ajoute donc un petit bout de code faisant appel au service « label » de Wikibase. C’est quelque chose de spécifique à Wikidata, qui ne correspond pas au standard (qui serait d’appeler la propriété rdfs:label) et est dû au fait que Wikidata a une gestion très poussée des langues. Elle permet cependant de faire un truc sympa : on peut lui préciser un langage de repli s’il n’y a pas de label dans la première langue demandée. Ainsi ici, si un élément remonté n’a pas de label en français, on va se replier sur celui en anglais. Pour ceux n’ayant pas de label dans ces deux langues, c’est l’identifiant Wikidata qui sera affiché.

J’ai ajouté également les préfixes pour les deux nouvelles ontologies utilisées. Enfin, on rajoute la deuxième colonne demandée au select. La syntaxe « ?<variable>Label » est particulière à ce service.

Continuons maintenant à préciser la requête : on se rappelle qu’on veut spécifiquement les femmes scientifiques.

Commençons par le genre.

On veut les personnes qui ont la valeur « femme (Q6581072) » à la propriété « sexe ou genre (P21) », et on a juste à ajouter la ligne

dans notre clause where. Pour la profession, c’est un peu plus compliqué : la plupart des scientifiques ne sont en effet pas recensés en tant que scientifiques directement mais avec des professions plus précises, comme Marie Curie qui est physicienne et chimiste. On veut donc non seulement les gens dont la profession (P106)  est scientifique (Q901) , mais aussi ceux dont la profession est une sous-classe (P279) de scientifique.

Cela se formule comme cela :

L’étoile sert à indiquer qu’on veut prendre plusieurs niveaux de sous-classe s’il y en a.

La requête finale est donc :

https://tinyurl.com/p9rtblf

Capture du 2015-10-18 22:04:45

Note : on peut abréger cette requête en remplaçant les trois lignes du where par une seule :

 

C’est bien, mais ce qu’on voulait à la base, c’est le *nombre* de femmes scientifiques, pas dix d’entre elles au hasard. Il suffit de changer la ligne 5 de la façon suivante :

on demande donc à SPARQL de compter le nombre de résultats de notre requête et de le renvoyer en tant que nouvelle variable ?nombre, ce qui donne ce résultat https://tinyurl.com/pgn6xel

Au moment où j’écris ces lignes, il y a donc 16764 femmes scientifiques sur Wikidata. Et si on veut comparer aux hommes ? Il est possible de sortir le chiffre par genre en mettant cette valeur comme une variable et en l’utilisant pour grouper les résultats. Cela se fait de la façon suivante :

https://tinyurl.com/oebwvh8

Capture du 2015-10-17 16:48:47

Quelques remarques :

  • j’ai dû renoncer à afficher les labels pour les genres, cela faisait partir la requête en timeout. Les valeurs sont les suivantes : masculin (Q6581097), féminin (Q6581072), femme transgenre (Q1052281), homme transgenre (Q2449503)
  • Les personnes trans* sont généralement indiquées à la fois comme de sexe masculin et féminin (avec des dates de début ou de fin correspondant à la transition) et de genre femme (ou homme) transgenre. Comme il y a une seule propriété pour sexe et genre, elles apparaissent donc 3 fois dans ces statistiques.
  • le t216432070 est en fait un blank node, c’est à dire un nœud vide.  Il correspond à Āpastamba, un mathématicien indien du IV ou Ve siècle avant notre ère, qui a « valeur inconnue » pour la propriété sexe ou genre (ce qui me semble une erreur, quelques recherches sur Internet pointent toutes vers un homme.)

 

Par rapport à la question d’origine, il ne reste donc plus qu’à filtrer les résultats pour ne garder que les éléments qui ont un interwiki vers la Wikipédia en français. On cherche donc la propriété schema:about en filtrant sur les URL concernant fr.wikipedia.org :

https://tinyurl.com/p3hokoo

Capture du 2015-10-18 22:03:23

Bilan : 7,6% de scientifiques sont des femmes sur la Wikipédia en français, contre 10% sur Wikidata. Cela a un peu progressé par rapport au précédent billet il y a sept mois.

PS : Merci à Karima Rafes pour sa présentation du langage SPARQL hier lors du SemanticCamp Paris #7.

Image à la une : Ada Lovelace par Margaret Carpenter (domaine public). L’editathon Femmes de sciences a lieu dans le cadre de l’Ada Week qui est nommée en son honneur.

Enregistrer

Enregistrer

Mais combien y a-t-il de femmes scientifiques sur Wikipédia ?

La semaine dernière s’est tenu à Paris un éditathon « Femmes de sciences », coorganisé par Wikimédia France. Mon collègue Mathieu s’est posé la question qui sert de titre à ce billet. Il se demandait également quel était le ratio hommes/femmes dans ce domaine, et m’a demandé comment trouver la réponse en utilisant Wikidata… Je me suis dit que la réponse pourrait intéresser d’autres personnes.

L’outil dont on a besoin est Autolist : https://tools.wmflabs.org/autolist/index.php? et on va l’utiliser pour obtenir les résultats d’une requête Wikidata Query (WDQ).

Prenons deux secondes pour repenser notre requête d’une façon compréhensible par l’ordinateur  : on veut les éléments qui ont pour nature (P31) « être humain (Q5) » (cette précision est obligatoire pour éliminer les personnages de fiction), de sexe ou genre (P21) « féminin (Q6581072) » et dont la profession (P106) est une sous-classe de (P279) « scientifique (Q901) »

Ce qui nous donne la requête : claim[31:5] AND claim[21:6581072] AND claim[106:(TREE[901][][279])] (la syntaxe du « TREE », pour obtenir les sous-classes de scientifique, est quelque peu déroutante mais est expliquée dans la documentation de WDQ.) On peut rajouter un « AND link[frwiki] » pour filtrer sur celles qui ont un article sur la Wikipédia en français. autolist

 Résultat : 14 725 éléments concernant des femmes scientifiques sur Wikidata. Parmi celles-ci, 2 629 ont un article sur Wikipédia en français.

Si je refais ces requêtes pour les hommes (claim[21:6581097]) : 157 093 hommes scientifiques sur Wikidata, dont 36 433 ont un article sur la Wikipédia en français.

On a donc :
  • 14725 / (14725 + 157093) * 100 = 8,57 % des scientifiques sur Wikidata sont des femmes.
  • 2629 / (2629 + 36433) * 100 = 6,73 % des scientifiques sur Wikipédia en français sont des femmes.

Les chiffres pour la Wikipédia en français me paraissent assez faibles et je présume que si la nature et le genre sont bien renseignés sur Wikidata, ce n’est probablement pas le cas de la profession (soit qu’elle n’est  pas indiquée sur l’entrée de la personne, soit que l’entrée de la profession elle-même n’est pas une sous-classe de « scientifique »).

Un autre moyen de rechercher cette information est de croiser les femmes renseignées sur Wikidata (claim[31:5] AND claim[21:6581072]) et les articles dans la catégorie:Scientifique (ou une des sous-catégories à une profondeur de 12 niveaux) sur la Wikipédia en français :

autolist2

Ce qui nous donne 42 321 hommes et 3 279 femmes et donc un taux de femmes de 7,19 %.

Bon, il reste du boulot. Aussi bien pour créer les articles sur Wikipédia que pour trier l’arborescence sur Wikidata.

Image d’en-tête : la conférence de Solvay, en 1911, où sur vingt-quatre scientifiques présents, il y a une seule femme : Marie Curie. Photographie de Benjamin Couprie, domaine public.

Enregistrer

Enregistrer

QuickStatements : trucs et astuces

Magnus Manske a créé beaucoup d’outils pour faciliter la contribution à Wikidata, Autolist et le Wikidata Game étant parmi les premiers qui viennent à l’esprit. Un autre de ses outils, très utile pour ajouter du contenu en masse, se nomme QuickStatements [1]QS dans la suite du texte..

Il est accessible ici et permet de créer des éléments de Wikidata, ou d’en compléter en ajoutant des déclarations (ou des références pour des déclarations existantes), en utilisant une syntaxe à base de tabulations qui est assez bien expliquée sur la page elle-même, ce qui m’évite d’avoir à détailler tout ça ici : débrouillez-vous, RTFM 🙂

Un petit avertissement cependant : si QS se débrouille très bien pour éviter de mettre en doublon une déclaration qui serait déjà présente, il n’y a aucun moyen de lui indiquer de ne pas remplacer un label ou une description s’il y en a déjà un.

Flood flag

Comme dit plus haut, QS permet d’ajouter du contenu en masse : on se retrouve vite à balancer plusieurs milliers de lignes dans le fichier, histoire de partir à un Mardi c’est wiki pour boire des bières [2]ou des diabolos : on n’est pas sectaires. pendant que notre ordinateur continue à contribuer tout seul. C’est cool, mais pas pour ceux qui vérifient les RC… Aussi, quand vous avez un gros traitement à lancer, je vous invite à demander le « flood flag » qui vous permet d’être considéré temporairement comme un robot.

Si vous êtes admin sur Wikidata, vous pouvez vous le mettre vous-même.

Conversion CSV vers QuickStatements

La syntaxe de QS peut devenir rapidement assez fastidieuse, et je trouve personnellement plus simple de travailler avec un tableur. J’ai donc écrit un script qui convertit un fichier CSV en liste de commandes pour QS. Il est trouvable à cette adresse, avec un exemple de la syntaxe attendue.

Il peut arriver qu’on veuille insérer le même label dans toutes les langues utilisant l’alphabet latin, aussi j’ai préparé un fichier avec les en-têtes dans un paquet de langues latines.

Récupération des lignes en erreur

Il peut arriver qu’une ligne pourtant correctement formatée ne passe pas dans QS [3]Pour info, sur un fichier d’environ 110 000 lignes, j’ai eu un peu moins de 500 erreurs… Et plus de 24h de traitement., à cause d’un timeout ou parce que Wikidata est passée en lecture seule. On a alors des résultats dans ce goût là dans le journal de QS :

Quand il y en a peu, il suffit de repasser la ligne précédente (ou de faire directement le changement en question à la main sur Wikidata…), mais quand il y en a beaucoup, on peut les récupérer automatiquement. Si vous êtes sous Linux, vous pouvez le faire de cette façon :

  1. enregistrer le journal des actions de QuickStatements dans un fichier texte (qu’on va nommer ici qs1.txt)
  2. ouvrir une console, se rendre dans le répertoire où est enregistré qs1.txt
  3. lancer la commande suivante :

Il suffit ensuite de copier-coller le contenu du fichier qs1_err.txt dans QuickStatements.

Image d’en-tête : « Shitloads of data to Wikidata », by Jean-Frédéric, CC-By 4.0

Notes   [ + ]

1. QS dans la suite du texte.
2. ou des diabolos : on n’est pas sectaires.
3. Pour info, sur un fichier d’environ 110 000 lignes, j’ai eu un peu moins de 500 erreurs… Et plus de 24h de traitement.