Intermediate · Oplossingen · 28. Functies, lijsten en data in Python StemExpert · Brecht Corbeel · schoolium.me
SE
StemExpert
I28. Functies, lijsten en data in Python — oplossingen
IIntermediate · deel I7 · Programmeren
Oplossingen · hoofdstuk 28Functies, lijsten en data in Python
Eigen functies, lijsten en woordenboeken, en een week meetdata van de klimaatmodule tot een besluit
Uitgewerkte oplossingen bij de 16 opdrachten van het werkboek. Voor de leerkracht, en voor wie zichzelf wil verbeteren nadat hij het eerst zelf probeerde.
b = a hangt een tweede naam aan dezelfde lijst: append via b en a[1] = ... veranderen allebei die ene lijst. c is een kopie van de lijst zoals ze toen was ([1, 2, 3]); daarna veranderde alleen c[0].
28.5
Een woordenboek: de pintabel
Oefenen4Programmeren15 min
De Arduino Mega van de klimaatmodule heeft een vaste pintabel: A0 NTC reservoir, A1 LDR, A2 pH-module, A3 batterijdeler; D2 vlotterschakelaar, D9 pomp (MOSFET).
a
Maak een woordenboek pinnen met de vier analoge pinnen en toon welk onderdeel op A2 zit.
Hoeveel kolommen en hoeveel gegevensrijen staan hier? Welke meting ontbreekt?
Vijf kolommen, vier gegevensrijen (onder de kop). De temperatuur van woensdag 22 april om 12 uur ontbreekt.
b
Schrijf het woordenboek dat csv.DictReader geeft voor de rij van 12 uur.
{'tijdstip': '2026-04-22 12:00', 'temperatuur_C': '', 'vocht_pct': '78', 'verbruik_Wh': '454', 'zon_Wh': '611'}. Alle waarden zijn tekst; de lege cel wordt de lege tekst ''.
c
Welk type heeft rij["zon_Wh"]? Wat is rij["zon_Wh"] + rij["zon_Wh"] voor die rij?
str (tekst). '611' + '611' plakt de teksten aan elkaar: '611611', niet 1222. Eerst int() gebruiken.
d
Een Belgisch rekenblad bewaart CSV vaak met een puntkomma als scheidingsteken en een decimale komma. Hoe zien de kop en de eerste gegevensregel er dan uit? Wat verander je aan je programma?
Lezen met csv.DictReader(bestand, delimiter=";"), en getallen omzetten met float(w.replace(",", ".")); eventueel openen met encoding="utf-8-sig". Een rekenblad kan ook de datum anders schrijven (22/04/2026 6:00): kijk het bestand na in een teksteditor voor je de slicing [:10] gebruikt.
28.8
Foutenjacht in een CSV-programma
Toepassen5Analyseren20 min
Dit programma moet het totale verbruik en de gemiddelde temperatuur van de meetweek tonen. Er zitten vier fouten in; drie geven een foutmelding.
# weektotaal.py - totaal verbruik en gemiddelde temperatuur van de weekimportcsvverbruik=[]temperaturen=[]withopen("klimaatmodule_week.csv",newline="",encoding="utf-8")asbestand:forrijincsv.DictReader(bestand):verbruik.append(rij["verbruik_Wh"])temperaturen.append(float(rij["temperatuur"]))print("totaal verbruik:",sum(verbruik),"Wh")print("gemiddelde temperatuur:",sum(temperaturen)/len(verbruik))
a
Python toont de drie meldingen na elkaar: telkens als je er één verbetert, verschijnt de volgende. Welke fouten zijn het, in volgorde, en hoe verbeter je ze?
De echte meldingen, telkens na de vorige verbetering:
Traceback (most recent call last):
File "weektotaal.py", line 9, in <module>
temperaturen.append(float(rij["temperatuur"]))
~~~^^^^^^^^^^^^^^^
KeyError: 'temperatuur'
Traceback (most recent call last):
File "weektotaal.py", line 9, in <module>
temperaturen.append(float(rij["temperatuur_C"]))
~~~~~^^^^^^^^^^^^^^^^^^^^^^
ValueError: could not convert string to float: ''
Traceback (most recent call last):
File "weektotaal.py", line 12, in <module>
print("totaal verbruik:", sum(verbruik), "Wh")
~~~^^^^^^^^^^
TypeError: unsupported operand type(s) for +: 'int' and 'str'
1. KeyError: de kolom heet temperatuur_C. 2. ValueError: de lege cel van woensdag; test eerst if rij["temperatuur_C"] != "":. 3. TypeError: sum() kan geen teksten optellen; verbruik.append(int(rij["verbruik_Wh"])).
b
Na die drie verbeteringen toont het programma een gemiddelde van 21,07 °C. Waarom is dat fout, en wat is het juiste gemiddelde?
Er wordt gedeeld door len(verbruik) (56 rijen), maar er zijn maar 55 temperaturen: een logische fout zonder melding. Met len(temperaturen):
De beheerder wil weten hoe warm het gemiddeld is in de nacht (0-6 uur), de ochtend (6-12), de middag (12-18) en de avond (18-24), over de hele week.
a
Schrijf een programma met een woordenboek dat voor elk dagdeel een lijst temperaturen verzamelt uit klimaatmodule_week.csv, en daarna per dagdeel het gemiddelde en het aantal metingen toont.
Waarom heeft de middag één meting minder dan de andere dagdelen?
De ontbrekende meting van woensdag om 12 uur valt in de middag: die wordt met continue overgeslagen.
28.10
Van blokken naar dagen
Toepassen5Programmeren20 min
Het verbruik staat per blok van drie uur in een lijst van 56 waarden, acht per dag. (De lijst kopieer je uit het bestand, of je leest ze in zoals in inlezen.py.)
a
Schrijf een functie dagtotalen(waarden, per_dag=8) die telkens acht opeenvolgende waarden optelt en een lijst met zeven dagtotalen teruggeeft. Gebruik slicing.
defdagtotalen(waarden,per_dag=8):"""Tel telkens 'per_dag' opeenvolgende waarden op: van blokken van 3 uur naar dagen."""totalen=[]forstartinrange(0,len(waarden),per_dag):totalen.append(sum(waarden[start:start+per_dag]))returntotalen
b
Schrijf een functie naar_kwh(lijst_wh) die een nieuwe lijst in kWh geeft (2 decimalen), met een lijstomschrijving.
defnaar_kwh(lijst_wh):"""Nieuwe lijst met de waarden in kWh, op 2 decimalen."""return[round(w/1000,2)forwinlijst_wh]
Met de 56 waarden uit het bestand toont het programma:
Controleer je dagtotalen met de tabel van per_dag.py in het handboek.
Dezelfde getallen als de kolom verbruik van per_dag.py: 1663, 2021, 2891, 2517, 1710, 1623, 2127 Wh.
28.11
De vochtigheid in een grafiek
Toepassen4Tekenen25 min
De kolom vocht_pct bevat de relatieve luchtvochtigheid. Op woensdag 22 april (de regendag) meet de module: 00 uur: 83 %, 03 uur: 82 %, 06 uur: 83 %, 09 uur: 78 %, 12 uur: 78 %, 15 uur: 76 %, 18 uur: 80 %, 21 uur: 83 %.
a
Teken de vochtigheid van woensdag op millimeterpapier, met de tijd (uur) horizontaal. Kies een schaal die het papier goed vult.
Horizontaal 0 tot 24 uur (bv. 1 cm per 2 uur), verticaal 75 tot 85 % (1 cm per %): de waarden schommelen maar tussen 76 en 83 %. Een as die bij 0 begint, zou alles plat maken; zet dan wel duidelijk de getallen bij de as.
b
Welke regels van grafiek_week.py verander je om de vochtigheid van de hele week te tekenen? Schrijf ze.
Plus: een lege lijst vocht = [] bovenaan, de hulplijn op 26 weglaten en de titel aanpassen. Zo ziet de week eruit:
c
Vergelijk met de temperatuurgrafiek: wat doet de vochtigheid als het warm wordt? Verklaar met wat je weet over waterdamp in lucht (F6).
Als het warm wordt, daalt de relatieve vochtigheid: warme lucht kan meer waterdamp bevatten, dus dezelfde hoeveelheid damp is een kleiner deel van het maximum. Op de zonnige middagen zakt ze tot rond 60 %; 's nachts stijgt ze tot 85 %. Op de regendag blijft ze hoog, omdat het koeler blijft.
Uitdagen
Uitdagen
transfer, open problemen, leerlijnen combineren
28.12
Habitat: een week in de klimaatmodule
Uitdagen6Habitat50 min
Je analyseert de meetweek als beheerder van de klimaatmodule. Gebruik je eigen programma's (of die van het handboek) op klimaatmodule_week.csv. De module heeft twee LiFePO4-batterijen met samen 2457,6 Wh bruikbare energie (hoofdstuk 20).
a
Maak de tabel per dag: gemiddelde en hoogste temperatuur, verbruik, zonnestroom en saldo.
dag
T gem (°C)
T max (°C)
verbruik (Wh)
zon (Wh)
saldo (Wh)
ma 20/4
22,6
28,1
1663
7465
+5802
di 21/4
21,2
25,1
2021
5105
+3084
wo 22/4
19,3
21,1
2891
1547
-1344
do 23/4
20,3
22,8
2517
3077
+560
vr 24/4
22,2
27,4
1710
6949
+5239
za 25/4
22,9
28,6
1623
7717
+6094
zo 26/4
21,3
25,1
2127
4676
+2549
b
Op welke dag moet de batterij bijspringen? Welk deel van de bruikbare batterij-energie kost die dag? Wordt het de dag erna weer goedgemaakt?
Alleen woensdag: 1344 Wh tekort, dat is 55 % van de 2457,6 Wh. Donderdag levert de zon 560 Wh meer dan de module verbruikt (met het laadrendement van 95 % uit hoofdstuk 16 en 20 ongeveer 532 Wh in de batterij): niet genoeg om alles goed te maken, vrijdag wel ruim.
c
Hoeveel uur was het warmer dan 26 °C, en wanneer? Stel twee maatregelen voor, telkens met hun gevolg voor het energiebudget.
18 uur (6 blokken van 3 uur): maandag, vrijdag en zaterdag, telkens tussen 12 en 18 uur. Maatregelen: het kasdak eerder openen of de ventilatoren vroeger laten draaien (enkele wattuur extra, weinig tegenover het overschot op die zonnige dagen); een schaduwdoek (minder warmte, maar ook minder daglicht, dus moeten de lampen minder dimmen en stijgt het verbruik).
d
Schrijf voor je portfolio een besluit van vijf zinnen: werkt het energiebeheer in deze week, en wat zou je volgende week meten?
Bijvoorbeeld: in deze aprilweek werkte het energiebeheer: de zonnestroom (36,5 kWh) was ruim het dubbele van het verbruik (14,6 kWh), en de lampen dimden op zonnige dagen, waardoor het dagverbruik daalde tot 1,6 kWh. Alleen de regendag vroeg 1,3 kWh uit de batterij, minder dan een kwart. Op drie middagen werd het warmer dan 26 °C: daar is ventilatie nodig. Volgende week meet ik om de 5 minuten, zodat korte pieken zichtbaar worden, en log ik ook de laadtoestand van de batterij.
Zo wordt dit beoordeeld
Tabel
Alle zeven dagen, met eenheden; de ontbrekende meting correct behandeld (niet als 0).
Batterij
Tekort berekend en als deel van 2457,6 Wh uitgedrukt; herstel de dag erna nagegaan.
Warmte
Warme blokken correct geteld (per 3 uur); maatregelen concreet, met gevolg voor verbruik.
Besluit
Onderbouwd met getallen uit de analyse; een zinvolle volgende meting (bv. per 5 minuten, of de temperatuur van het reservoir).
28.13
Een voortschrijdend gemiddelde
Uitdagen6Programmeren25 min
Metingen schommelen. Een voortschrijdend gemiddelde vervangt elke waarde door het gemiddelde van haar en de volgende n − 1 waarden, zodat de lijn gladder wordt. In E21 wordt dat een digitaal filter.
a
Schrijf een functie voortschrijdend(waarden, n=3) die een nieuwe lijst met de gemiddelden van telkens n opeenvolgende waarden teruggeeft. Gebruik slicing.
defvoortschrijdend(waarden,n=3):"""Gemiddelde van telkens n opeenvolgende waarden; de nieuwe lijst is n - 1 korter."""uit=[]foriinrange(len(waarden)-n+1):stuk=waarden[i:i+n]uit.append(sum(stuk)/n)returnuit
b
Pas ze toe op de acht temperaturen van maandag. Hoeveel waarden heeft de nieuwe lijst, en waarom?
Zes waarden: met n = 3 kan het venster maar op 8 − 3 + 1 = 6 plaatsen beginnen.
c
Wat gebeurt er met de hoogste waarde? Is dat erg voor de vraag 'hoe lang was het warmer dan 26 °C'?
Het maximum zakt (van 28,1 naar 26,6 °C): pieken worden afgevlakt. Voor 'hoe lang boven 26 °C' is dat wel erg: je telt dan te weinig warme uren. Een filter kies je dus naar de vraag.
28.14
Onderzoek: hangt het verbruik af van de zon?
Uitdagen7Onderzoeken40 min
De correlatiecoëfficiëntr van Pearson meet hoe goed twee reeksen samen op en neer gaan: r=1 is een perfect stijgend verband, r=−1 een perfect dalend, r=0 geen lineair verband. Met de gemiddelden xˉ en yˉ: r=∑(x−xˉ)2⋅∑(y−yˉ)2∑(x−xˉ)(y−yˉ).
a
Schrijf een functie correlatie(x, y) volgens de formule, met zip en lijstomschrijvingen.
defgemiddelde(w):returnsum(w)/len(w)defcorrelatie(x,y):"""Correlatiecoëfficiënt van Pearson van twee even lange lijsten (tussen -1 en 1)."""gx,gy=gemiddelde(x),gemiddelde(y)teller=sum([(a-gx)*(b-gy)fora,binzip(x,y)])noemer=math.sqrt(sum([(a-gx)**2forainx])*sum([(b-gy)**2forbiny]))returnteller/noemer
b
Bereken r tussen zonnestroom en verbruik (a) over alle 56 blokken en (b) alleen over de 35 blokken van 6 tot en met 18 uur.
importcsvimportmathdefgemiddelde(w):returnsum(w)/len(w)defcorrelatie(x,y):"""Correlatiecoëfficiënt van Pearson van twee even lange lijsten (tussen -1 en 1)."""gx,gy=gemiddelde(x),gemiddelde(y)teller=sum([(a-gx)*(b-gy)fora,binzip(x,y)])noemer=math.sqrt(sum([(a-gx)**2forainx])*sum([(b-gy)**2forbiny]))returnteller/noemeralle_zon,alle_verbruik=[],[]licht_zon,licht_verbruik=[],[]withopen("klimaatmodule_week.csv",newline="",encoding="utf-8")asbestand:forrijincsv.DictReader(bestand):z,v=int(rij["zon_Wh"]),int(rij["verbruik_Wh"])alle_zon.append(z)alle_verbruik.append(v)if6<=int(rij["tijdstip"][11:13])<=18:licht_zon.append(z)licht_verbruik.append(v)print("alle 56 blokken:",round(correlatie(alle_zon,alle_verbruik),2))print("35 blokken met lampen aan:",round(correlatie(licht_zon,licht_verbruik),2))
Uitvoer:
alle 56 blokken: -0.19
35 blokken met lampen aan: -0.98
c
Verklaar het verschil tussen (a) en (b). Wat leert dit over het vergelijken van groepen die op een andere manier verschillen?
Over de 35 blokken met lampen is r = −0,98: een sterk dalend verband, want de lampen dimmen bij daglicht. Over alle 56 blokken is r = −0,19, veel zwakker: 's nachts is de zonnestroom 0 én het verbruik laag (lampen uit), wat in de puntenwolk een groep linksonder geeft die tegen het dalende verband in werkt. Dag en nacht is een derde factor die beide reeksen beïnvloedt. Vergelijk dus alleen blokken die verder gelijk zijn (zoals in een eerlijke proef, hoofdstuk 2), en bewijs een oorzaak met kennis van het systeem, niet met r alleen (hoofdstuk 39).
Zo wordt dit beoordeeld
Functie
Formule correct, met docstring; getest op een eenvoudig geval (bv. x = y geeft 1).
Berekening
Beide r-waarden correct, de selectie van de blokken gemotiveerd.
Interpretatie
Het verschil verklaard met een derde factor (dag en nacht); correlatie niet als bewijs gebracht.
28.15
Ontwerp: het logbestand van de klimaatmodule
Uitdagen6Ontwerpen30 min
In hoofdstuk 30 bouw je een datalogger die de metingen van de klimaatmodule op een SD-kaart schrijft. Ontwerp nu al het CSV-formaat, zodat je analyseprogramma's er meteen mee werken.
a
Welke kolommen neem je op (minstens zes), met welke naam en eenheid? Welke kolom is de sleutel om te groeperen?
Bijvoorbeeld: tijdstip, temperatuur_lucht_C, temperatuur_reservoir_C, vocht_pct, licht_lux, pH, EC_mS_cm, CO2_ppm, verbruik_Wh, zon_Wh, laadtoestand_pct. Groeperen doe je op het tijdstip (datum en uur uit de tekst).
b
Kies het tijdformaat, het decimaalteken, het scheidingsteken en wat er in een cel staat als een sensor faalt. Motiveer.
Tijd als '2026-04-20 06:00' (jaar eerst: sorteert vanzelf juist) en liefst in UTC of met de tijdzone erbij, want bij de overgang naar zomertijd komt een uur twee keer voor. Decimale punt en komma als scheiding: zo leest Python het zonder omzetten. Een lege cel bij een sensorfout, nooit 0 of −127: een lege cel valt op, een verzonnen getal niet.
c
De logger schrijft elke minuut een regel van ongeveer 60 tekens. Hoe groot wordt het bestand na een jaar? Kies: één bestand per dag, per week of per jaar?
Een jaar heeft 525 600 minuten; 525 600 × 60 tekens ≈ 31,5 miljoen bytes, ongeveer 32 MB. Dat past makkelijk op een SD-kaart, maar één groot bestand is lastig om te openen en gaat helemaal verloren als het beschadigd raakt. Eén bestand per dag (±86 kB, zoals 2026-04-20.csv) is een goede keuze.
Zo wordt dit beoordeeld
Kolommen
Relevante grootheden (temperatuur lucht en reservoir, vocht, licht, pH, EC, CO₂, verbruik, zon, laadtoestand), eenheid in de naam, zonder spaties.
Formaat
ISO-tijd (jjjj-mm-dd uu:mm, met tijdzone of UTC), decimale punt en komma als scheiding, lege cel bij een fout; gemotiveerd.
Omvang
Juiste orde van grootte en een onderbouwde keuze van de bestandsgrootte.
28.16
Debat: rekenblad of Python?
Uitdagen5Argumenteren20 min
Een klasgenoot vindt Python overdreven voor de meetweek: 'In een rekenblad heb ik dat gemiddelde in tien seconden, en ik zie meteen alle getallen.' Denk aan het verhaal van de vijf ontbrekende landen.
a
Geef twee sterke argumenten voor een rekenblad en twee voor Python, elk met een voorbeeld uit dit hoofdstuk.
Rekenblad: je ziet alle data meteen, en een grafiek of een som is snel gemaakt, zonder iets te installeren. Python: elke stap staat zichtbaar in de code en is voor een nieuwe week opnieuw te draaien (per_dag.py werkt voor elk bestand in hetzelfde formaat), en ontbrekende waarden en honderdduizenden rijen gaan even vlot als 56.
b
Voor welke taak kies jij wat? Welke controle doe je in beide gevallen om een fout als die van de vijf landen te vermijden?
Rekenblad voor een snelle blik op een klein bestand; Python voor een analyse die je herhaalt, deelt of in een verslag verantwoordt. Controle in beide: tel hoeveel waarden er echt meetellen (len(), of de functie AANTAL), vergelijk met wat je verwacht (8 per dag, 56 per week), en laat iemand anders de berekening overdoen.