# Data Processing in Python
{{ :gf_informatik:daten:dataprocessing.pptx | Präsentation}}
Wir haben nun einige Erfahrung gesammelt, um mit Tabellenprogrammen Daten zu bearbeiten und darzustellen. Aber was, wenn wir *mehr* Daten haben, als Excel darstellen kann?
Wieviel ist viel? 1000?
#### Aufgabe 1
Finde heraus, bei wie vielen Zeilen Excel oder Google Sheets in die Knie gehen.
## Das Dateisystem
Alle Dateien sind im Permanentspeicher in einer _hierarchischen Ordnerstruktur_ abgelegt. Mit Python kann die Ordnerstruktur gelesen und manipuliert werden. Damit eine Datei gelesen oder beschrieben werden kann, muss sie zuerst geöffnet werden.
### Absolute und relative Pfade
Ein _Dateipfad_ identifiziert eine Datei:
* ein _absoluter_ Pfad gibt die Ordner-Hierarchie vom obersten Knoten her an und beginnt mit einem Laufwerksbuchstaben oder einem Schrägstrich, z.B. `C:/Users/Nutzername/Meine_Dateien/beispiel.txt` oder `/Users/Nutzername/Downloads/beispiel.txt`.
* ein _relativer_ Pfad identifiziert eine Datei von einem Referenz-Ordner her, oft vom Arbeits-Ordner des Programms. Wird das Programm im Ordner `C:/Users/Nutzername` ausgeführt, so zeigt der relative Pfad `Meine_Dateien/beispiel.txt` auf die gleiche Datei wie oben.
Es gibt zwei spezielle Pfadnamen:
* `.` der einzelne Punkt zeigt auf den aktuellen Arbeits-Ordner.
* `Meine_Dateien/beispiel.txt` und `./Meine_Dateien/beispiel.txt` zeigen auf die gleiche Datei.
* `..` zwei Punkte zeigen auf das Eltern-Verzeichnis:
* `Meine_Dateien/../beispiel.txt` zeigt auf `beispiel.txt` im aktuellen Ordner.
### Dateinamen und Erweiterungen
Ein Dateiname (ohne den Ordnerpfad) hat meist eine durch einen Punkt abgetrennte _Erweiterung_, die den Typ der Datei anzeigt:
* `beispiel.txt` -- eine Text-Datei
* `beispiel.pdf` -- eine PDF-Datei
* `beispiel.xlsx` -- eine Microsoft-Excel-Tabelle
Windows versteckt die Erweiterung standardmässig, es empfiehlt sich, [[https://support.microsoft.com/de-de/windows/allgemeine-dateierweiterungen-in-windows-da4a4430-8e76-89c5-59f7-1cdbbc75cb01|sie anzuzeigen]].
### Dateioperationen mit Python
Mit `os.listdir` können wir die Dateien im momentanen Arbeitsverzeichnis auflisten:
from os import listdir
print(listdir())
## Dateien einlesen
Grossen Datenmengen sind natürlich nur ein Grund, weshalb wir mit einem Programm Daten lesen und schreiben wollen. Andere Gründe: wir wollen Benutzerdaten lesen oder speichern können, den Programmzustand abspeichern (und beim Neustart wieder einlesen), etc.
Wie lesen wir Daten in einer Text-Datei?
# Opens a file for reading (and closes it again after the 'with').
with open('beispiel.txt', 'r') as infile:
count = 0
# Loops over all lines in the file
for line in infile:
count += 1
print(count)
* 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 `beispiel.txt`) muss sich im Ordner befinden, wo Python ausgeführt wird.
* `'r'` bedeutet *read*, dass die Textdatei nur gelesen und nicht verändert wird.
#### Aufgabe 2
Lade die Datei [[https://kantonsschuleromanshorn.sharepoint.com/:f:/s/FSInformatik/Ek-Hi_stH2RMjDa-wQN9jekBMeF_YD6rvhmibDlNglGWxw?e=Y3AX65|gemeinden.csv]] herunter und speichere sie im Ordner, wo du dein Python-Programm abspeicherst. Verwende obigen Python-Code, um herauszufinden, wieviele Zeilen die Datei hat.
Alternativ dazu kannst du auch direkt obigen Code modifizieren - die Datei `gemeinden.csv` ist bereits hinterlegt.
##### Encoding
Achtung, Mac-Users: Die Datei verwendet in Mitteleuropa die Latin1-Codierung, einer Erweiterung von [[gf_informatik:verschluesselung:codierung|ASCII]], um auch Umlaute anzeigen zu können. Diese ist in Windows voreingestellt. MacOS hingegen verwendet standardmässig die universelle Unicode (UTF-8) Codierung. Beim Öffnen der Datei kann die Abweichung korrigiert werden:
# Specify text encoding when opening a file.
with open('dateiname.txt', 'r', encoding='latin1') as infile:
## Dateien schreiben
Schreiben funktioniert ganz ähnlich wie lesen, aber als zweites Argument muss `'w'` (für _write_) angegeben werden:
with open('dateiname.txt', 'w') as outfile:
for i in range(10):
line = "Zeile " + str(i) + "\n"
outfile.write(line)
Beachte:
* `str()` verwandelt die Zahl in einen Text.
* `'\n'` ist der ASCII-Code für einen Zeilenumbruch.
#### Aufgabe 3
Beschreibe eine Datei mit einigen Zeilen. Es ist ungünstig, mehr als einige zehntausend Zeilen zu schreiben...
## CSV-Format
Die Datei `gemeinden.csv` ist im [[wpde>CSV_(Dateiformat)|Comma-Separated-Values]] Format gespeichert: Die Daten sind ganz ähnlich gespeichert wie in einer Tabelle und können auch mit Excel und Sheets geöffnet werden. Jede Zeile entspricht einer Zeile der Tabelle; die Spalten sind meist mit Kommas voneinander getrennt. Manchmal werden aber auch Semikolons (`;`) oder ein [[wpde>Tabulatorzeichen|Tabulator]] (`\t`) als Trennzeichen verwendet.
Oft werden in der ersten Zeile die Spaltennamen festgelegt:
Gemeinde,Kanton,Einwohner,Fläche
Aadorf,TG,9216,19.93
Aarau,AG,21726,12.36
...
Wollen wir eine Zeile in die einzelnen Werte aufspalten, müssen wir dafür ein paar String-Operationen kennen:
* `split(char)` erzeugt aus einem String eine Liste von Werten, die mit dem angegebenen Trennzeichen abgetrennt sind:
* `"Aarau,AG,21726,12.36".split(',')` erzeugt die Liste `["Aarau","AG","21726","12.36"]`
* `strip()` gibt den selben String zurück, aber ohne Leerschläge oder anderen _Whitespace_ (Zeilenumbrüche...) an beiden Enden:
* `" Romans Horn ".strip()` gibt `"Romans Horn"` zurück.
#### Aufgabe 4
Wandle den Code aus Aufgabe 2 so ab, dass jeweils der Kanton auf der Konsole ausgegeben wird:
* Jede Zeile wird mit `values = line.split(',')` aufgeteilt.
* Mit `print(values[1])` wird der Kanton (die zweite Spalte) ausgegeben.
* Wieviele Gemeinden gibt es im Kanton Thurgau? Wieviele im Kanton Bern?
## Text in Zahlen umwandeln.
Alles, was wir aus der Textdatei lesen, ist... well, Text. Damit wir mit den Werten rechnen können, müssen wir die Strings umwandeln. Dazu verwenden wir die folgenden eingebauten Funktionen:
* `int(string)` wandelt einen String in eine Ganzzahl (*integer*) um.
* `float(string)` wandelt einen String in eine reelle Zahl (*floating point number* - Fliesskommazahl) um.
Allerdings funktioniert das nur, wenn der String auch wirklich eine Zahl darstellt. Sonst wird eine *Exception* geworfen; wir können sie mit `try...except` auffangen:
try:
my_number = int("abc") # may throw an exception
print(my_number) # only executes if the above was successful
except ValueError:
print("not a number") # executed if an exception was thrown
#### Aufgabe 5
Benütze `try...except` um in deinem Code die Bevölkerung und die Fläche der Gemeinden auszulesen.
* welche Spalten (Indices) gehören zu diesen Werten?
* verwendest du `int()` oder `float()`?
* wie gross ist die Bevölkerung des Kanton Thurgau?
#### Aufgabe 6
Schreibe Python-Code, um die folgenden Fragen zu beantworten:
* Was ist die Gemeinde mit der kleinsten Bevölkerungszahl?
* Welche Gemeinde hat die grösste Fläche?
* Wieviele Einwohner hat die Schweiz?
++++Lösung:|
* kleinste Bevölkerung: Kammersrohr (32 Einwohner)
* grösste Fläche: Scuol ($438.76 km^2$)
* Einwohner: $9050451$
++++
#### Aufgabe 7
Erweitere den Code, um folgende Fragen zu beantworten:
* Welches ist die Thurgauer Gemeinde mit den wenigsten Einwohnern?
* Was ist die Gesamtfläche aller Tessiner Gemeinden?
* Wieviele Gemeinden hat der Kanton Glarus?
### Nächstes Kapitel
Weiter mit [[gf_informatik:daten:processing:dictionaries]].