Ik heb op mijn werk een leerbudget, ‘t is te zeggen dat ik een vast percentage van mijn tijd kan/mag/moet doorbrengen met dingen bijleren.

Een groot gemak: zo ben ik aan mijzelf verplicht om elke week een blokje tijd opzij te zetten om iets te doen dat ik zou willen bijleren, of om te prutsen met iets dat ik ken om het nog wat beter te leren kennen.

Deze week heb ik geprutst met gegevens op een scherm krijgen. Meestal als ik iets wil datagevisualiseerd krijgen, trek ik mijn plan in Excel of PowerBI of iets dergelijks, of doe ik zeer belachelijk low-level dingen met html/js of python.

Of een combinatie van dingen — pak bijvoorbeeld deze abominatie, die een vies json-bestand inleest in python en er een nog vele keren viezer html-bestand van maakt. Maar het resultaat ziet er (op letterlijk vier pixels na) uit zoals ik wil dat het er uitziet, dus ik trek er mij niets te kloten van aan hoe ik er geraakt ben:

En ik wéét dat het allemaal op een betere manier zou kunnen, natuurlijk. Ik heb bijvoorbeeld hier en daar wel wat dingen met D3 gedaan, maar ook daar was het nooit echt zoals het zou moeten: brutekracht dingen manueel aanmaken in plaats van propere data binding te doen, pakweg.

Dus was mijn doel vanmorgen: ik wil een visualisatie die ik in mijn hoofd had vannacht op een relatief propere manier maken. Dit is wat ik om halfdrie met een slaapdronken vinger op mijn telefoon had getekend:

…en wat zoeken en prutsen verder had ik precies wat ik wou, met hoop en al maar een paar lijnen code:

Eerste een csv-bestand inlezen en voor elke lijn

  • eerst de datum uit de datum-plus-tijd halen
  • dan kijken de hoeveelste dag van het jaar die datum is en dat in een y-waarde steken
  • daarna de tijd uit de datum-plus-tijd halen
  • en kijken hoeveel minuten van middernacht die verwijderd is en dat in een x-waarde steken
  • en dan de duurtijd in minuten nemen en dat in een breedte-waarde steken

en dan

  • in een div met id container
  • een svg-element aanmaken
  • met een bepaalde breedte en hoogte
  • dan alle rechthoeken selecteren (het zijn er voorlopig nog 0) en koppelen met de data
  • daarna in de collectie rechthoeken gaan
  • en rechthoeken toevoegen
  • waarvan de x- en y-positie en breedte bepaald worden door de gegevens in de data
  • met een ingestelde hoogte

En hopla, het doet exact wat ik getekend had:

Akkoord, het is allemaal nog niet proper en zo, maar dat is naast de kwestie. Ik heb 2256 datapunten gevisualiseerd op de manier die ik wou. Al de rest is versiering en goldplating. En als het er op het einde van het jaar dubbel zoveel zijn, zal dat allemaal ook nog altijd werken.

(Als ik data van meer dan één jaar heb, zal ik wél aanpassingen moeten doen, maar dat zien we dan wel.)

Zoals altijd moet ik dan denken aan The Feeling Of Power. Asimov heeft het over een maatschappij waar computers al het rekenen doen, en mensen zich zelfs niet kunnen inbeelden dat zij ook zelf kunnen rekenen. Uiteraard is de situatie hier anders, maar het komt wel op hetzelfde neer: als meer mensen zouden begrijpen hoe sommige problemen kunnen opgelost worden door ze op te delen in alsmaar kleinere stukjes, tot de kleine stukjes doodeenvoudig op te lossen zijn, zouden we zó veel verder zijn in de wereld.

Neem bijvoorbeeld “ik heb 02/09/2021 22:23 als input en ik wil weten de hoeveelste dag van het jaar dat is”:

  • eerst wil ik alleen de datum hebben, dus splits ik “02/09/2021 22:23″ in twee, met ” ” (spatie) als splitsingsteken, en neem ik het eerste van de twee elementen
  • dat geeft mij de tekst “02/09/2021”
  • (ik had ook de eerste 10 karakters kunnen pakken, maar dan zou ik problemen krijgen als er bijvoorbeeld “2/9/2021 22:23” zou staan)
  • javascript kan daar niet automatisch een datum van maken, want het staat in dag/maand/jaar
  • dus splits ik “02/09/2021” in drie, met “/” als splitsingsteken
  • dat geeft mij een lijst met drie stukjes tekst: “02”, “09” en “2021”
  • en maak ik daar een nieuwe datum van, met het derde deel als jaar, het tweede als maand en het eerste als dag (in die volgorde)
  • (maar ik moet wel de tekstjes eerst omzetten naar cijfers)
  • (en de maand loopt van 0 tot 11, dus ik moet 1 aftrekken van het tweede ding)
  • het resultaat van al dat werk is dat ik een datum heb waar javascript iets mee kan doen, maar dan moet ik nog weten de hoeveelste dag van het jaar dat is
  • in een normaal jaar begint januari op dag 1, februari op dag 32, maart op dag 60, april op dag 91, enzoverder; in een schrikkeljaarkomt daar vanaf maart telkens één dag bij
  • dus kan ik weten welke dag van het jaar we zijn door een lijstje te maken van wanneer de maanden in een normaal jaar beginnen, en dan in dat lijstje het juiste getal op te zoeken voor de maand van de datum die ik heb, en daar de dag van de datum (min één) aan toe te voegen
  • en dan te kijken of het jaar een schrikkeljaar is, en de maand maart of later is, en in dat geval er één dag aan toe te voegen
  • (om te weten of dit jaar een schrikkeljaar is, moeten we kijken of het niet deelbaar is door vier (dan is het geen schrikkeljaar), en als het wel deelbaar door vier is, of het deelbaar is door 100 (in welk geval het géén schrikkeljaar is, tenzij het deelbaar is door 400).

Elk van die kleine kleine blokjes zijn bijzonder simpel, en eens het zo uit elkaar getrokken is, is het een kwestie van te kijken hoe de individuele stappen om te zetten naar code. Dat geeft dan bijvoorbeeld dit:

En ja, ik heb hiervoor code van hier en daar op het internet gepikt — het is niet omdat ik weet hoe ik het zou moeten doen als ik van niets begin, dat ik tijd ga verspelen als iemand al een perfect goede oplossing heeft gemaakt. Het belangrijkste is dat ik perfect begrijp wat de code doet, en dat ik niet blindelings dingen kopieer en dan pruts tot het min of meer werkt zoals ik denk dat het zou moeten werken. 🙂

(En ik ben zelfs te leeg om het aan te passen als het werkt, zelfs al zou ik zelf bijvoorbeeld die new Date(+dateArr[2], dateArr[1] - 1, +dateArr[0]) als het langere maar vind ik meer duidelijke parseInt(dateArr[2]) etc. gedaan hebben. Allemaal goed en wel dat javascript een string met een getal erin soms behandelt als een echt getal, maar ik vind dat maar vies.)

Of, om een ander voorbeeld van in-kleine-stukken-trekken-en-er-iets-mee-doen te nemen op basis van deze gegevens: stel dat ik niet een verloop over tijd wil zien, maar een soort heatmap van “wanneer zijn de gebeurtenissen gemiddeld op een dag”. Dan is dat, voor wie begrijpt wat hij aan het doen is en niet zomaar copypaste ergens “gantt-achtige chart in D3” opgezocht heeft, zo simpel als zeggen:

  • maak de individuele lijnen wat hoger
  • en zet ze allemaal bovenop elkaar
  • maar maak ze elk individueel erg doorschijnend

Dat geeft dan (met de kleur naar blauw veranderd in plaats van zwart), iets als dit:

Of een heatmap per week als ik het nummer van de week in de y-waarde zet in plaats van de dag van het jaar en de hoogte en de doorschijnendheid wat aanpas:

Of een heatmap per maand als ik de maand in de y-waarde zet en hoogte en doorschijnendheid opnieuw wat aanpas :

Magisch! 🙂

De volgende stap, als ik nog eens tijd en goesting heb, is het allemaal proper maken: werktijd en niet-werktijd aanduiden, het onderscheid tussen de maanden misschien, en nadenken over kleuren en typografie.

Dan eens.

(Ook hier trouwens: punten voor wie raadt wat de gegevens voorstellen.)