Eine Anleitung für die Bearbeitung und Abgabe der Übunsgaufgaben in Python findet Ihr im Abgabebereich des Moodlekurses ( Link ).
Kurzform: Eine Aufgabe besteht immer aus einer "Funktion", die für einen definierten Input (Argumente) einen definierten Output zurückgeben soll (engl.: return
). Überprüft die Korrektheit dieses Outputs und damit Eurer Lösung mit testme(funktionsname)
. Wenn Ihr fertig seid, erzeugt unter im Abschnitt Gesamtauswertung Euer Zertifikat und gebt es dann in Moodle zusammen mit diesem Notebook ab.
Hier ein Beispiel für eine Funktion: Die Funktion heißt beispiel
, hat die Argumente (den Input) x
und y
und gibt die Variable ergebnis
zurück. Das Ergebnis ist in diesem Fall die Summe der Argumente x
und y
.
def beispiel(x, y):
ergebnis = x + y
return(ergebnis)
beispiel(1,1)
beispiel(2,-3)
from testzentrum import *
import numpy as np
import datetime as dt
import geopandas as gpd
Dies ist unsere letzte Übungsrunde. Wir wollen in dieser Runde einen Rundumschlag über das bereits Gelernte geben. Es können also Inhalte aus allen Lektionen drankommen - juchuu!
Das Arbeiten mit der Versionsverwaltungssoftware git
lernen wir eigentlich erst in der nächsten Lektion. Hier aber schonmal ein kleiner Vorgeschmack. Keine Sorge, es geht in dieser Aufgabe nur um Stringverkettung und Ihr braucht eigentlich gar keine git
Kenntnisse...
Trotzdem kurz der Hintergrund: Beim Arbeiten mit git
liegt Euer Code (Python, R oder was auch immer) in einem lokalen "Repository". Ihr könnt in dieses Repository Eure eigenen Änderungen am Code einpflegen. Ihr könnt aber auch Änderungen anderer Personen aus sogenannten "remote repositories" (also z.B. auf Git.UP unser Kursrepository) in Euer lokales Repository "reinziehen" (pull). Der Befehl dazu lautet: git pull {REMOTENAME} {BRANCHNAME}
. Ein Branch ist sowas wie ein "Entwicklungszweig". Wir benutzen hier als {BRANCHNAME}
immer master
.
Eure Funktion git_pruefung
erhält nun als Argument remote
den Namen des Remote Repository, also {REMOTENAME}
. Die Funktion soll nun den vollständigen Befehl zurückgeben, mit dem Ihr Änderungen aus dem Remote Repository {REMOTENAME}
in Euer lokales Repository zieht.
Alles sehr verwirrend? Am Beispiel aber sehr einfach:
>>> git_pruefung("erich")
'git pull erich master'
>>> git_pruefung("Leonid")
'git pull Leonid master'
Hinweis: Trennt jedes Element des gesamten Befehls mit EINEM Leerzeichen.
def git_pruefung(remote):
pass
testme(git_pruefung)
Das 2-D Array x
enthalte Werte der $NO_x$-Konzentration an städtischen Hotspot-Messstellen. Die Zeilen stellen die Zeitschritte dar, die Spalten die unterschiedlichen Messstellen.
Die Funktion alarm
gebe für jeden Zeitschritt die Zahl der Stationen zurück, an denen der Schwellenwert schwelle
überschritten wird.
Beispiel:
>>> schwelle = 30
>>> array([[22.5, 57. , 43.9],
[35.9, 9.4, 9.4],
[ 3.5, 52. , 36.1],
[42.5, 1.2, 58.2],
[49.9, 12.7, 10.9]])
Ergebnis:
[2, 1, 2, 2, 1]
Achtung: Das Ergebnis soll als Liste zurückgeben werden (.tolist()
).
def alarm(x, schwelle):
pass
testme(alarm)
Im 2-D Array x
sind Fehlwerte durch eine Zahl flag
markiert. Die Funktion ohne_fehl
soll für jede Zeile das Minimum zurückgeben, Fehlwerte sind hierbei aber zu ignorieren! Das Ergebnis soll als Liste zurückgegeben werden! (mit .tolist()
).
Beispiel:
>>> flag = -99
>>> x = array([[ 14, 15, -99, 18, -99],
[ 7, -99, 2, 4, 8],
[ 0, 14, -99, 2, 2],
[-99, 19, -99, -99, -99]])
Ergebnis
--------
[14, 2, 0, 19]
Hinweise:
flag
entsprechen, in np.nan
umzuwandelnnp.nanmin
nutzen...def ohne_fehl(x, flag):
pass
testme(ohne_fehl)
Die Funktion get_crs
gebe das CRS (Coordinate Reference System) eines Vektordatensatzes zurück, der unter pfad
liegt. Die Rückgabe soll als EPSG-Code erfolgen (Datentyp int
). Der Datensatz liegt in einer Datei, die mit geopandas
gelesen werden kann.
Beispiel:
>>> pfad = data/landuse1.shp
Ergebnis: 4326
def get_crs(pfad):
pass
testme(get_crs)
Als Reaktionszeit (engl. response time) eines Einzugsgebiets bezeichnet man die Verzögerung zwischen dem zeitlichen Schwerpunkt des Niederschlags und dem darauf folgenden Abflusspeak. dtprec
sei der Zeitpunkt des Niederschlagsschwerpunkts und dtrunoff
der Zeitpunkt des Abflusspeaks. Beide sind als Strings der Art "2021-12-31T20:22:59"
gegeben (sog. Isoformat). Die Funktion responsetime
gebe die Reaktionszeit des Einzugsgebiets in Sekunden zurück.
Vorgehensweise:
Beispiel:
>>> dtprec = "2021-12-31T20:22:59"
>>> dtrunoff = "2022-01-01T12:22:00"
Ergebnis: 57541.0
def responsetime(dtprec, dtrunoff):
pass
testme(responsetime)
Eine Datei enthalte zeilenweise Daten eines wägbaren Lysimeters, und zwar für die folgenden Variablen:
start
: Beginn des Messzeitraums (im Format %Y-%m-%dT%H:%M:%S
)end
: Ende des Messzeitraums (im Format %Y-%m-%dT%H:%M:%S
)deltaS
: Massenänderung des Lysimeters im Messzeitraum (in kg)Q
: Masse des Sickerwassers (in kg), welches im Bezugszeitraum aus dem Lysimeter gesickert istP
: Niederschlagsmenge (in mm).Die Oberfläche des Lysimeters sei 1 m².
Du sollst nun die mittlere Verdunstungsrate $\frac{ET}{\Delta(t)}$ im Messzeitraum in der Einheit $mm/h$ zurückgeben: also das verdunstete Volumen (in Litern) pro Fläche (in m²) und Zeit (in $h$). Nimm als Dichte für Wasser 1 kg/l an. Hier nochmal zur Erinnerung die Wasserbilanzgleichung:
$(P - ET - Q - deltaS) \frac{1}{\Delta(t)} = 0$
Soweit so gut. Leider ist die Datei sehr merkwürdig formatiert! Hier mal ein Beispiel für zwei Zeilen:
":start=2020-06-01T00:00:00;Hallo Mutti!end=2020-06-15T00:00:00;deltaS=30;Q=10;P=100:"
":start=2020-06-15T00:00:00;Hi Thorsten!P=90;deltaS=40;Q=10;end=2020-07-01T00:00:00:"
Bei so einem Datenschrott geht selbst pandas
in die Knie.
:...:
)gruss
zu grüßen (hier: Hallo Mutti!
bzw. Hi Thorsten!
)Variablenname=...
beschriftet.;
) verwendet.Wirst Du es schaffen, dem Wahnsinn die Stirn zu bieten?
Deine Funktion lysimeter
erhält immer nur eine Zeile des Datensatzes (Argument zeile
) sowie das Argument gruss
, welches ein String mit dem überflüssigen Gruß ist. Zurückgeben soll Deine Funktion die mittlere Verdunstungsrate über den gesamten Zeitraum in der Einheit $mm/h$, gerundet auf eine Nachkommastelle.
Tipps zur Vorghensweise:
zeile
bereinigen: Die einschließenden :
mit strip
, den störenden gruss
mit replace
.split
trennen (welches Trennzeichen?). Das Ergebnis ist eine Liste, die Du z.B. items
nennen kannstdata
an mit data = {}
items
legen wir nun eine for
-Schleife an:items
wird nochmal mit split
behandelt (welches Trennzeichen?), das Ergebnis ist eine Liste mit zwei Einträgen, nennen wir diese Liste mal paar
.paar
ist der Name der gemessenen Variable (z.B. "deltaS"
), der zweite Eintrag ist ein String mit dem Wert (z.B. "10.1"
. Lege nun mit jedem Durchlauf der Schleife im Dictionary data
einen neuen Eintrag an, also data[paar[0]] = paar[1]
for
-Schleife durch und alle Einträge hübsch im Dictionary. Diese Einträge sind aber noch Zeichenketten. Du musst nun die Einträge für "start"
und "end"
jeweils in ein datetime
-Objekt umwandeln (mit dt.datetime.strptime
); die Einträge "P"
, "Q"
und "deltaS"
in einen float
.Beispiel:
>>> gruss = "Hallo Heidi!"
>>> zeile = ":start=2020-06-01T00:00:00;end=2020-06-15T00:00:00;Hallo Heidi!deltaS=30;Q=10;P=100:"
Zwischenergebnisse:
Bereinigte Zeile:
"start=2020-06-01T00:00:00;end=2020-06-15T00:00:00;deltaS=30;Q=10;P=100"
Dictionary data vor der for-Schleife:
data = {}
Dictionary data nach der for-Schleife:
data = {'start': '2020-06-01T00:00:00',
'end': '2020-06-15T00:00:00',
'deltaS': '30',
'Q': '10',
'P': '100'}
Dictionary data nach Umwwandlung in korrekte Datentypen:
data = {'start': datetime.datetime(2020, 6, 1, 0, 0),
'end': datetime.datetime(2020, 6, 15, 0, 0),
'deltaS': 30.0,
'Q': 10.0,
'P': 100.0}
Verdunstetes Volumen über den Gesamtzeitraum:
60 Liter (100-10-30)
Dauer des Messzeitraums:
336 Stunden
ENDERGEBNIS
60 Liter / (336 h * 1 m²) = 0.17857142857142858 mm/h
also: 0.2
Versucht die Lösung Stück für Stück zur entwickeln, bis Ihr sie letztlich zur FUnktion zusammensetzt.
def lysimeter(zeile, gruss):
# Erst die Zeile bereinigen
# Nun splitten
# Leeren Dictionary anlegen
# For-Schleife über items
# Type conversion
# Wasserbilanz aufstellen
pass
testme(lysimeter)
Nach der umweltwissenschaftlichen Monsteraufgabe zum Lysimeter noch was zum Runterkommen - etwas aus der Zeit gefallen und doch ein brandaktueller Beitrag zur Genderdebatte: Loriots "Frühstücksei".
er
und sie
unterhalten sich strikt abwechselnd, er
beginnt. Die untenstehenden Listen enthalten in korrekter Reihenfolge die Redebeiträge der beiden.
Die Funktion das_ei
soll Dir Deine Lieblingsstellen im Dialog als String zurückgeben.
Das Argument wer
ist ein String und gibt an, wer als erstes spricht: "er"
oder "sie"
. Das Argument i
gibt den Index in der zugehörigen Liste er
bzw. sie
. An die entsprechende Dialogzeile er[i]
bzw. sie[i]
soll dann noch die passende Replik des Partners angehängt werden, getrennt durch den String " - "
.
Ist verwirrend? Am Beispiel hoffentlich klarer:
Beispiel:
>>> wer = "er"
>>> i = 2
Ergebnis: "Das Ei ist hart!!! - Ich habe es gehört ..."
>>> wer = "sie"
>>> i = 3
Ergebnis = "Zu viele Eier sind gar nicht gesund! - Ich meine, wie lange dieses Ei gekocht hat ...?"
Du musst in dieser Aufgabe eine if
-Abfrage nutzen, Listen korrekt indizieren und Strings verketten. Beachte: Die Antwort auf er[i]
ist sie[i]
, aber die Antwort auf sie[i]
ist er[i+1]
.
er = ["Berta!",
"Das Ei ist hart!",
"Das Ei ist hart!!!",
"Wie lange hat das Ei denn gekocht?",
"Ich meine, wie lange dieses Ei gekocht hat ...?",
"Das weiß ich ..."
"Ich meine, wie lange dieses Ei gekocht hat ...?",
"Weil dieses Ei nicht viereinhalb Minuten gekocht haben kann!",
"Wieso ist es dann mal zu hart und mal zu weich?",
"Ach! ... Und woher weißt du, wann das Ei gut ist?",
"Nach der Uhr oder wie?",
"Im Gefühl? Was hast du im Gefühl?",
"Aber es ist hart ... vielleicht stimmt da mit deinem Gefühl was nicht ...",
"Jaja ... jaja ... jaja ... wenn ein Ei nach Gefühl kocht, kocht es eben nur zufällig genau viereinhalb Minuten.",
"Ich hätte nur gern ein weiches Ei und nicht ein zufällig weiches Ei! Es ist mir egal, wie lange es kocht!",
"Nein - nein ...",
"Das habe ich doch gesagt ...",
"Ich hätte nur gern ein weiches Ei ...",
"Ich bringe sie um ... morgen bringe ich sie um!"
]
sie = ["Ja ...",
"(schweigt)",
"Ich habe es gehört ...",
"Zu viele Eier sind gar nicht gesund!",
"Du willst es doch immer viereinhalb Minuten haben ...",
"Was fragst du denn dann?"
"Ich koche es aber jeden Morgen viereinhalb Minuten.",
"Ich weiß es nicht ... ich bin kein Huhn!",
"Ich nehme es nach viereinhalb Minuten heraus, mein Gott!",
"Nach Gefühl ... eine Hausfrau hat das im Gefühl ...",
"Ich habe es im Gefühl, wann das Ei weich ist ...",
"Mit meinem Gefühl stimmt was nicht? Ich stehe den ganzen Tag in der Küche, mache die Wäsche, bring deine Sachen in Ordnung, mache die Wohnung gemütlich, ärgere mich mit den Kindern rum und du sagst, mit meinem Gefühl stimmt was nicht?",
"Es kann dir doch ganz egal sein, ob das Ei zufällig viereinhalb Minuten kocht ... Hauptsache, es kocht viereinhalb Minuten!",
"Aha! Das ist dir egal ... es ist dir also egal, ob ich viereinhalb Minuten in der Küche schufte!",
"Aber es ist nicht egal ... das Ei muss nämlich viereinhalb Minuten kochen ...",
"Aber eben hast du doch gesagt, es ist dir egal!",
"Gott, was sind Männer primitiv!"
]
def das_ei(er, sie, wer, i):
pass
testme(das_ei)
get_certificate(testmysolutions=[git_pruefung, alarm, ohne_fehl,
get_crs, responsetime, lysimeter, das_ei],
lesson=6)