Datenverarbeitung mit Python
Slides & Lernziele
Slides: gfif_datenverarbeitung_python.pdf
Lernziele
Prüfungsrelevant ist alles, was in den Lektionen und Übungen behandelt wurde. Die Lernziele unten dienen als Gradmesser und sind nicht unbedingt komplett.
Was ist Datenverarbeitung? Mache Beispiele.
Vor- und Nachteile von Datenauswertung mit Spreadsheets vs. Textfiles und Python
Strings in Zahlen (int und float) umwandeln und umgekehrt.
Unterschiede von ints und floats kennen und wissen, wann man welche verwenden soll.
Erkläre was Textfiles und Binärfiles sind, vergleiche diese und mache Beispiele.
Textdateien in Python einlesen und schreiben können.
Daten mit Python verarbeiten können, z.B.: alle Werte durchgehen, mit diesen Rechnen, in neuer Form speichern.
Textdateiformate CSV & JSON:
Beide Einlesen und Schreiben können.
Bedeutung von CSV und JSON kennen.
Miteinander vergleichen: Vor- und Nachteile?
Dictionaries:
Wissen, sie sind und wie sie aufgebaut sind.
Mit ihnen arbeiten können (Values auslesen, neue Einträge, löschen , alle Keys oder Werte durchgehen …)
Dictionaries mit Listen vergleichen können.
Verbindung Dictionaries ↔ JSON erklären.
JSON-File als Dictionary einlesen, Dictionary als JSON-File speichern
Situationen erkennen, in denen man Try-Except anwenden kann …
… und anwenden
1. Einlesen & Schreiben von Dateien
Theorie
Datei einlesen
Das Code-Beispiel unten zeigt, wie man eine Textdatei einliest und die Anzahl Zeilen zählt, die es hat:
import io
# Oeffne File
with io.open('dateiname.txt', 'r', encoding='utf-8') as infile:
line_count = 0 # Counter, um Anz. Zeilen zu zaehlen
for line in infile: # gehe der Reihe nach alle Zeilen des Files durch
line_count += 1
print(line_count) # gebe am Schluss Anz. Zeilen aus
Bemerkungen:
Wenn Dateien gelesen oder geschrieben werden, müssen sie beim Betriebssystem reserviert werden. Mit with
wird sichergestellt, dass die Datei nicht offen bleibt sondern nach dem Lesevorgang wieder geschlossen wird.
Die Datei (hier 'dateiname.txt') muss sich im gleichen Ordner befinden wie das Python-File.
'r'
bedeutet read, dass das angegebene File nur gelesen und nicht verändert wird.
Datei schreiben
Schreiben (also in Datei speichern) funktioniert ganz ähnlich wie lesen, aber als zweites Argument muss 'w' angegeben werden:
import io
with io.open('dateiname.txt', 'w', encoding='utf-8') as outfile:
for i in range(10):
line = "Zeile " + str(i) + "\n"
outfile.write(line)
Bemerkungen:
str()
verwandelt die Zahl in einen Text.
'\n'
ist der
ASCII-Code für einen Zeilenumbruch. Lässt man diese am Ende der Zeile weg, werden keine Zeilenumbrüche gemacht (mehr dazu unten).
'w' steht für write: es wird in das File geschrieben.
Neben io.open(...)
gibt auch die Funktion open(...)
, die praktisch identisch angewendet wird. Der wichtige Unterschied ist, dass man bei der ersteren die Codierung (typischerweise UTF-8) angeben kann. Dadurch werden z.B. Umlaute wie ä,ö,ü richtig dargestellt.
Zeilenumbrüche
Liest man ein Textfile ein, so endet jede Linie mit einem Zeilenumbruch. Achtung: Je nach System können dafür unterschiedliche ASCII/Unicode-Steuerzeichen verwendet werden. Der Code unten wandelt die Symbole im String line
in die zugehörigen Positionen in der Unicode-Zeichentabelle um:
# String
line = "Hello Wörld\n"
print(' '.join(str(ord(c)) for c in list(line)))
# Output: 72 101 108 108 111 32 87 246 114 108 100 10
Wahrscheinlich wird die letzte Zahl eine $10$ sein, welche für das ASCII/Unicode-Steuerzeichen „Line Feed (LF)“ steht.
Liest man nun ein Textfile ein und printed jede Zeile, so wird es zwischen zwei eigentlichen Zeilen immer noch eine leere haben, da zwei Zeilenumbrüche eingefügt werden: Einen vom letzten Symbol jeder Linie und einen, den der print()
-Befehl einfügt. Um dies zu vermeiden, gibt es zwei Möglichkeiten:
Zeilenumbrüche am Ende der Zeile entfernen: line = line.replace('\n','')
print ohne zusätzlichen Zeilenumbruch: print(line,end='')
Auftrag A
Aufgabe A1: File Einlesen
Erstelle mit einem beliebigen Editor ein Textfile mit Endung .txt und schreibe einige Zeilen Text hinein.
Speichere es im gleichen Ordner, in dem du das zugehörige Python-File speichern wirst.
Schreibe einen Python-Code, der dieses File einliest und folgendes macht:
Anzahl Zeilen Text bestimmen und ausgeben.
Jede Zeile in der Konsole ausgibt. Stelle sicher, dass keine überflüssigen Zeilenumbrüche angezeigt werden (siehe Theorie oben).
Aufgabe A2: File schreiben
Schreibe einen Python-Code, der eine Liste mit mehreren Strings beinhaltet: s = ['Hallo Welt','Wie geht es dir?',...]
Die Strings in dieser Liste sollen dann in ein neues Textfile geschrieben werden. Jeder Eintrag der Liste steht in einer eigenen Zeile.
Aufgabe A3: Buch einlesen
Lade die Bibel herunter:
-
-
Lese sie in Python ein.
Wie viele Zeilen enthält das Buch?
Gebe die ersten 20 Zeilen aus. Stelle wieder sicher, dass keine überflüssigen Zeilenumbrüche angezeigt werden.
Erstelle eine Version des Buchs, welche nur aus Grossbuchstaben besteht (siehe Tipps unten).
Tipps
Zusatzaufgaben
Mache eine Häufigkeitsanalyse der Buchstaben in der Bibel. Unterscheide nicht zwischen Gross-/Kleinbuchstaben, eliminiere Umlaute und andere Spezialbuchstaben (z.B. a zu ae, ß zu ss). Welcher Buchstabe kommt am seltenesten vor? Tipp: Verwende ein Dictionary.
In der Theorie oben gibt es eine sehr kompakte Zeile Code, mit dem man von einem String die zugehörigen Unicode-Zeichen ermitteln kann. Schreibe selbst (ohne diese Zeile anzuschauen) einen mehrzeiligen Code, der dies macht. Vergleiche dann deinen Code mit dieser Zeile und versuche diese nachzuvollziehen.
2. Notentabelle
Theorie I
CSV-Files
Daten werden oft in CSV-Files gespeichert, wobei CSV für Comma Separated Values steht. Ein CSV-File ist ein einfaches Textfile, in dem die Werte durch ein Sonderzeichen, genannt Delimiter, getrennt werden. Wie der Name suggeriert, verwendet man dafür oft ein Komma. Dies ist problematisch, wenn man das Komma bereits verwendet, um Nachkommastellen von Zahlen abzutrennen. Gerne verwendet man deshalb ein Semikolon.
String-Manipulation
Folgende Befehle sind sehr hilfreich, um die Strings, die man aus Dateien einliest, so zu manipulieren, dass man gut mit ihnen arbeiten kann:
x = li[3]
: Bestimmtes Element aus Liste auslesen
teil_li = li[3:8]
: Teilliste auslesen
int(s)
: String s
der Zahl beinhaltet in ganze Zahl (integer) umwandeln
float(s)
: String s
der Zahl beinhaltet in Zahl mit Nachkommastellen (float) umwandeln
str(z)
: Zahl z
in String umwandeln
s = s.replace('a','A')
: Zeichen in String s
durch anderes ersetzen
l = s.split(',')
: String s
immer dort wo ein ,
(oder welches Zeichen auch immer man angibt) auftritt aufgeteilt und in Liste l
gespeichert
s = s.strip()
entfernt links und rechts im String alle Leerschläge. Funktioniert auch für andere Zeichen, z.B. s = s.strip('_')
. Mit lstrip
resp. rstrip
nur von links, resp. rechts, Zeichen entfernen.
CSV-Files lesen & schreiben
Mithilfe des csv-Moduls können CSV-Dateien einfach eingelesen werden:
import csv
import io
with io.open('dateiname.csv', 'r', encoding='utf-8', newline='') as csv_file:
# Create a CSV reader object, change delimiter if elements are separated by different symbol than comma ','
reader = csv.reader(csv_file,delimiter=',')
# Read each row in the CSV file, creates list of all elements (separated by delimiter) in line
for row in reader:
print(row)
Beachte den Parameter newline=''
. Dieser ist optional, vermeidet aber Probleme, die auftreten können, wenn CSV-Dateien zwischen verschiedenen Systemen (z.B. Windows und Mac) ausgetauscht werden, da diese beiden Plattformen Zeilenumbrüche anders handeln.
In ein CSV-File schreiben geht dann wie folgt. Erstelle zuerst eine Liste, die die Daten beinhaltet: Diese besteht wiederum aus Listen, die die Inhalte jeder Zeile beinhalten sollen:
data = [['Hans',42],['Monika',37]]
Diese Liste kann nun ganz einfach in ein CSV-File geschrieben werden
import csv
import io
with io.open('dateiname.csv', 'w', , encoding='utf-8', newline='') as csv_file:
# Create a CSV writer object
writer = csv.writer(csv_file,delimiter=',')
# Write the data to the CSV file
writer.writerows(data)
Das Beispiel oben erzeugt dann ein CSV-File mit Inhalt
Hans,42
Monika,37
Neben der Codierung „UTF-8“ gibt es auch „UTF-8 with BOM“. UTF-8 with BOM (Byte Order Mark) ist eine Variante der UTF-8-Kodierung, die einen speziellen Marker am Anfang der kodierten Daten enthält. Der Byte Order Mark ist eine Byte-Folge (0xEF, 0xBB, 0xBF), die die Byte-Reihenfolge und das verwendete Kodierungsschema angibt.
Auftrag B
Schreibe ein Programm, welches eine Notentabelle im CSV-Format einliest. Für jedes Fach wird (falls möglich) der Durchschnitt berechnet und auf halbe Noten gerundet. Daraufhin werden berechnet/ermittelt:
Sämtliche Resultate, inkl. gerundeter Noten der einzelnen Fächer, werden in ein neues CSV-File geschrieben.
Beispiel
Für die Notentabelle
- notentabelle.csv
Deutsch,4.5,4,5.5,5.5
Französisch,5,5.5,5,4.5
Englisch,3,5,1,
Mathematik,3,2,3,
Biologie,5,4.5,4.5,
Chemie,,,,
Physik,6,6,,
Geschichte,4.5,4,4,
Geographie,5,4,5,
Wirtschaft und Recht,3.5,2.5,3,
Bildnerisches Gestalten,5,6,5,
Musik,6,,,
Informatik,6,6,,
Schwerpunktfach,4.5,,,
Ergänzungsfach,6,,,
Erhält man das Output-File:
Deutsch,5.0
Französisch,5.0
Englisch,3.0
Mathematik,2.5
Biologie,4.5
Chemie,
Physik,6.0
Geschichte,4.0
Geographie,4.5
Wirtschaft und Recht,3.0
Bildnerisches Gestalten,5.5
Musik,6.0
Informatik,6.0
Schwerpunktfach,4.5
Ergänzungsfach,6.0
Anz UG,3
Pluspunkte,13.0
Minuspunkte (doppelt),7.0
Promotion,promoviert
Das Programm wird am Schluss einige Zeilen Code haben, weshalb es wichtig ist, dass du die Sache strukturiert angehst. Daher teilen wir den Auftrag in mehrere Teile ein.
Teil I
Ziel: Für jedes Fach durchschnitt berechnen und ausgeben (printen).
Befolge die Schritte und Tipps unten:
Erstelle ein CSV-File mit einer Notentabelle. Achte darauf, dass unterschiedliche Fächer unterschiedlich viele Noten haben und es Fächer ohne Noten gibt. Verwende z.B. die Notentabelle aus dem Beispiel oben.
Lese das CSV-File mit der Notentabelle ein. Verwende dazu das csv-Module (siehe Theorie oben).
Gehe mit einer Schleife jede Zeile durch.
Für jede Zeile erhält man eine Liste à la ['Mathematik', '3', '2', '3', '']
Extrahiere das Fach und die Noten (siehe Tipp A)
Berechne für das Fach den Notendurchschnitt (siehe Tipp B)
Runde den Durchschnitt auf halbe Noten (siehe Tipp C)
Gebe Fach und Durchschnitt in der Konsole aus
Tipps
Tipp A:
Tipp B:
Eliminiere oder ignoriere alle leeren Einträge ''
.
Berechne Durchschnitt nur, wenn überhaupt Noten vorliegen.
Für die Berechnung kann man (muss man aber nicht) eine Funktion calc_average(grades)
schreiben, die die Note für eine Liste mit Noten grades
berechnet.
Zahlen-Strings (z.B. '3.5') in Zahl umwandeln mit float()
(Zahl mit NKS), damit man mit diesen rechnen kann.
Durchschnitt: Noten aufsummiert, dividiert durch Anzahl Noten
Tipp C:
Anfänger: verwende die Funktion round_to_multiple(...)
unten
Fortgeschrittene: Versuche zuerst selbst, eine Funktion zu schreiben, die dir auf halbe Noten rundet.
def round_to_multiple(x, mul):
return round(x / mul) * mul
Teil II
Ziel: Durchschnitte in neuem File speichern
Speichere die in Teil I berechneten Notendurchschnitte inkl. Fächernamen in einem neuen File notentabelle_resultate.csv
.
Speichere dazu die Fächernamen und Durchschnitte in einer Daten-Liste: Jeder Eintrag dieser Liste soll dann einen Eintrag im neuen CSV-File sein, z.B.: data = [['Deutsch',5.0],['Französisch',5.0]]
. Mit csv.writer
kann diese Liste mit einem einzigen Befehl ins File geschrieben werden (siehe Tipps oben).
Teil III
Ziel: Restliche Dinge berechnen und in File speichern.
Bestimme die Anzahl UGs, speichere in Variable
Bestimme die Pluspunkte, speichere in Variable (siehe Tipps unten)
Bestimme die Minuspunkte (doppelt), speichere in Variable
Bestimme Promotion, speichere in Variable
Füge passende Einträge zu data-Liste hinzu
Sollte jetzt automatisch in CSV-File geschrieben werden (mit Code von Teil II)
Das erwartete Output-CSV sollte etwa wie unten angegeben aussehen
Tipps
Erwartetes Output-CSV
Deutsch,5.0
Französisch,5.0
Englisch,3.0
Mathematik,2.5
Biologie,4.5
Chemie,
Physik,6.0
Geschichte,4.0
Geographie,4.5
Wirtschaft und Recht,3.0
Bildnerisches Gestalten,5.5
Musik,6.0
Informatik,6.0
Schwerpunktfach,4.5
Ergänzungsfach,6.0
Anz UG,3
Pluspunkte,13.0
Minuspunkte (doppelt),7.0
Promotion,promoviert
Theorie II
Try-except
Wir haben gesehen, dass man mit int(...)
und float(...)
Zahlenstrings (z.B. '5'
oder '3.14159'
) in Zahlen umwandeln kann. Dies geht aber nur, wenn man diese Funktionen auf passende Strings anwendet, ansonsten gibt es einen Fehler und das Programm bricht ab. Beispiele:
int('6')
: funktioniert
float('4.5')
: funktioniert
int('4.5')
: Fehler! Weil $4.5$ keine ganze Zahl
int('')
oder float('ksr')
Fehler! Weil String leer resp. Text beinhaltet.
Ist man nicht sicher, ob man einen Fehler erhalten wird, so kann man try-except anwenden, mit dem man Fehler abfangen kann:
st = '4.5' # define string that may or may not contain a number
try: # try ...
nr = float(st) # ... to convert string into float
print(nr) # if works, print number
except: # if float(st) raises error (exception), code in except is executed
print('String does not contain number')
Auftrag B (weiter)
Teil IV
Studiere die Theorie oben zum Thema Try-Except und mache dich mit dieser vertraut:
Tippe das entsprechende Code-Snippet ab (nicht copy-paste).
Teste es für verschiedene Strings, wie z.B. st = '3.14159'
, st = 'ksr'
, s = 4cm
.
Verwende es, um eine Notenliste wie ['5.5','6','5','','','']
umzuwandeln in [5.5,6,5]
. Mit try-except ist es nicht mehr nötig, zu überprüfen, ob man float()
überhaupt auf ein Element anwenden kann. Man macht es einfach und schaut dann, ob ein Fehler auftritt oder nicht.
Teil V
Mache eine Kopie deines Codes zur Notentabelle und passe diesen wie unten beschrieben an.
Verwende try-except für die …
Aufbereitung der Notenlisten (['5.5','6','5','','','']
zu [5.5,6,5]
)
Berechnung des Durchschnitts (ergibt Fehler, Division durch 0, wenn keine Noten beinhaltet)
3. Gemeinden
In diesem Auftrag geht es darum, einen grösseren Datensatz, der Informationen zu allen Gemeinden der Schweiz beinhaltet, einzulesen und auszuwerten.
Theorie
CSV-Datensätze haben typischerweise einen Header, der angibt, welche Daten sich in welchen Spalten befinden. Zum Beispiel sehen die ersten Zeilen des Datensatzes dieser Übung wie folgt aus:
['Gemeinde', 'Kanton', 'Einwohner', 'Fläche']
['Aadorf', 'TG', '9216', '19.93']
['Aarau', 'AG', '21726', '12.36']
['Aarberg', 'BE', '4626', '7.94']
['Aarburg', 'AG', '8577', '4.40']
Die erste Zeile ist der Header und muss für die Datenverarbeitung ignoriert werden:
with open(...) ...:
reader = csv.reader(csv_file)
header = next(reader)
...
Der Header wird so in der Variablen header
gespeichert. Nachher kann man wie bisher mit einer for-Schleife den Datensatz durchgehen.
Aufgabe C
-
Lese die Datei in Python ein.
Schreibe einen Code, der die Fragen unten beantwortet und die Antworten in passend formatierten Strings in eine Textdatei gemeinden_resultate.txt
schreibt (alle Antworten zusammen in einem File).
Fragen:
Wie viele Gemeinden gibt es in der Schweiz?
Wie viele Einwohner hat die Schweiz?
Welche Gemeinde hat am meisten Einwohner?
Welche Gemeinde hat die grösste Fläche?
Wie viele Städte (mehr als 10000 EW) gibt es in der Schweiz?
Zusatzaufgaben:
Auf welchem Platz im Ranking 'Gemeinden mit den meisten Einwohnern' steht Romanshorn?
Es gibt mehrere Ortschaften, die gleich viele Einwohner haben. Welches sind die beiden Orte mit den meiden Einwohnern, die identisch sind?
Antworten ohne Code
Anz. Gemeinden: 2145
Einwohner Schweiz: 8670125
Am meisten Einwohner hat Zürich mit 421878 Einwohnern.
Grösste Fläche hat Scuol mit 438.76 km^2 Fläche.
Anzahl Städte (> 10000 EW): 164
Zusatzaufgaben:
4. Dictionaries & JSON
Theorie
Dictionary
Ein Dictionary (kurz Dict) ist eine Datenstruktur in Python, die es ermöglicht, Daten als Schlüssel-Wert-Paare (key:value) zu speichern. Jeder Schlüssel in einem Dictionary muss eindeutig sein, und er wird mit einem Wert verknüpft. Dictionaries sind äusserst vielseitig und nützlich, um verschiedene Arten von Daten zu organisieren. Ein Dictionary findet für einen Key den zugehörigen Value sehr schnell, da Dictionaries mit Hash-Tables arbeiten (mehr dazu später).
Mit einem Dictionary kannst du zum Beispiel speichern, wie viele Früchte du noch hast:
fruits = {'Apfel': 5, 'Banane': 3, 'Orange': 2}
Jedem Key wird also ein Wert zugeordnet. Zum Beispiel hat der Key „Banane“ den Wert $3$.
Über den Key kann man nun auf die Werte zugreifen:
print("Ich habe noch " + str(fruits['Banane']) + " Bananen.")
Isst man eine Banane, kann man den zugehörigen Wert anpassen:
fruits['Banane'] = 2
print(fruits) # -> {'Banane': 2, 'Orange': 2, 'Apfel': 5}
Wenn ein Schlüssel nicht vorhanden ist, führt der Zugriff zu einem Fehler. Um dies zu vermeiden, können Sie die Methode get() verwenden, die einen Standardwert zurückgibt, wenn der Schlüssel nicht gefunden wird:
print(fruits.get('Birne', 0)) # Gibt den Wert 0 aus, da 'Birne' nicht im Dictionary enthalten ist
Mit dem Keyword in
kann man überprüfen, ob ein Key im Dictionary vorhanden is:
if 'Banane' in fruits:
print('Ich habe noch Bananen zuhause.')
else:
print('Ich muss Bananen kaufen.')
Neue Einträge können direkt über den neuen Key generiert werden:
fruits['Kiwi'] = 7
print(fruits) # -> {'Banane': 2, 'Orange': 2, 'Kiwi': 7, 'Apfel': 5}
Mit fruits.keys()
und fruits.values()
kann man alle Key-Value-Paare systematisch durchzugehen:
# Option 1
for key in fruits: # oder for key in fruits.keys()
print(key, fruits[key])
# Option 2
for key,value in fruits.items():
print(key,value)
Die Befehle .keys()
und .values()
erstellen „dict_key“ Objekte (zumindest in neueren Python Versionen). Möchte man aber eine Liste mit allen Keys oder Values eines Dicts haben, muss man diese mit der list()
-Funktion noch in solche umwandeln:
key_list = list(fruits.keys())
value_list = list(fruits.values())
Interessiert man sich nur für die Werte, kann man auch einfach diese durchgehen:
for value in fruits.values():
print(value)
Mit dem Keyword del
kann man Einträge aus dem Dictionary löschen:
del fruits['Banane']
print(fruits) # -> {'Orange': 2, 'Kiwi': 7, 'Apfel': 5}
JSON
JSON steht für JavaScript Object Notation und ist ein Datenformat (my_file.json
), welches sich zur Speicherung von Daten eignet. Es ist eine Alternative zu CSV und besonders für etwas komplexere, z.B. verschachtelte, Datensätze geeignet.
JSON repräsentiert Daten in Form von Schlüssel:Wert-Paaren (Key:Value) und unterstützt verschiedene Datentypen wie Strings, Zahlen, Booleans (True/False), Listen und Dictionaries. Es ähnelt daher der Struktur von Python-Dictionaries.
Hier zwei Beispiele für JSON-Daten:
{
"Bern": 3000,
"Lausanne": 1000,
"Zurich": 8000,
"Basel": 4000,
"Genf": 1200
}
{
"Genthod": {
"area": 2.81,
"inhabitants": 2893,
"canton": "GE"
},
"Gams": {
"area": 22.28,
"inhabitants": 3587,
"canton": "SG"
},
"Rorbas": {
"area": 4.5,
"inhabitants": 2885,
"canton": "ZH"
},
...
}
JSON-Files können in Python ganz einfach in Dictinaries eingelesen werden:
import json
# LESEN von JSON-File
with open("my_file", "r") as json_file:
data = json.load(json_file) # lade File in Dictionary data
Hat man in Python ein Dictionary, so kann man dieses ganz einfach in ein JSON-File schreiben:
import json
data = {} # wichtig: muss DICTIONARY sein!
# SCHREIBEN von JSON-File
with open('my_file.json', 'w', encoding='utf-8') as json_file:
json.dump(data, json_file, indent=4, ensure_ascii=False) # indent: Anz. Leerschlaege zum Einruecken
Auftrag D
Aufgabe D1
Studiere die Theorie oben zu Dictionaries und JSON und löse dann die Aufgabe unten:
Die fünf bevölkerungsstärksten Städte mit ihrer jeweiligen Postleitzahl sind Zurich (8000), Genf (1200), Basel (4000), Lausanne (1000) und Bern (3000). Starte mit dem Dictionary:
big_5 = {'Zurich': 9999, 'Weinfelden': 8570, 'Basel': 4000, 'P3Rn': 3000}
Korrigiere das Dictionary in möglichst wenigen Schritten.
Speichere das fertige Dictionary in einem JSON-File.
Aufgabe D2: Voci-Trainer
Ziel ist, einen einfachen Voci-Trainer zu implementieren.
Version 1
Erstelle zuerst ein Dictionary word_pairs
. Der Key ist immer das Deutsche Wort (z.B. 'Katze') und der Value die englische Übersetzung ('cat'). Füge deinem Dictionary mindestens zehn solche Key-Value-Paare hinzu.
Gehe nun einmal das Dictionary durch (Tipp: In der Theorie oben wird erklärt, wie man ein Dict durchgehen kann.). Fordere die Benutzerin auf, das deutsche Wort auf Englisch zu übersetzen.
Die Eingabe wird dann mit der korrekten Antwort verglichen …
… und es wird eine entsprechende Ausgabe gemacht, z.B. „Antwort korrekt“, „Antwort leider falsch“.
Speichere den Score. Speichere dazu in zwei Variablen die Anzahl korrekten und falschen Antworten. Gebe den Score nach jeder Ausgabe aus.
Version 2
Mache eine Kopie der letzten Version.
Das Spiel soll nun unendlich lange gespielt werden können. In jedem Durchgang soll ein zufälliges Wort ausgewählt werden. Siehe Tipp unten.
Alles andere soll gleich bleiben wie bei der letzten Version.
Tipp
Unendlich lange spielen: while True
Endlosschleife!
Zufallswort: Mit my_dict.keys()
erstellst du eine Liste mit allen Keys des Dictionaries. Mit random.choice(my_list)
wählst du aus einer Liste ein zufälliges Element aus. Vergesse nicht, ganz oben das random-Modul zu importieren.
Version 3 (optional, Pflicht für TALITs)
Mache eine Kopie der letzten Version und erweitere den Code wie folgt:
Für jedes Wort soll unabhängig der Fortschritt (Progress) gespeichert werden (siehe Tipps unten).
Übersetzt man ein Wort korrekt/falsch, so soll dessen Progress um eins erhöht/verringert werden. Negativer Progress soll verhindert werden.
Hat ein Wort einen maximalen Progress (z.B. $3$) erreicht, wird es aus dem Dict entfernt und nicht mehr trainiert.
Hat man alle Wörter vollständig gelernt, wird einem gratuliert und das Programm ist zu Ende.
Optional:
Nach jeder Frage soll man abbrechen können. Aktueller Stand wird dann in JSON-File geschrieben. Lösche keine Wörter aus dem File.
Soll am Anfang des Spiels den Progress zurücksetzen können, damit man alle Wörter wieder lernen kann.
Implementiere eigene Features.
Tipp
Die Values eines Dictionaries können selbst wieder Dictionaries sein. Jedes deutsche Wort (key, z.B. 'Katze') soll als Value ein Dict haben, welches zwei Key-Value-Paare beinhaltet: 'en':'cat'
und 'progress':0
Aufgabe D3: Gemeinden
Teil I
Lese den Gemeinden-Datensatz aus dem CSV-File von weiter oben ein und speichere die Daten in einem Dictionary mit der folgenden Form:
{
"Genthod": {
"area": 2.81,
"inhabitants": 2893,
"canton": "GE"
},
"Gams": {
"area": 22.28,
"inhabitants": 3587,
"canton": "SG"
},
"Rorbas": {
"area": 4.5,
"inhabitants": 2885,
"canton": "ZH"
},
...
}
Speichere dann das Dict in einem JSON-File gemeinden.json
.
Teil II
Öffne nun in einem neuen Python-File das JSON-File gemeinden.json
aus dem ersten Teil der Aufgabe und lese dessen Daten in ein Dictionary ein. Beantworte mit dessen Hilfe die folgenden Fragen:
Wie viele Einwohner hat Aarwangen?
Welche Fläche hat Estavayer?
Welche Gemeinde hat $314$ Einwohner?
Wie viele Gemeinden liegen im Kanton Tessin?
Lösungen kurz
$4638$
$44.89$ km$^2$
Courchavon (obwohl Pitown passender wäre)
$106$
Lösungen
Lösungen A
Aufgabe A1
import io
with io.open('dateiname.txt', 'r', encoding='utf-8') as infile:
line_count = 0
for line in infile:
line_count += 1
print(line_count,end='')
Aufgabe A2
poem = ['Hallo Welt','Wie geht es dir?','Nicht so gut','Danke der Nachfrage']
with io.open('my_great_poem.txt', 'w', encoding='utf-8') as outfile:
for line in poem:
outfile.write(line + '\n')
Aufgabe A3
Lösung 1
import io
bible_caps = []
with io.open('bibel_martin_luther_1912.txt', 'r', encoding='utf-8') as infile:
line_count = 0
for line in infile:
if line_count < 20: # ersten ... Zeilen ausgeben
print(line,end='')
line_count += 1
# in caps umwandeln und in Liste speichern
bible_caps.append(upper(line))
print(line_count)
with io.open('bibel_caps.txt', 'w', encoding='utf-8') as outfile:
for line in bible_caps:
outfile.write(line)
Lösung 2
import io
with io.open('bibel_martin_luther_1912.txt', 'r', encoding='utf-8') as infile:
with io.open('bibel_caps2.txt', 'w', encoding='utf-8') as outfile:
line_count = 0
for line in infile:
if line_count < 20:
print(line,end='')
line_count += 1
outfile.write(line)
print(line_count)
Zusatzaufgaben
Häufigkeitsanalyse Buch
import io
char_count = {}
with io.open('bibel_martin_luther_1912.txt', 'r', encoding='utf-8') as infile:
line_count = 0
for line in infile:
line = line.replace('Ä','ae').replace('Ö','oe').replace('Ü','ue').replace('ä','ae').replace('ö','oe').replace('ü','ue').replace('ß','SS')
line = upper(line)
for c in line:
if c in string.ascii_uppercase:
if c in char_count:
char_count[c] += 1
else:
char_count[c] = 1
line_count += 1
print(line_count)
nr_letters = sum(char_count.values())
with io.open('bibel_char_count.txt', 'w', encoding='utf-8') as outfile:
for key,value in char_count.items():
line = key + ": " + str(value) + " (" + str(round(value/nr_letters*100,3)) + "%)"
outfile.write(line + "\n")
Unicode-Zeichen String
s = ""
for c in line:
s += str(ord(c)) + " "
s = s[:-1] # entfernt letztes Zeichen (ueberfluessiger Leerschlag)
print(s)
Lösungen B
Teil I
import csv
import io
def round_to_multiple(x, mul):
return round(x / mul) * mul
def calc_average(grades):
# create new list without empty entries and with floats instead of strings
grades_new = []
for g in grades:
if g != '':
grades_new.append(float(g))
# calc average
if len(grades_new) == 0: # no grades
return ''
else:
average = sum(grades_new)/len(grades_new) # calc average
average = round_to_multiple(average,0.5) # round
return average
with io.open('notentabelle.csv', 'r', encoding='utf-8') as csvfile:
reader = csv.reader(csvfile,delimiter=',')
for row in reader:
subject = row[0] # first element of list
grades = row[1:] # sublist without first element
average = calc_average(grades)
print(subject + "," + str(average))
Teil II
import csv
import io
def round_to_multiple(x, mul):
return round(x / mul) * mul
def calc_average(grades):
# create new list without empty entries and with floats instead of strings
grades_new = []
for g in grades:
if g != '':
grades_new.append(float(g))
# calc average
if len(grades_new) == 0: # no grades
return ''
else:
average = sum(grades_new)/len(grades_new) # calc average
average = round_to_multiple(average,0.5) # round
return average
data = [] # when reading data, save here to write afterwards
with io.open('notentabelle.csv', 'r', encoding='utf-8', newline='') as csv_file:
reader = csv.reader(csv_file,delimiter=',')
for row in reader:
subject = row[0] # first element of list
grades = row[1:] # sublist without first element
average = calc_average(grades)
print(subject + "," + str(average))
# Teil II: save data into data-list
data.append([subject,average])
# Teil II
with io.open('notentabelle_resultate.csv', 'w', encoding='utf-8', newline='') as csv_file:
writer = csv.writer(csv_file,delimiter=',') # Create a CSV writer object
writer.writerows(data) # Write the data to the CSV file
Teil III
import csv
import io
def round_to_multiple(x, mul):
return round(x / mul) * mul
def calc_average(grades):
# create new list without empty entries and with floats instead of strings
grades_new = []
for g in grades:
if g != '':
grades_new.append(float(g))
# calc average
if len(grades_new) == 0: # no grades
return ''
else:
average = sum(grades_new)/len(grades_new) # calc average
average = round_to_multiple(average,0.5) # round
return average
data = [] # when reading data, save here to write afterwards
nr_ug = 0
points_positive = 0
points_negative = 0
promotion = "promoviert"
with io.open('notentabelle.csv', 'r', encoding='utf-8', newline='') as csv_file:
reader = csv.reader(csv_file,delimiter=',')
for row in reader:
subject = row[0] # first element of list
grades = row[1:] # sublist without first element
average = calc_average(grades)
print(subject + "," + str(average))
# Teil II: save data into data-list
data.append([subject,average])
# Teil III
if average != '':
if average < 4:
nr_ug += 1
points_negative += -2*(average - 4)
else:
points_positive += average - 4
# Teil III: determine promotion conditions
if nr_ug > 3 or points_positive - points_negative < 0:
promotion = "nicht promoviert"
# add additional info to data
data.append(['Anz UG',nr_ug])
data.append(['Pluspunkte',points_positive])
data.append(['Minuspunkte (doppelt)',points_negative])
data.append(['Promotion',promotion])
# Teil II
with io.open('notentabelle_resultate.csv', 'w', encoding='utf-8', newline='') as csv_file:
writer = csv.writer(csv_file,delimiter=',') # Create a CSV writer object
writer.writerows(data) # Write the data to the CSV file
Teil IV
grades = ['5.5','6','5','','','']
grades_new = []
for grade in grades:
try:
grade = float(grade)
grades_new.append(grade)
except:
pass
print(grades_new)
Teil V
import csv
import io
def round_to_multiple(x, mul):
return round(x / mul) * mul
def calc_average(grades):
# create new list without empty entries and with floats instead of strings
grades_new = []
for g in grades:
try:
grades_new.append(float(g))
except:
pass
# calc average
try:
average = sum(grades_new)/len(grades_new) # calc average
average = round_to_multiple(average,0.5) # round
return average
except:
return ''
data = [] # when reading data, save here to write afterwards
nr_ug = 0
points_positive = 0
points_negative = 0
promotion = "promoviert"
with io.open('notentabelle.csv', 'r', encoding='utf-8', newline='') as csv_file:
reader = csv.reader(csv_file,delimiter=',')
for row in reader:
subject = row[0] # first element of list
grades = row[1:] # sublist without first element
average = calc_average(grades)
print(subject + "," + str(average))
# Teil II: save data into data-list
data.append([subject,average])
# Teil III
if average != '':
if average < 4:
nr_ug += 1
points_negative += -2*(average - 4)
else:
points_positive += average - 4
# Teil III: determine promotion conditions
if nr_ug > 3 or points_positive - points_negative < 0:
promotion = "nicht promoviert"
# add additional info to data
data.append(['Anz UG',nr_ug])
data.append(['Pluspunkte',points_positive])
data.append(['Minuspunkte (doppelt)',points_negative])
data.append(['Promotion',promotion])
# Teil II
with io.open('notentabelle_resultate.csv', 'w', encoding='utf-8', newline='') as csv_file:
writer = csv.writer(csv_file,delimiter=',') # Create a CSV writer object
writer.writerows(data) # Write the data to the CSV file
Lösungen C
Teil I
grades = ['5.5','6','5','','','']
grades_new = []
for grade in grades:
try:
grade = float(grade)
grades_new.append(grade)
except:
pass
print(grades_new)
Teil II
import csv
import io
nr_of_towns = 0
inhabitants_total = 0
inhabitants_max_nr = 0
inhabitants_max_town = None # or = ''
area_max_nr = 0
area_max_town = None
towns_over_10000 = 0
inhabitants_romanshorn = 0
ranking_inhabitants_romanshorn = 1
# only necessary for add. exercises
data = []
inhabitants_list = []
with io.open('gemeinden.csv','r',encoding='utf-8') as csv_file:
reader = csv.reader(csv_file)
header = next(reader)
print(header)
for row in reader:
town = row[0]
canton = row[1]
inhabitants = int(row[2])
area = float(row[3])
nr_of_towns += 1
inhabitants_total += inhabitants
if area > area_max_nr:
area_max_nr = area
area_max_town = town
if inhabitants > inhabitants_max_nr:
inhabitants_max_nr = inhabitants
inhabitants_max_town = town
if inhabitants > 10000:
towns_over_10000 += 1
# ADDITIONAL EXERCISES
data.append(row)
if town == 'Romanshorn':
inhabitants_romanshorn = inhabitants
inhabitants_list.append(inhabitants)
# ADDITIONAL EXERCISES
inhabitants_list.sort()
inhabitants_max_double = None
for i in range(len(inhabitants_list)-1):
if inhabitants_list[i] == inhabitants_list[i+1]:
inhabitants_max_double_nr = inhabitants_list[i]
inhabitants_max_double_towns = []
for row in data:
town = row[0]
canton = row[1]
inhabitants = int(row[2])
area = float(row[3])
if inhabitants > inhabitants_romanshorn:
ranking_inhabitants_romanshorn += 1
if inhabitants == inhabitants_max_double_nr:
inhabitants_max_double_towns.append(town)
# OUTPUT
with io.open('gemeinden_resultate.txt','w',encoding='utf-8') as txt_file:
txt_file.write('Reguläre Aufgaben:\n')
txt_file.write(' * Anz. Gemeinden: ' + str(nr_of_towns) + '\n')
txt_file.write(' * Einwohner Schweiz: ' + str(inhabitants_total) + '\n')
txt_file.write(' * Am meisten Einwohner hat ' + str(inhabitants_max_town) + ' mit ' + str(inhabitants_max_nr) + ' Einwohnern.\n')
txt_file.write(' * Grösste Fläche hat ' + str(area_max_town) + ' mit ' + str(area_max_nr) + ' km^2 Fläche.\n')
txt_file.write(' * Anzahl Städte (> 10000 EW): ' + str(towns_over_10000) + '\n')
txt_file.write('Zusatzaufgaben:\n')
txt_file.write(' * Platz von Romanshorn im Ranking "meiste EW": ' + str(ranking_inhabitants_romanshorn) + '\n')
txt_file.write(' * Gemeinden mit grösster identischer Anz. EW: ' + inhabitants_max_double_towns[0] + ' und ' + inhabitants_max_double_towns[1] + '\n')
Lösungen D
Aufgaben D1
big_5 = {'Zurich': 9999, 'Weinfelden': 8570, 'Basel': 4000, 'Lausanne': 1000, 'P3Rn': 3000}
# Wert anpassen
big_5['Zurich'] = 8000
# Eintraege loeschen
del big_5['Weinfelden']
del big_5['P3Rn'] # ACHTUNG! key ist unveraenderlich! Kann deshalb nicht geaendert werden, muss loeschen und neuen Eintrag machen
# Neue Eintraege
big_5['Bern'] = 3000
big_5['Genf'] = 1200
print(big_5)
Aufgabe D2 Version 1
word_pairs = {
'Apfel': 'apple',
'Haus': 'house',
'Auto': 'car',
'Buch': 'book',
'Katze': 'cat',
'Tisch': 'table',
'Stuhl': 'chair',
'Hund': 'dog',
'Schule': 'school',
'Bleistift': 'pencil'
}
correct = 0
wrong = 0
for german in word_pairs: # or: for german in word_pairs.keys():
english = word_pairs[german]
answer = input('Uebersetze auf Englisch: ' + german)
if answer == english:
correct += 1
print('Antwort korrekt. Score: ' + str(correct) + '/' + str(correct + wrong))
else:
wrong += 1
print('Antwort falsch. Score: ' + str(correct) + '/' + str(correct + wrong))
Aufgabe D2 Version 2
import random
word_pairs = {
'Apfel': 'apple',
'Haus': 'house',
'Auto': 'car',
'Buch': 'book',
'Katze': 'cat',
'Tisch': 'table',
'Stuhl': 'chair',
'Hund': 'dog',
'Schule': 'school',
'Bleistift': 'pencil'
}
correct = 0
wrong = 0
while True:
german = random.choice(word_pairs.keys())
english = word_pairs[german]
answer = input('Uebersetze auf Englisch: ' + german)
if answer == english:
correct += 1
print('Antwort korrekt. Score: ' + str(correct) + '/' + str(correct + wrong))
else:
wrong += 1
print('Antwort falsch. Score: ' + str(correct) + '/' + str(correct + wrong))
Aufgabe D2 Version 3
import random
# CONSTANTS ('variables' that don't change)
PROGRESS_MAX = 3
# dict from previous exercise
word_pairs_0 = {
'Apfel': 'apple',
'Haus': 'house',
'Auto': 'car',
'Buch': 'book',
'Katze': 'cat',
'Tisch': 'table',
'Stuhl': 'chair',
'Hund': 'dog',
'Schule': 'school',
'Bleistift': 'pencil'
}
# extended dict with progress
word_pairs = {}
for german in word_pairs_0.keys():
word_pairs[german] = {'en': word_pairs_0[german], 'progress': 0}
print(word_pairs)
# main loop
while len(word_pairs) > 0:
german = random.choice(word_pairs.keys())
english = word_pairs[german]['en']
progress = word_pairs[german]['progress']
answer = input('Uebersetze auf Englisch: ' + german)
if answer == english:
word_pairs[german]['progress'] += 1
print('Antwort korrekt. Progress: ' + str(word_pairs[german]['progress']) + '/' + str(PROGRESS_MAX))
if word_pairs[german]['progress'] == PROGRESS_MAX:
del word_pairs[german]
else:
word_pairs[german]['progress'] -= 1
if word_pairs[german]['progress'] < 0:
word_pairs[german]['progress'] = 0
print('Antwort falsch. Score: ' + str(word_pairs[german]['progress']) + '/' + str(PROGRESS_MAX))
print(len(word_pairs))
print("GRATULATION! Du hast alle Wörter gut gelernt!")
Aufgabe D3
Teil I
import csv
import io
import json
# CSV LESEN und DICT ERSTELLEN
data = {} # dict fuer alle Daten
with io.open('gemeinden.csv','r',encoding='utf-8') as csv_file:
reader = csv.reader(csv_file)
header = next(reader)
for row in reader:
town = row[0]
canton = row[1]
inhabitants = int(row[2])
area = float(row[3])
data[town] = {
"canton":canton,
"inhabitants":inhabitants,
"area":area
}
# IN JSON SCHREIBEN
with open('gemeinden.json', 'w') as json_file:
json.dump(data, json_file, indent=4)
Teil II
# 1.
print(data['Aarwangen']['inhabitants'])
# 2.
print(data['Estavayer']['area'])
# 3. Variante 1
for key,value in data.items():
if value['inhabitants'] == 314:
print(key)
# 3. Variante 2
for town in data.keys():
if data[town]['inhabitants'] == 314:
print(town)
# 4.
count = 0
for key,value in data.items():
if value['canton'] == 'TI':
count += 1
print(count)