mitmario.dev

Auswerten

Python Sandbox 4 Min Lesezeit 3 BeispieleLektion 4 von 8

Ein Stromzähler zählt, ein Auto zählt, ein Wasserzähler zählt, und alle zählen nur vorwärts. Was man abliest, ist ein Stand, also wie viel bis zu diesem Tag insgesamt zusammengekommen ist. Wissen willst du aber etwas anderes, nämlich wie viel in einem Monat dazukam.

Und weil niemand am Ersten jedes Monats pünktlich abliest, liegen die Stände an Tagen, wie es gerade passte. Hier wird aus solchen Ständen eine Auswertung. Als Beispiel dient das Fahrtenbuch eines Autos mit Kilometerständen von der Tankquittung, und gefragt sind die Kilometer je Monat.

Ein Stand ist keine Strecke

Ein Stand ist keine Strecke
staende = [48210, 48655, 48902, 49388]

vorher = 0
for stand in staende:
    print(stand - vorher, "km")
    vorher = stand

Gefahren ist man das, was zwischen zwei Ständen liegt, also die Differenz. Von 48210 bis 48655 sind es 445 Kilometer. Deshalb merkt sich die Schleife den Stand davor und zieht ihn ab. Nur fängt sie mit vorher = 0 an, und beim ersten Stand kommen 48210 Kilometer heraus. So weit ist das Auto in seinem ganzen Leben gefahren, nicht in diesem Monat.

Der erste Stand hat keinen Vorgänger. Zu ihm gehört also keine Strecke. Aus fünf Ständen werden vier Strecken, nie fünf.

Paare mit zip

Paare mit zip
staende = [48210, 48655, 48902, 49388]

print(staende[1:])
for vorher, jetzt in zip(staende, staende[1:]):
    print(f"{vorher} bis {jetzt}: {jetzt - vorher} km")

Gebraucht wird jeder Stand zusammen mit dem davor. staende[1:] ist dieselbe Liste ohne den ersten Eintrag, also um eins verschoben. zip aus Lektion 5.3 nimmt beide im Gleichschritt, den ersten mit dem zweiten, den zweiten mit dem dritten und so weiter.

Dort stand auch, dass zip aufhört, sobald die kürzere Liste zu Ende ist, und dass man das leicht übersieht. Hier ist das gewollt. Die verschobene Liste ist eins kürzer, und so entsteht kein Paar für den letzten Stand, nach dem nichts mehr kommt. Vier Stände, drei Paare, und kein vorher = 0.

Welchem Monat gehört eine Strecke?

Jede Strecke mit ihrem Monat
import csv
from datetime import datetime

eintraege = []
with open("fahrtenbuch.csv", encoding="utf-8-sig", newline="") as datei:
    for zeile in csv.DictReader(datei, delimiter=";"):
        eintraege.append({
            "datum": datetime.strptime(zeile["Datum"], "%d.%m.%Y").date(),
            "stand": int(zeile["Kilometerstand"].replace(".", "")),
        })

for vorher, jetzt in zip(eintraege, eintraege[1:]):
    monat = jetzt["datum"].strftime("%m.%Y")
    print(f"{monat}: {jetzt['stand'] - vorher['stand']} km")

Wenn die Stände ein Datum haben, bekommt jede Strecke einen Monat. fahrtenbuch.csv wird wie in Lektion 12.1 gelesen, und aus jeder Zeile wird ein Dictionary mit Datum und Stand. Der Kilometerstand hat einen Tausenderpunkt, und der muss erst weg, bevor int() ihn bekommt. Mit dem Punkt endete int() mit einem ValueError, und float() machte daraus achtundvierzig Komma zwei eins, so wie früher aus 3.000 eine Drei wurde.

Bleibt die Frage, zu welchem Monat eine Strecke gehört. Hier zählt sie zum Monat der zweiten Ablesung. Ein Stand sagt, wie weit das Auto bis zu diesem Tag gefahren ist, und was zwischen zwei Ständen liegt, steht erst am Tag des zweiten fest.

Ganz genau ist das nicht. Die Strecke vom 30.09. bis zum 14.10. landet komplett im Oktober, obwohl ein Tag davon im September lag. Wer es auf den Tag genau braucht, verteilt eine Strecke nach Tagen auf die Monate. Für eine Übersicht reicht die einfache Regel, zumal mit ihr jeder Kilometer genau einmal gezählt wird.

Im September gab es zwei Ablesungen, also zwei Strecken, und deshalb steht der Monat in der Ausgabe zweimal da. In einer Monatsübersicht gehören beide in dieselbe Summe, 445 und 247 sind 692 Kilometer. Dafür passt das bekannte Muster, ein Dictionary mit einer Summe je Monat.

Im November hat niemand abgelesen. Er fehlt deshalb ganz, und seine Kilometer stecken in der Strecke bis zum 03.12., also im Dezember. Auch das folgt aus der Regel. Wer das nicht will, liest einmal im Monat ab.

In so einem Dictionary stehen die Monate in der Reihenfolge, in der sie hineinkamen, und das ist die der Ablesungen. Nach dem Text sortiert man sie hier lieber nicht, denn 01.2027 käme vor 12.2026.

Der Spitzenwert

Fehlt noch die Frage, die du an so eine Übersicht eigentlich hast. In welchem Monat war es am meisten? max mit key beantwortet das in einer Zeile, angewendet auf die items() des Dictionarys je Monat und mit der Strecke als Schlüssel. Heraus kommt das ganze Paar aus Monat und Strecke.

Im Fahrtenbuch wäre das der Dezember, aber nur, weil der November darin mitgezählt ist. Ohne diesen zweiten Blick hielte man ihn für den Monat, in dem am meisten gefahren wurde.

Was die Aufgabe will

Dasselbe mit einem Stromzähler. Zählerstände an unregelmäßigen Tagen, und gefragt sind der Verbrauch je Monat, was er bei 32 Cent je Kilowattstunde kostet, und der teuerste Monat. Eingelesen ist schon alles. Es fehlt der Weg von den Ständen zu den Monaten.

Zum Mitnehmen

Ein Verbrauch ergibt sich erst aus dem Unterschied zwischen zwei Zählerständen. Mit zip(staende, staende[1:]) bekommst du jeden Stand zusammen mit dem davor. Der Unterschied zählt für den Monat der zweiten Ablesung und wird in einem Dictionary je Monat aufsummiert, und den größten Monat findet max() mit key.

Jetzt du

Basis Konto, kostenlos

Zu dieser Lektion gehört eine Aufgabe. Du schreibst den Code selbst, und nach jedem Lauf sagt dir eine Prüfliste, was schon stimmt.

Dafür brauchst du das Basis Konto. Es kostet nichts, und ein Passwort gibt es auch nicht.

In diesem Kurs läuft dein Code auf einem Server. Dafür hat das Basis Konto 1 Stunde im Monat, mehr Zeit gibt es mit dem Premium Konto.

Was in dieser Lektion steckt

  • Artikel mit 3 Beispielen zum Ausprobieren

    Steht hier, ohne Konto lesbar.

  • Aufgabe, dein Code läuft auf einem Server

    Öffnet sich mit dem Basis Konto.