The Digital City

Amsterdam has a new coalition agreement. The paragraph on democratisation and the Digital City was well received - a London-based researcher from Amsterdam liked the plans so much she decided to translate them into English.

The new coalition wants to create a democratic version of the smart city. Citizens should be in control of their data. The city will support co-operations that provide an alternative to platform monopolists. An information commissioner will see to it that the principles ‘open by default’ and ‘privacy by design’ are implemented.

The agreement also lists a number of issues the city is (or was) already working on:

  • City council information will be opened up. In 2015, the city council asked to make documents such as council meeting reports, motions, written questions etc available as open data. Since, some of that data has been made available through Open Raadsinformatie, but as yet no solution has been found for offering all council information in a machine readable form.
  • Freedom of information requests (Wob requests) will be published. Amsterdam started publishing decisions on Wob requests earlier this year; so far three have been [published][wob].
  • Interestingly, Amsterdam wants to use open source software whenever possible. Over ten years ago, Amsterdam planned a similar move, and its plans were sufficiently serious to needle Microsoft. In 2010, the plans foundered on an uncooperative IT department.

All in all, a nice combination of new ambitions and implementation of ‘old’ plans.

De digitale stad

Amsterdam heeft een nieuw coalitieakkoord. De passage over democratisering en de Digitale Stad is goed ontvangen - een Amsterdams-Britse onderzoeker was zo enthousiast dat ze een Engelse vertaling maakte.

De nieuwe coalitie wil een democratische invulling geven aan de smart city. Burgers moeten meer controle krijgen over hun data, er worden niet meer gegevens verzameld dan nodig en er komt steun voor coöperaties die een alternatief willen bieden voor platformmonopolisten. Een informatiecommissaris gaat erop toezien dat de uitgangspunten ‘open tenzij’ en ‘privacy by design’ worden waargemaakt.

Het akkoord noemt ook een aantal onderwerpen waar de gemeente al mee bezig is (of was):

  • Raadsinformatie wordt toegankelijk. In 2015 heeft de gemeenteraad daar al om gevraagd. Sindsdien is een deel van de raadsinformatie beschikbaar via Open Raadsinformatie, maar er is nog geen goede oplossing om alle raadsinformatie in een goed doorzoekbare en analyseerbare vorm beschikbaar te stellen.
  • Wob-verzoeken en documenten worden toegankelijk. Hier is ook al een begin mee gemaakt. Tot nog toe zijn er drie Wob-besluiten gepubliceerd.
  • Ook interessant is dat Amsterdam zo veel mogelijk met open-sourcesoftware gaat werken. Ruim tien jaar geleden was Amsterdam dat al van plan, en dat was serieus genoeg om Microsoft op de kast te jagen. In 2010 leden de plannen schipbreuk op ambtelijke weerstand.

Al met al een mooie mix van nieuwe ambities en uitvoering van ‘oude’ plannen.

Dutch government drops 3D pie charts

The Dutch government has replaced pie charts with bar charts in it’s annual reports, someone noted on Twitter (via @bokami). Pie charts aren’t always a bad choice - contrary to the view of some adherents of the stricter school in data visualisation. But 3D pie charts are really hard to justify and it’s a bit awkward they were still used one year ago.

The charts are from the 2016 and 2017 reports of the Department of Social Affairs and Employment.

How to use Python and Selenium for scraping election results

A while ago, I needed the results of last year’s Lower House election in the Netherlands, by municipality. Dutch election data is available from the website of the Kiesraad (Electoral Board). However, it doesn’t contain a table of results per municipality. You’ll have to collect this information from almost 400 different web pages. This calls for a webscraper.

The Kiesraad website is partly generated using javascript (I think) and therefore not easy to scrape. For this reason, this seemed like a perfect project to explore Selenium.

What’s Selenium? «Selenium automates browsers. That’s it!» Selenium is primarily a tool for testing web applications. However, as a tutorial by Thiago Marzagão explains, it can also be used for webscraping:

[S]ome websites don’t like to be webscraped. In these cases you may need to disguise your webscraping bot as a human being. Selenium is just the tool for that. Selenium is a webdriver: it takes control of your browser, which then does all the work.

Selenium can be used with Python. Instructions to install Selenium are here. You also have to download chromedriver or another driver; you may store it in /usr/local/bin/.

Once you have everything in place, this is how you launch the driver and load a page:

from selenium import webdriver
URL = ''
browser = webdriver.Chrome()

This will open a new browser window. You can use either xpath or css selectors to find elements and then interact with them. For example, find a dropdown menu, identify the options from the menu and select the second one:

XPATH_PROVINCES = '//*[@id="search"]/div/div[1]/div'
element = browser.find_element_by_xpath(XPATH_PROVINCES)
options = element.find_elements_by_tag_name('option')

If you’d check the page source of the web page, you wouldn’t find the options of the dropdown menu; they’re added afterwards. With Selenium, you needn’t worry about that - it will load the options for you.

Well, actually, there’s a bit more to it: you can’t find and select the options until they’ve actually loaded. Likely, the options won’t be in place initially, so you’ll need to wait a bit and retry.

Selenium comes with functions that specify what it should wait for, and how long it should wait and retry before it throws an error. But this isn’t always straightforward, as Marzagão explains:

Deciding what elements to (explicitly) wait for, with what conditions, and for how long is a trial-and-error process. […] This is often a frustrating process and you’ll need patience. You think that you’ve covered all the possibilities and your code runs for an entire week and you are all happy and celebratory and then on day #8 the damn thing crashes. The servers went down for a millisecond or your Netflix streaming clogged your internet connection or whatnot. It happens.

I ran into pretty similar problems when I tried to scrape the Kiesraad website. I tried many variations of the built-in wait parameters, but without any success. In the end I decided to write a few custom functions for the purpose.

The example below looks up the options of a dropdown menu. As long as the number of options isn’t greater than 1 (the page initially loads with only one option, a dash, and other options are loaded subsequently), it will wait a few seconds and try again - until more options are found or until a maximum number of tries has been reached.

def count_options(xpath, browser):
    tries = 0
    while tries < MAX_TRIES:
            element = browser.find_element_by_xpath(xpath)
            count = len(element.find_elements_by_tag_name('option'))
            if count > 1:
                return count
        tries += 1
    return count

Here’s a script that will download and save the result pages of all cities for the March 2017 Lower House election, parse the html, and store the results as a csv file. Run it from a subfolder in your project folder.

UPDATE 23 February 2019 - improved version of the script here.


Dutch election results are provided by the Kiesraad as open data. In the past, the Kiesraad website used to provide a csv with the results of all the municipalities, but this option is no longer available. Alternatively, a download is available of datasets for each municipality, but at least for 2017, municipalities use different formats.

Scraping the Kiesraad website appears to be the only way to get uniform data per municipality.

Since I originally wrote the scraper, the Kiesraad website has been changed. As a result, it would now be possible to scrape the site in a much easier way, and there would be no need to use Selenium. The source code of the landing page for an election contains a dictionary with id numbers for all the municipalities. With those id numbers, you can create urls for their result pages. No clicking required.

Doe-het-zelfonderzoek: fietsenrekken en stoplichten

DTV Consultants doet een oproep: help tellen hoeveel fietsen er geparkeerd staan bij woningen en bij voorzieningen als winkels, scholen, en horeca. Die cijfers willen ze gebruiken om de fietsparkeerkencijfers te actualiseren. Deze kencijfers zijn in 2010 vastgesteld en worden door gemeenten als richtlijn gebruikt.

De vraag van DTV is simpel: tel op een druk moment hoeveel fietsen er geparkeerd staan bij een woning of voorziening, vul een excelformulier in en stuur de gegevens op. Het ideale tijdstip om te tellen verschilt per voorziening, maar het is in ieder geval de bedoeling om te tellen bij mooi weer. DTV zoekt zelf het vloeroppervlak erbij. Als het opgegeven aantal fietsen niet reëel lijkt, nemen ze contact op.

Er zit wel een nadeel aan de kencijfers en de manier waarop ze worden vastgesteld. Als er te weinig fietsenrekken zijn zullen minder mensen de fiets pakken. Als je dan fietsen gaat tellen om te bepalen hoeveel fietsenrekken er nodig zijn, hou je het probleem in stand.

Informatie over het fietstelproject van DTV Consultants vind je hier. Het is de bedoeling dat de tellingen worden uitgevoerd in de maand mei.

Genoeg fietsenrekken? Bereken het zelf

Kan je je fiets niet kwijt? Je kan zelf berekenen of er wel genoeg fietsenrekken zijn in je straat - althans, volgens de bestaande normen:

  • Zoek bij het Kadaster op straatnaam plus gemeente. Klik op het V-tje naast ‘Toon bijbehorende adressen’, rechts op de resultatenpagina.
  • Zoek voor alle adressen de gebruiksfunctie op en zoek de bijbehorende norm op. Hier vind je de landelijke normen uit 2010, hier de normen voor Amsterdam. Amsterdam hanteert bijvoorbeeld voor supermarkten een norm van 4,3 fietsenrek per 100 vierkante meter vloeroppervlak. Deze norm geldt voor het deel van de stad waar het meest wordt gefietst, grofweg binnen de ring en ten zuiden van het IJ.
  • In dit geval is de norm gebaseerd op het vloeroppervlak. Dat kan je ook vinden bij het Kadaster. Voor Jodenbreestraat 21, waar de AH zit, is dat bijvoorbeeld 1.730 vierkante meter.
  • Je komt dan op 4,3 * 1.730 / 100 ofwel ongeveer 75 fietsparkeerplekken.
  • Voor woningen is er een norm per woning en een norm per kamer. Als je weet hoeveel kamers een woning heeft, kan je die norm gebruiken. Let op: je moet per woning ook nog 0,5 à 1 fietsparkeerplek toevoegen voor bezoekers.

In de Jodenbreestraat halen ze die 75 plekken misschien nog wel, dat hangt er vanaf hoeveel fietsen je rekent per fietsparkeervak. Bij een filiaal als de Vijzelstraat (zie foto boven dit artikel) wordt de norm duidelijk niet gehaald. Maar dat is ook wel een lastige plek. Misschien moet hier de stoep wat breder en de weg wat smaller.

In de praktijk zal de berekening soms wat ingewikkelder zijn. Het werkt waarschijnlijk het beste als je de straat goed kent. En verder is de norm niet heilig. Als er in theorie genoeg fietsenrekken zijn maar je kan toch je fiets niet kwijt, dan betekent dat misschien dat de norm te laag is.


Het onderzoek van DTV Consultants is natuurlijk niet het enige voorbeeld waarbij de hulp van het publiek wordt ingeroepen. Denk aan de Fietstelweek waarin duizenden fietsers met een app hun lokatiegegevens beschikbaar hebben gesteld. Die gegevens kan je bijvoorbeeld gebruiken als je wil weten hoe lang fietsers bij een rood licht staan te wachten.

Maar dat kan nog simpeler. Althans, dat hoopt de Britse voetgangersorganisatie Living Streets, zo blijkt uit onderstaande tweet:

RESEARCH: Take a 2 hour random walk in your city/town centre with a stopwatch. Record wait time per signal junction. Need number jncts, average and max wait time. Tweet us results using #waitingfortheman

Hier een van de antwoorden:

Central London. 37 junctions. 53 seconds average. 127 max. #waitingfortheman

Tot nog toe lijken er niet zo heel veel bruikbare reacties te zijn binnengekomen (verder gaan sommige #waitingfortheman-tweets natuurlijk over de Velvet Underground). Maar misschien was het doel vooral om mensen aan het denken - en aan het wandelen - te zetten. Hoe dan ook een leuk project.