Aussehen
Daten auswerten
Wie alt ist Heinrich, Ela oder Felix? Für viele Namen haben wir direkt im Kopf, ob es ein Kind, Eltern- oder Großelternteil sein könnte. Das liegt daran, dass Vornamen in Wellen auftreten. Die wenigsten nennen ihre Kinder, so wie ihre Freunde oder Eltern heißen. Aber stimmt das überhaupt, und wie schnell geht so etwas?
Ob das stimmt, zeigen die Zahlen. Du liest echte Daten ein, rechnest, zeichnest und vergleichst.
Die Daten stammen von der Stadt Zürich, die solche Zahlen frei bereitstellt (Open Government Data). Der Datensatz „Vornamen neugeborener Mädchen und Knaben mit Wohnsitz in der Stadt Zürich" (Statistik Stadt Zürich, Lizenz CC0) zählt seit 1993 jedes Jahr, wie oft welcher Vorname bei Neugeborenen vergeben wurde. Für dieses Projekt sind 16 Namen ausgesucht und pro Name beide Geschlechter zusammengezählt, dazu die Gesamtzahl der Geburten pro Jahr.
Was du brauchst
- Das Modul
matplotlib. Wie man Module installiert, steht auf der Übersicht der Projekte. - Die Datei vornamen-zuerich.csv. Speichere sie in einem Ordner und lege dein Programm direkt daneben ab.
Die Daten
Die Datei ist eine CSV-Datei: reiner Text, eine Tabellenzeile pro Zeile, die Spalten durch Semikolons getrennt. Gekürzt sieht sie so aus:
Vorname;1993;1994;1995;…;2025
Laura;31;16;28;…;3
Sarah;25;23;19;…;2
…
Geburten gesamt;3400;3483;3419;…;4535Die erste Zeile nennt die Jahre, jede weitere Zeile ist ein Name mit seinen 33 Zahlen, eine pro Jahr. Die letzte Zeile zählt alle Neugeborenen eines Jahres zusammen, nicht nur die mit diesen 16 Namen.
Stufe 1: Daten einlesen
Für Python ist die Datei zunächst ein langer Text, und mit Zahlen, die aus Buchstaben bestehen, kann es nicht rechnen. Du liest sie deshalb ein, zerlegst den Text in seine Teile und wandelst jede Zahl um. Vier Werkzeuge brauchst du dafür:
open("vornamen-zuerich.csv").read()liest die ganze Datei und liefert ihren Inhalt als einen Text.text.splitlines()schneidet einen Text an den Zeilenumbrüchen auseinander und liefert eine Liste der Zeilen.text.split(";")schneidet einen Text an jedem Semikolon auseinander und liefert eine Liste von Teilen.int(text)macht aus"31"die Zahl31.
In dein Programm schreibst du:
python
daten = open("vornamen-zuerich.csv").read()
zeilen = daten.splitlines()
# Die erste Zeile enthält die Jahre. Davor steht das Wort "Vorname", das lassen wir weg.
jahre = []
for text in zeilen[0].split(";")[1:]:
jahre.append(int(text))
# Jede weitere Zeile: vorn der Name, dahinter die Zahlen.
zahlen = {}
for zeile in zeilen[1:]:
teile = zeile.split(";")
werte = []
for text in teile[1:]:
werte.append(int(text))
zahlen[teile[0]] = werte
print(jahre[0], jahre[-1], len(jahre))
print(zahlen["Emma"])[1:] heißt „ab dem zweiten Element": Der Index 0 wird übersprungen. zahlen ist ein Dictionary: Zu jedem Namen gehört die Liste seiner Zahlen, in der Reihenfolge der Jahre. Die Zahl an Stelle 0 gehört also zu jahre[0], die an Stelle 1 zu jahre[1] und so weiter.
Probier es aus
- Starte das Programm. In der ersten Zeile müssen
1993 2025 33stehen. Kommt einFileNotFoundError, findet Python die Datei nicht: Sie muss im selben Ordner liegen wie dein Programm. - Gib
len(zeilen)aus. Die Datei enthält 16 Namen, trotzdem ist die Zahl größer als 16. Warum? - Gib die Zahlen von
"Laura"aus und beschreibe ihre Entwicklung in einem Satz. - Bei Emma steht für 1993 eine
0. Was bedeutet das? - Wie viele Kinder wurden 1993 geboren, wie viele 2025? Die Zahlen stehen unter dem Namen
"Geburten gesamt". - Gib
zeilen[0].split(";")[1:]und danachzeilen[0].split(";")[2:]aus. Was ist anders?
Stufe 2: Ein Name, drei Kennzahlen
Eine lange Zahlenreihe liest niemand. Du willst eine Zahl, die etwas über die Reihe sagt: Wie viele Kinder insgesamt? In welchem Jahr gab es die meisten? Dafür schreibst du zwei Funktionen:
python
def summe(name):
gesamt = 0
for anzahl in zahlen[name]:
gesamt = gesamt + anzahl
return gesamt
def spitzenjahr(name):
werte = zahlen[name]
beste = 0
for i in range(len(werte)):
if werte[i] > werte[beste]:
beste = i
return jahre[beste]
print(summe("Emma"), spitzenjahr("Emma"))spitzenjahr merkt sich nicht den größten Wert, sondern die Nummer, an der er steht. Mit der Nummer kommt man an den Wert (werte[beste]) und auch ans Jahr (jahre[beste]).
Probier es aus
- Wie oft kommen
"Anna"und"Laura"insgesamt vor, und in welchem Jahr waren sie am häufigsten? - Schreibe eine Funktion
hoechstwert(name), die nicht das Jahr, sondern die Anzahl im Spitzenjahr zurückgibt. - Welche der 16 Namen haben ihr Spitzenjahr nach 2020? Gehe dafür mit einer Schleife durch alle Namen:
for name in zahlen:. Auch"Geburten gesamt"steht inzahlen, ist aber kein Name.
Stufe 3: Ein Diagramm
Eine Zahl wie 2014 sagt, wann etwas am höchsten war. Wie es dazu kam und wie es weiterging, sagt sie nicht. Das zeigt eine Kurve.
Ganz oben im Programm steht diese Zeile:
python
import matplotlib.pyplot as pltAns Ende kommt die Zeichnung:
python
plt.plot(jahre, zahlen["Emma"])
plt.title("Emma in Zürich")
plt.xlabel("Jahr")
plt.ylabel("Neugeborene")
plt.show()plt.plot bekommt zwei Listen gleicher Länge: erst die Werte für die waagerechte Achse, dann die für die senkrechte. Der erste Punkt der Kurve ist (jahre[0], zahlen["Emma"][0]), der zweite (jahre[1], zahlen["Emma"][1]) und so fort. plt.show() öffnet das Fenster und gehört immer ans Ende.
Das ganze Programm bis hierher
python
import matplotlib.pyplot as plt
daten = open("vornamen-zuerich.csv").read()
zeilen = daten.splitlines()
# Die erste Zeile enthält die Jahre. Davor steht das Wort "Vorname", das lassen wir weg.
jahre = []
for text in zeilen[0].split(";")[1:]:
jahre.append(int(text))
# Jede weitere Zeile: vorn der Name, dahinter die Zahlen.
zahlen = {}
for zeile in zeilen[1:]:
teile = zeile.split(";")
werte = []
for text in teile[1:]:
werte.append(int(text))
zahlen[teile[0]] = werte
def summe(name):
gesamt = 0
for anzahl in zahlen[name]:
gesamt = gesamt + anzahl
return gesamt
def spitzenjahr(name):
werte = zahlen[name]
beste = 0
for i in range(len(werte)):
if werte[i] > werte[beste]:
beste = i
return jahre[beste]
plt.plot(jahre, zahlen["Emma"])
plt.title("Emma in Zürich")
plt.xlabel("Jahr")
plt.ylabel("Neugeborene")
plt.show()Probier es aus
- Zeichne die Kurve von
"Emma"und dann die von"Laura". Beschreibe jede in einem Satz. - Stimmt dein Spitzenjahr aus Stufe 2 mit dem höchsten Punkt der Kurve überein?
Stufe 4: Namen vergleichen
Einzelne Kurven erzählen wenig. Spannend wird es, wenn mehrere in einem Bild liegen. Jede Kurve bekommt mit label einen Namen, die Legende (plt.legend()) zeigt sie an. Ersetze die Zeichenbefehle aus Stufe 3, alles außer plt.show(), durch diese:
python
for name in ["Laura", "Emma", "Anna"]:
plt.plot(jahre, zahlen[name], label=name)
plt.title("Drei Namen in Zürich")
plt.xlabel("Jahr")
plt.ylabel("Neugeborene")
plt.legend()Das ganze Programm bis hierher
python
import matplotlib.pyplot as plt
daten = open("vornamen-zuerich.csv").read()
zeilen = daten.splitlines()
# Die erste Zeile enthält die Jahre. Davor steht das Wort "Vorname", das lassen wir weg.
jahre = []
for text in zeilen[0].split(";")[1:]:
jahre.append(int(text))
# Jede weitere Zeile: vorn der Name, dahinter die Zahlen.
zahlen = {}
for zeile in zeilen[1:]:
teile = zeile.split(";")
werte = []
for text in teile[1:]:
werte.append(int(text))
zahlen[teile[0]] = werte
def summe(name):
gesamt = 0
for anzahl in zahlen[name]:
gesamt = gesamt + anzahl
return gesamt
def spitzenjahr(name):
werte = zahlen[name]
beste = 0
for i in range(len(werte)):
if werte[i] > werte[beste]:
beste = i
return jahre[beste]
for name in ["Laura", "Emma", "Anna"]:
plt.plot(jahre, zahlen[name], label=name)
plt.title("Drei Namen in Zürich")
plt.xlabel("Jahr")
plt.ylabel("Neugeborene")
plt.legend()
plt.show()Probier es aus
- Suche zwei Namen, deren Kurven sich kreuzen, und lies im Diagramm ab, in welchem Jahr das passiert.
- Finde einen Namen, der früher häufig war und fast verschwunden ist, und einen, der es umgekehrt gemacht hat. Zeichne beide.
- Zeichne
"Leon"und"Leo"in ein Bild. Beschreibe, wie sich die beiden Kurven zueinander verhalten. - Schreibe eine Funktion
ueberholt(name1, name2), die das erste Jahr zurückgibt, in demname1häufiger vorkommt alsname2. Für"Emma"und"Laura"muss2005herauskommen.
Ein Name, mehrere Schreibweisen
Leon und Leo sind verwandt, Sofia und Sophia klingen gleich. In den Daten sind das getrennte Namen. Sophia fehlt in deiner Datei, wurde 2025 aber ebenfalls 19-mal vergeben, genauso oft wie Sofia. Die Kurve von Sofia zeigt also nur einen Teil der Kinder, deren Name so klingt.
Stufe 5: Anteile statt Anzahlen
Es werden nicht jedes Jahr gleich viele Kinder geboren: 1993 waren es 3400, 2021 waren es 5261, ein Jahr später nur noch 4538. Wenn in einem Jahr mehr Kinder geboren werden, kommt auch jeder Name öfter vor, ohne dass er beliebter geworden wäre.
Zwei Namen mit je 20 Kindern sind in einem kleinen Jahrgang etwas anderes als in einem großen. Fairer vergleichst du deshalb mit dem Anteil: Wie viele von 1000 Neugeborenen haben diesen Namen? Die Funktion kommt vor die Zeichenbefehle, die du wieder ersetzt (alles außer plt.show()):
python
def pro_tausend(name):
ergebnis = []
for i in range(len(jahre)):
ergebnis.append(zahlen[name][i] / zahlen["Geburten gesamt"][i] * 1000)
return ergebnis
plt.plot(jahre, zahlen["Anna"], label="Anzahl")
plt.plot(jahre, pro_tausend("Anna"), label="pro 1000 Geburten")
plt.title("Anna in Zürich")
plt.legend()Die Funktion rechnet für jedes Jahr dasselbe: Anzahl des Namens geteilt durch alle Geburten dieses Jahres, mal 1000. Zurück kommt eine neue Liste, die genauso lang ist wie jahre. Du kannst sie direkt an plt.plot geben.
Normieren
Wer Werte vergleichen will, die auf unterschiedlich großen Grundgesamtheiten beruhen, rechnet sie auf eine gemeinsame Größe um: pro 1000 Einwohner, pro 100 Spiele, in Prozent. Das heißt normieren.
Das ganze Programm bis hierher
python
import matplotlib.pyplot as plt
daten = open("vornamen-zuerich.csv").read()
zeilen = daten.splitlines()
# Die erste Zeile enthält die Jahre. Davor steht das Wort "Vorname", das lassen wir weg.
jahre = []
for text in zeilen[0].split(";")[1:]:
jahre.append(int(text))
# Jede weitere Zeile: vorn der Name, dahinter die Zahlen.
zahlen = {}
for zeile in zeilen[1:]:
teile = zeile.split(";")
werte = []
for text in teile[1:]:
werte.append(int(text))
zahlen[teile[0]] = werte
def summe(name):
gesamt = 0
for anzahl in zahlen[name]:
gesamt = gesamt + anzahl
return gesamt
def spitzenjahr(name):
werte = zahlen[name]
beste = 0
for i in range(len(werte)):
if werte[i] > werte[beste]:
beste = i
return jahre[beste]
def pro_tausend(name):
ergebnis = []
for i in range(len(jahre)):
ergebnis.append(zahlen[name][i] / zahlen["Geburten gesamt"][i] * 1000)
return ergebnis
plt.plot(jahre, zahlen["Anna"], label="Anzahl")
plt.plot(jahre, pro_tausend("Anna"), label="pro 1000 Geburten")
plt.title("Anna in Zürich")
plt.legend()
plt.show()Probier es aus
- Zeichne
zahlen["Geburten gesamt"]allein. Was passiert zwischen 2021 und 2022? - Vergleiche
"Alexander"in den Jahren 1993 und 2021, einmal als Anzahl und einmal pro 1000 Geburten. Ist der Name seltener geworden? Begründe mit Anzahl und Anteil. - Zeichne drei Namen deiner Wahl noch einmal, aber als Anteil. Welche Kurven verändern sich durch die Umrechnung stark, welche kaum?
- Vergleiche für jeden der 16 Namen die ersten fünf Jahre (1993 bis 1997) mit den letzten fünf (2021 bis 2025), als Anzahl und pro 1000 Geburten. Bei genau einem Namen steigt die Anzahl, während der Anteil sinkt. Bei welchem? Tipp:
werte[:5]sind die ersten fünf Elemente einer Liste,werte[-5:]die letzten fünf, undsum(werte)zählt eine Liste zusammen.
Wie es weitergeht
Der vollständige Datensatz enthält alle Vornamen seit 1993, eine Zeile pro Name, Jahr und Geschlecht, über 70000 Zeilen. Die Spalten sind dort durch Kommas getrennt und die Texte stehen in Anführungszeichen. Für solche Dateien gibt es in Python das Modul csv, das schon zu Python gehört.