Het Koppelen Van Een Externe Databron

By EDSN

Externe Databron

Deze datastory gaat over het koppelen van een externe databron aan je bestaande Linked Data model. Het stappenplan voor het koppelen van een externe databron is afhankelijk van het formaat waarin die bron gepubliceerd is. Een bron in .csv of Excel formaat (1 of 2 sterren in het 5-sterrenmodel) moet eerst opgehaald worden bij de bron en vervolgens worden omgezet naar een Linked data formaat om deze met de bestaande dataset te kunnen verlinken. Voorbeelden van Linked data formaten zijn rdf/xml, json-ld en turtle. In deze PoV maken we gebruik van de laatste.

Als de externe bron al in een Linked data formaat gepubliceerd is, is de koppeling veel makkelijker te maken. Een voorbeeld van een partij die hier al wat verder mee is, is het Kadaster. Zij hebben hun data gepubliceerd, en stellen API's beschikbaar waarmee je direct aan de Linked Data kan koppelen (zie https://www.kadaster.nl/zakelijk/datasets/linked-data-en-sparql).

Verlinken van csv-bestanden

Op zoek naar een dataset

Het koppelen van een externe databron begint bij het online zoeken naar een geschikte bron. In dit voorbeeld gebruiken we een dataset van het CBS, die te vinden is via deze website: CBS. Het CBS heeft hier zowel de onbewerkte dataset als de metadata als een csv bestand gepubliceerd. We downloaden allebei deze bestanden, zodat we ze lokaal kunnen bekijken.


De data bekijken

Als eerste gaan we kijken naar de onbewerkte dataset. Hier staat de data in 8 verschillende kolommen: ID, WijkenEnBuurten, Gemeentenaam_1, SoortRegio_2, Codering_3, IndelingswijzigingWijkenEnBuurten_4, AantalInstallatiesBijWoningen_5, OpgesteldVermogenVanZonnepanelen_6. Om te begrijpen wat deze kolommen betekenen, hebben we het document met de metadata nodig. Hierin staan de definities van de kolomnamen, zoals bijvoorbeeld:


AantalInstallatiesBijWoningen_5:
Een installatie is een registratie van zonnepanelen op een bepaalde locatie in een bepaald jaar:

  • een registratie in PIR,
  • een registratie in CertiQ,
  • een aanvraag voor de subsidieregeling zonnestroom particulieren
  • een aanvraag voor de btw aftrek regeling zonnepanelen,
  • een aanvraag voor de energie investeringsaftrek regeling.

Na het lezen van deze definities, besluiten we dat er twee kolommen zijn die interessant zijn om aan onze dataset toe te voegen: AantalInstallatiesBijWoningen_5 en OpgesteldVermogenVanZonnepanelen_6. We hebben echter wel een class nodig die we aan ons huidige datamodel kunnen koppelen. Het huidige datamodel bevat postcode informatie, maar de externe databron bevat alleen de gegevens per wijk of buurt. Een oplossing hiervoor is op zoek gaan naar een dataset die de buurt- en wijkcodes koppelt aan postcodes. Ook deze dataset is te vinden bij het CBS. Het downloaden van de data geeft een zip-bestand met daarin zowel een korte beschrijving van de data, als een Excel met onder andere de postcode6, BuurtCode en WijkCode voor verschillende gemeentes. Aangezien dit erg veel data is, gebruiken we voor deze use case alleen de data van postcodes in de gemeente Amersfoort. We kopiëren alleen dit deel van de dataset naar een los csv-bestand.


De data koppelen

De data die we nu verzameld hebben, bestaat uit:

  1. Een csv-bestand met de 1) aantal installaties bij woningen en 2) opgesteld vermogen bij zonnepanelen per buurt- en wijkcode.
  2. Een csv-bestand met de buurt- en wijkcode per postcode in de gemeente Amersfoort.

De volgende stap is het omzetten van deze datasets naar een linked data formaat. In dit geval hebben we er voor gekozen om dit in Python te doen, maar er zijn ook andere tools beschikbaar. Het Python script gebruikt de DirectTurtleWriter.py: een ander Python script dat helpt bij het omzetten van csv files naar triples. Dit is een herbruikbaar component, gebouwd door CGI, dat gebruikt kan worden om de input van classes om te zetten naar ttl-formaat. We beginnen met het definiëren van de prefixes die we gaan gebruiken:

python code
Deze lijst bevat een aantal standaard prefixes (zoals rdf, owl, skos en xsd), en een aantal domeinspecifieke prefixes (cim en ck). Aan de hand van deze prefixes, gaan we de data beschrijven in triples. Dit doen we bijvoorbeeld door het predikaat heeftWijkCode toe te voegen aan onze ontologie. Met dit predikaat willen we een postcode koppelen aan een wijkcode. Daarnaast kunnen we met skos:definition een definitie van een wijkcode toevoegen. Deze halen we uit het CBS bestand met de metadata, en slaan we direct in ons model op. Dit bereiken we met deze Python code:

python code

In het bovenstaande voorbeeld zien we dat het predikaat van het type owl:ObjectProperty is en daarnaast betekent rdfs:domain het subject waar het predikaat bij hoort en rdfs:range het object waarbij het predikaat hoort.

Nadat we op deze wijze het model hebben gedefinieerd, kunnen we de instantie data uit de csv-bestanden gaan omzetten naar triples. Als dit voor zowel de zonnepanelen dataset, als de postcode dataset gebeurd is, hebben we als resultaat twee datasets in .ttl-formaat: één met het kennismodel, en één met de instantiedata over zonnepanelen en postocdes. De Python code voor de ETL van de instantiedata is ten behoeve van de PoV gedeeld met EDSN.


Triples inladen in TriplyDB

De datasets met triples kunnen we in TriplyDB inladen, zodat we deze data integraal kunnen bevragen met onze bestaande dataset. De ingeladen dataset is terug te vinden onder EDSN > Datasets >im-capaciteitskaart. Als je in dat tabblad naar Table gaat, kan je een tabel weergave van de triples bekijken. Om de nieuwe data te bekijken, kunnen we bijvoorbeeld het volgende typen bij de kolom Subject: http://www.edsn.nl/id/Buurt_BU03070100 te vinden in de Table. Je ziet dat deze buurt als buurtnaam Hof heeft, en dat er in totaal 3 zonnepaneelinstallaties zijn. Als we deze buurtcode verslepen naar de kolom Object, zien we de postcodes die horen bij deze buurt.

We hebben nu de externe bron aan onze data toegevoegd. Om het effect van deze toevoeging te bekijken, hebben we een SPARQL query geschreven die data uit beide bronnen gebruikt.

Query voor het integraal bevragen van de data

De onderstaande query heeft data van zowel het standaardmodel (de capaciteitskaart) als onze externe bron (de zonnepanelen) nodig. De query toont per voedingsgebied in Amersfoort het totaal aantal zonnepanelen (zie Opmerking), de generation capacity in queue (Vermogen in wachtrij voor teruglevering) en de generation requests in queue (Unieke verzoeken in wachtrij voor teruglevering).

Het aantal zonnepanelen per voedingsgebied in Amersfoort

Opmerking data mocken

In deze datastory hebben we je laten zien hoe we de data op buurt- en wijkniveau hebben gekoppeld aan postcodes. Er zijn echter buurten die meerdere postcodes hebben. Dit kan zorgen voor incorrecte resultaten wanneer de totalen berekend worden. Omdat het doel van deze use case niet ligt bij het exact berekenen van het aantal zonnepanelen, maar bij het aantonen hoe een nieuwe bron gekoppeld wordt, hebben we ervoor gekozen om de aantallen zonnepanelen per postcode slim te mocken. We hebben hiervoor gekeken naar alle postcodes die in een bepaalde buurt liggen, en het aantal zonnepanelen van deze buurt verdeeld over deze postcodes. Een postcode krijgt zo uiteindelijk een totaal dat wordt gevormd door alle buurten waar deze postcode in ligt.