XPadje: Halsema’s speeches van Twitter lengte

Geplaatst op 21-12-2010 door Maarten Marx | onderwijs, XPath | tags: , | comment image Geen reacties »

PoliticalMashup heeft al verschillende blogs geschreven waarin wordt getoond hoe handig XPath en XQuery zijn voor het maken van politieke analyses op politieke data in XML. We gaan daar een serie van maken. We noemen de afleveringen daarvan Xpadjes.
Elke aflevering bestaat uit

  • Een onderzoeksvraag
  • De benodigde ingrediënten
  • De uitwerking in XPath en XQuery
  • Links naar de uitkomsten van de queries

De aflevering van vandaag gaat over Femke Halsema en haar Twitter gedrag.

Wordle: HalsemaTwitterLengteSpeeches

De vraag

Femke Halsema wordt de Queen of Twitter genoemd, omdat ze grandioos met dit nieuwe medium weet om te gaan. We vragen ons af of al dat getwitter van invloed is op de lengte van haar toespraken in de Tweede Kamer. Meer concreet,

nemen het aantal speeches van Halsema van Twitter-lengte (hooguit 140 karakters) toe?

Als speech kiezen we voor een deel uit de Handelingen dat aan één spreker wordt toegeschreven. Dus iets van de vorm

Mevrouw Halsema (GroenLinks): Heeft u er enig zicht op wanneer u de Kamer er meer over kunt zeggen? Kan dat volgende week al?

Ons resultaat.

We hebben 1726 speeches van Twitter lengte van haar gevonden. Hiervan zijn er 274 uitgesproken vanaf het spreekgestoelte, en de rest dus vanachter de interruptiemicrofoon.
Al die speeches bestaan in totaal uit 21604 woorden en 121267 karakters. Een gemiddelde van 12.2 woorden en 70 karakters.
Van een toename lijkt eigenlijk geen sprake.

Nodig:

De uitwerking

Informatiebehoefte: Geef alle speeches van Halsema korter dan 140 karakters.


let $scope := collection('/db/nlparliament/data/HAN1995')
return $scope//speech
          [contains(@speaker,'Halsema')] 
          [count(.//p)=1]
          [string-length(.//p) le 140] 

Informatiebehoefte: Geef me van die speeches steeds de datum gevolgd door de speech text, gescheiden door een ‘;’

declare namespace dc="http://purl.org/dc/elements/1.1/";

let $FemkesTwitSpeeches := $scope//speech
                                [contains(@speaker,'Halsema')]  
                                [count(.//p)=1]
                                [string-length(.//p) le 140]    
for $twitspeech in $FemkesTwitSpeeches
    let $date := $twitspeech/ancestor::root//dc:date
    return
    concat($date,';',$twitspeech//p,'
') 

De namespace declaratie is nodig omdat de datum in een element met een namespace (dc:date is opgeslagen. De namespace van dc vindt je bovenaan het XML document als attribuut van het root-element daarvan.
In de laatste regel is 
 een entity die voor een nieuwe regel zorgt. Het resultaat van deze query staat hier.

Dit kunnen we nog op twee manieren verbeteren:

  1. Ordenen op datum (met laatste eerst)
  2. Iets meer context bieden: we voegen toe of deze speech vanaf het spreekgestoelte komt of van achter de interruptiemicrofoon. Dit is makkelijk te bepalen: Als de speech valt in een scene waarin zij de spreker is, is het vanf het spreekgestoelte.

De aangepaste query wordt dan, met dit resultaat .

for $twitspeech in $FemkesTwitSpeeches
    let $date := $twitspeech/ancestor::root//dc:date
    let $type := if ($twitspeech/ancestor::scene/@speaker = $twitspeech/@speaker) 
                       then 'spreekgestoelte' 
                       else 'interruptie'
    order by $date descending
    return
    concat($date,';',$type,';',$twitspeech//p,'
')

In plaats van omgekeerd chronologisch te ordenen biedt het ook inzicht om op lengte te ordenen.
Dat kan makkelijk door order by $date descending in de query hierboven te vervangen door

let $len := string-length($twitspeech//p)
    order by $len, $date descending

Het resultaat is weer te downloaden. Hieronder haar korste tweets…

2010-03-25;spreekgestoelte;Ja.
2010-03-25;spreekgestoelte;Ja.
2010-02-16;interruptie;Ja.
2009-05-28;interruptie;Ja.
2008-04-15;spreekgestoelte;Ja.
2007-10-09;spreekgestoelte;Ja.
2007-03-08;interruptie;Ja.
2005-06-16;spreekgestoelte;Ja.
2005-04-27;interruptie;...
2004-04-08;interruptie;Ja!

Histogram

Nu we wat inzicht hebben gekregen in de data kunnen we analyses op een wat abstracter niveau gaan doen. Onze vraag was

Nemen Halsema’s Twitter achtige speeches in de Kamer toe?

Om deze vraag te beantwoorden maken we een histogram: voor elk jaar tellen we het aantal Twitter-speeches. Om de invloed van haar totale aantal speeches in een jaar mee te wegen, normaliseren we de absolute aantallen ook. Voor elk jaar delen we haar speeches van Twitter-lengte door haar totale aantal speeches en maken er een percentage van.

Jammer genoeg is de uitkomst niet zo duidelijk, en kunnen we niet spreken van een toename.
Echter, de data bevat veel gaten. Zo missen er 11 dagen uit 2009, waaronder de algemene beschouwingen. Van 2010 hebben we sowieso maar gegevens tot aan de zomer meegenomen.

2010;100;1.31
2009;149;1.96
2008;263;3.45
2007;135;1.77
2006;75;0.99
2005;160;2.1
2004;196;2.57
2003;32;0.42
2001;73;0.96
2000;298;3.91
1999;166;2.18
1998;79;1.04

Informatiebehoefte: Bereken per jaar het aantal speeches van Twitter lengte van Femke Halsema en hun deel als percentage van al haar speeches.

let $years := distinct-values(for $s in $FemkesTwitSpeeches return 
                             substring-before($s/ancestor::root//dc:date,'-'))

for $y in $years
let $twityearcount := count($FemkesTwitSpeeches[contains(ancestor::root//dc:date,$y)])
let $speechcount := count($scope//speech[contains(@speaker,'Halsema')])
let $percentage := round-half-to-even(($twityearcount div $speechcount) * 100,2)
order by $y descending
return concat($y,';',$twityearcount,';',$percentage,'
')

Laatste opmerkingen

  1. In de csv-output is het eigenlijk nodig om textuele velden te escapen. Het probleem is dat we ‘;’ als scheider hebben gekozen, en die kan ook in de speeches staan.
  2. In plaats van zoeken op naam, kunnen we ook het MPid attribuut gebruiken. De MPid van Halsema is 02220. In haar geval maakt het waarschijnlijk niet uit. Met andere namen kan er wel verwarring ontstaan.

Reageer

Je moet ingelogd zijn om te kunnen reageren.