fvtworkshop

Informatie zoeken in Wikidata

In deze opdracht gaan we aan de slag met SPARQL. Dat klinkt technisch (en dat is het ook), maar het is zo handig dat het de moeite meer dan waard is om daar ervaring mee op te doen, al is het maar om te weten wat kan. We gaan een aantal voorbeelden doorlopen, en hierbij is het knippen en plakken van SPARQL-zoekopdrachten absoluut toegestaan. Sterker nog, dat is vaak beter dan het wiel opnieuw uitvinden.

Een eenvoudige zoekopdracht: Katten

In deze eerste opdracht maak je kennis met een van de manieren om informatie te zoeken in Wikidata. Je kan natuurlijk de zoekfunctie op de Wikidata homepage gebruiken, maar met de Wikidata Query Service (WQS) kunnen we veel gerichter zoeken. Het eerste voorbeeld is zoeken op alle katten in Wikidata. De SPARQL-zoekopdracht daarvoor hoeven we niet zelf te verzinnen, het is namelijk een van de 300+ voorbeelden die de WQS standaard aanbiedt onder de “Example” knop:

Wikidata heeft veel voorbeeld SPARQL zoekopdrachten

Als we hier de ‘Cats’ voorbeeld kiezen, krijgen we de bijbehorende zoekopdracht te zien:

Elke zoekopdracht is geschreven in SPARQL

Je kan die zoekopdracht uitvoeren door op de blauwe ‘‘play’’ knop te clicken met dit als resultaat:

Een lijst van katten in Wikidata

Deze zoekopdracht heeft een vaste structuur, die er in grote lijnen uitziet als:

SELECT ?resultaat WHERE {
  # zoekopdracht
}

We zien hier twee delen: SELECT en WHERE. Het SELECT deel zegt hoe we de informatie willen zien, en het WHERE vertelt ons welke informatie we willen zien. Dat laatste is belangrijk, wat we willen niet alles zien, maar alleen datgene dat aan onze zoekopdracht voldoet.

Bij de zoekopdracht naar katten, willen we weten welk ding (‘‘item’’) in Wikidata een kat is, en wat de naam (‘‘itemLabel’’) van die kat is. De zoekopdracht stelt dat we alleen dingen willen die ‘‘kat zijn’’. De ‘‘zijn’’ in die opdracht is the wdt:P31 (P31 is ‘‘instance of’’, ofwel ‘‘van het type’’). De ‘‘kat’’ in die opdracht is Q146. De zoekopdracht is dus vooral:

?item wdt:P31 wd:Q146

Dit kan je lezen als: alle items (‘‘?item’’) die ‘‘van het type’’ ‘‘kat’’ zijn.

En omdat Wikidata een internationale database is, gebruiken we verder nog een ‘‘SERVICE’’ om een label in onze (zoals ingesteld in je webbrowser) taal te geven.

Dat maakt de volledige zoekopdracht in de SPARQL zoektaal:

#Cats
SELECT ?item ?itemLabel 
WHERE 
{
  ?item wdt:P31 wd:Q146.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
}

Alle soorten haaien

Hierboven zagen we het gebruik van is een (P31) om alle katten te vinden, maar als we alle soorten haaien willen vinden moet een ander gezegde (relatie) vinden. Namelijk, we moeten moedertaxon (P171) gebruiken, want dat is hoe soorten beschreven worden.

Dus de basis is alle soorten die als moedertaxon haai (Q7372) hebben (het sterretje betekent een-of-meer, zodat die moedertaxon relatie meer dan 1 keer kan voorkomen):

?soort wdt:P171* wd:Q7372

We willen ook plaatjes en fotos van die haaien (P18), met 1 voorbeeld per soort (door de combinatie van SAMPLE en GROUP BY), zodat de hele zoekopdracht dan is:

SELECT ?haai ?haaiLabel (SAMPLE(?foto) AS ?foto) WHERE {
  ?haai wdt:P171* wd:Q7372 ;
         wdt:P18 ?foto .
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
} GROUP BY ?haai ?haaiLabel

Probeer het maar!

Karakters uit Harry Potter boeken

De zoekopdracht naar katten is redelijk eenvoudig, maar we kunnen de opdracht steeds complexer maken. Bijvoorbeeld, we kunnen een zoekopdracht maken die alle karakters opzoekt uit Harry Potter-boeken. We moeten dan dus eerst weten welke boeken bij de Harry Potter serie horen. Gelukkig is er een Wikidata item voor de Harry Potter serie (Q8337), zodat we kunne zeggen welke boeken in die serie horen (P179):

SELECT ?boek ?boekLabel WHERE {
  ?boek wdt:P179 wd:Q8337 .
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
}

De volgende stap is dan de link te slaan tussen een boek en de karakters in dat boek. Daar heeft Wikidata het personage (P674) eigenschap voor:

SELECT ?boek ?boekLabel ?karakter ?karakterLabel WHERE {
  ?boek wdt:P179 wd:Q8337 .
  ?boek wdt:P674 ?karakter .
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
}

Dat geeft een mooie lijst:

Lijst van karakters in Harry Potter boeken

En als je nu wil weten wanneer deze personen geboren zijn, hoeven we eigenlijk niet zo heel veel te veranderen. We voegen een regel toe om de geboortedag op te vragen en we halen weg dat hij zegt in welke boeken het karakter voorkomt:

SELECT DISTINCT ?karakter ?karakterLabel ?geboortedag WHERE {
  ?boek wdt:P179 wd:Q8337 .
  ?boek wdt:P674 ?karakter .
  ?karakter wdt:P569 ?geboortedag .
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
}

En omdat we nu datums hebben, kunnen we dit ook als tijdslijn visualiseren (“Timeline” in het Engels):

Het veranderen van hoe de resultaten getoond worden: de tijdslijn

Het resultaat ziet er dan zo uit:

Tijdlijns die laat zien wanneer Harry Potter-karakters geboren zijn

(Voor de ouders, wie is er in jouw geboortejaar geboren?)

Meer visualisaties: Van Gogh

We hebben naast de tabel hierboven ook een tijdslijn als visualisatie mogelijkheid gezien. Maar als we schilderijen van Van Gogh willen zien, willen we graag weten welk schilderij waar hangt. Ook over schilderijen staat heel veel informatie in Wikidata, met dank aan de musea die tegenwoordig afbeeldingen van schilderijen beschikbaar maken, kunnen we leuke dingen doen.

Ten eerste, we zijn dus op zoek naar schilderijen (Q3305213) die door Van Gogh (Q5582) geschilderd zijn. Dit doen we met de zoekopdracht:

SELECT ?schilderij ?schilderijLabel WHERE {
  ?schilderij wdt:P170 wd:Q5582 ; # door Van Gogh
              wdt:P31 wd:Q3305213 . # is een schilderij
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
}

Maar we hebben dus ook de locatie (P276) nodig (inclusief coordinaten (P625)), en als het even kan een plaatje (P18) van het schilderij:

SELECT ?schilderij ?schilderijLabel ?location ?locationLabel ?image ?coordinates WHERE {
  ?schilderij wdt:P170 wd:Q5582 ; # door Van Gogh
              wdt:P31 wd:Q3305213 ; # is een schilderij
              wdt:P276 ?location .
  ?location wdt:P625 ?coordinates . # waar hangt het?
  OPTIONAL { ?schilderij wdt:P18 ?image }
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
}

We zagen al eerder bij de Harry Potter karakters hoe we kunnen wisselen van de standaard tabel naar een tijdslijn. Maar als we plaatjes hebben, kunnen we ook een overzicht van plaatjes maken (“Image Grid” in het Engels):

Plaatjes van schilderijen van Van Gogh

En omdat we ook coordinaten hebben van de lokaties hebben waar het schilderij hangt, een wereldkaart (“Map”):

Wereldkaart met lokaties waar Van Gogh schilderijen hanen

Boeken van voor 1900 door auteurs die in Nederland geboren zijn

De zoekopdrachten kunnen veel meer. Bijvoorbeeld, we kunnen zoeken naar boeken die voor 1900 gepubliceerd zijn en geschreven zijn door schrijvers die in Nederland geboren zijn:

Boeken van voor 1900 door auteurs die in Nederland geboren zijn

Maar dat zijn wel heel veel stappen in een keer. We doen het step voor stap en beginnen met de zoekopdracht. We willen dus alleen dingen die een boek zijn (Q571). Dus we maken een ‘‘variabele’’ en gebruiken net zoals bij de katten P31:

?book wdt:P31 wd:Q571

Dit leest dus als: alle boeken (‘‘?book’’) die ‘‘van het type’’ ‘‘boek’’ zijn.

Maar we willen meer van het boek weten, zoals de auteur:

?book wdt:P50 ?author

We willen ook weten wanneer het boek gepubliceerd is:

?book wdt:P577 ?date

Bovendien moet de auteur in een plaats (P19 is ‘‘geboorteplaats’’) in Nederland (Q55) (P17 is ‘‘land’’) geboren zijn:

?author  wdt:P19 ?birthPlace .
?birthPlace wdt:P17 wd:Q55 .

Daarmee is de hele zoekopdracht:

#defaultView:Timeline
SELECT ?book ?bookLabel ?date ?author ?authorLabel ?birthPlace ?birthPlaceLabel ?image WHERE {
  VALUES ?bookType { wd:Q571 wd:Q3331189 }
  ?book wdt:P50 ?author ; wdt:P31 ?bookType ; wdt:P577 ?date .
  OPTIONAL { ?book wdt:P18 ?image }
  ?author wdt:P19 ?birthPlace .
  ?birthPlace wdt:P17 wd:Q55 .
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
  FILTER (year(?date) < 1900)
}

Beroemde dennebomen in Europa

Een laatste zoekopdracht dan, over beroemde dennebomen (Q12024). Die zijn er niet zo heel veel, maar toch een paar:

Map of Europe with the location of famous pine trees

De bijbehorende zoekopdracht is:

#defaultView:Map
SELECT ?boom ?boomLabel ?locatie ?foto WHERE {
  { ?boom wdt:P279+|wdt:P31+/wdt:P171 wd:Q12024 }
  UNION
  { ?boom wdt:P279+|wdt:P31+ wd:Q12024 }
  ?boom wdt:P18 ?foto ; wdt:P625 ?locatie .
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
}

Opdracht: kan jij deze zoekopdracht aanpassen zodat hij beroemde eikenbomen laat zien?

Tot slot

Een zoekopdracht kan echter op een gegeven moment te moeilijk worden om in kort tijd uit te voeren in de database. Er zijn dan wel wat trucjes, maar die vallen buiten de inhoud van deze workshop.