Mathematik für Biologiestudierende¶
Wintersemester 2024/25
- Oktober 2024
© 2024 Prof. Dr. Rüdiger W. Braun
Merkmale¶
Grundbegriffe¶
- die Elemente der Grundgesamtheit sind Träger von Merkmalen
- die Merkmale haben verschiedene Ausprägungen
- jedes Element der Grundgesamtheit besitzt für jedes Merkmal nur eine Ausprägung
Typen von Merkmalen¶
Quantitatives Merkmal:
zahlenmäßig erfassbar; Zahlenwerte besitzen Bedeutung
unterteilt in
stetiges Merkmal:
Zahlenwerte variieren kontinuierlich (z.B. Gewicht, gemessene Zeit)
diskretes Merkmal:
Skala ohne Zwischenwerte (z.B. Anzahl, Zeit in Tagen)
Qualitatives Merkmal:
alle anderen
Beispiele zu den Grundbegriffen¶
Grundgesamtheit: alle Bäume einer Baumschule
Merkmal: Art (qualitatives Merkmal)
Ausprägung: Fichte
Merkmal: Größe (quantitativ stetiges Merkmal)
Ausprägung: 3.38m
Merkmal: Pflanzdatum (quantitativ diskretes Merkmal)
Ausprägung: 9.10.2003
Matrikelnummer¶
Ist die Matrikelnummer ein quantitatives oder ein qualitatives Merkmal?
Antwort: Qualitatives Merkmal, jedenfalls innerhalb einer Jahrgangs
Darstellung von Merkmalen in Python¶
- Ausprägungen qualitativer Merkmale werden als kategorielle Daten bezeichnet
- sie werden als Zeichenketten (string) dargestellt
- Beispiel
species = "Adelie"
- diskrete quantitative Merkmale werden als ganze Zahlen (integer) dargestellt
- Beispiel
anzahl = 17
- kontinuierliche quantitative Merkmale werden als Fließkommazahlen (float) dargestellt
- Beispiel
gewicht = 4.880
- Der Unterschied zwischen einer Fließkommazahl und einer ganzen Zahl ist, dass die Fließkommazahl einen Dezimalpunkt enthält, die ganze Zahl nicht
- Python kann ganze Zahlen exakt darstellen, Fließkommazahlen nur näherungsweise
- Das spielt für uns aber keine Rolle
Stichproben¶
- Eine Stichprobe ist eine zufällig gewonnene Teilmenge aus der zu untersuchenden Grundgesamtheit
- Der Stichprobenumfang ist die Anzahl der Elemente in der Stichprobe
- Die Daten sind die beobachteten Ausprägungen des Merkmals bzw. der Merkmale
- Die Erfassung der Daten geschieht in der Urliste, auch Protokoll genannt
- Die Urliste ist unveränderlich
Zufall¶
Zufall bedeutet für uns: Kein erkennbares Muster
Zufällige Auswahl ist nicht einfach. Man verwendet
- Würfel
- Zufallsgenerator
- und früher sogar gedruckte Zufallstafeln
weil der Computer eine deterministische Maschine ist, sind die in den verschiedenen Programmiersprachen verfügbaren Zufallsgeneratoren in Wahrheit Pseudozufallsgeneratoren, erzeugen also Zahlenfolgen, die für den Beobachter unvorhersehbar sind
die Pseudozufallsgeneratoren der gängigen Programmiersprachen reichen für Versuchsplanung und Modellbildung völlig aus
Zufallsgeneratoren in Python¶
import random
zufällige Fließkommazahl zwischen 0 und 1:
random.random()
0.7697433767422679
random.random()
0.04721840544650613
random.random()
0.6748578967530499
Ganze Zufallszahl zwischen n und m:
random.randint(10, 20)
# beide Randpunkte eingeschlossen
17
zufällige Auswahl:
random.sample(range(10), 5)
[2, 6, 7, 3, 9]
range
ist wie np.arange
np.arange
ist bei random
aber nicht zulässig
range(10)
range(0, 10)
list(range(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Seeding¶
random.seed(1234)
random.randint(1, 1000)
990
random.randint(1, 1000)
797
random.seed(1234)
random.randint(1, 1000)
990
Wozu soll das gut sein?
- Auf Maschinen, die nicht in der Lage sind, ein gutes seed zu konstruieren, kann man selber eins angeben
- Wichtiger: Zur Fehlersuche bei Programmen mit zufälligem Anteil
- Fische lernen, in einem Labyrinth Futter zu suchen; Zeit wird gemessen
- die Fische werden an 25 Artgenossen verfüttert
- die Artgenossen sollen im selben Labyrinth Futter suchen; Zeit wird gemessen
- die neuen Fische sind schneller
- Nobelpreis?
Grafiken¶
Balkendiagramm: Für jeden möglichen Wert ein Balken, der die Anzahl anzeigt
Histogramm: Wie Balkendiagramm, aber Werte werden vorher in Klassen zusammengefasst
Bei Stichprobenumfang $n$: Anzahl der Klassen ungefähr $\sqrt n$
Tortendiagramm: Anteile an der Gesamtpopulation werden grafisch dargestellt
Beispiel Pinguine¶
import seaborn as sns
df = sns.load_dataset("penguins") # mitgelieferter DataFrame
df
species | island | bill_length_mm | bill_depth_mm | flipper_length_mm | body_mass_g | sex | |
---|---|---|---|---|---|---|---|
0 | Adelie | Torgersen | 39.1 | 18.7 | 181.0 | 3750.0 | Male |
1 | Adelie | Torgersen | 39.5 | 17.4 | 186.0 | 3800.0 | Female |
2 | Adelie | Torgersen | 40.3 | 18.0 | 195.0 | 3250.0 | Female |
3 | Adelie | Torgersen | NaN | NaN | NaN | NaN | NaN |
4 | Adelie | Torgersen | 36.7 | 19.3 | 193.0 | 3450.0 | Female |
... | ... | ... | ... | ... | ... | ... | ... |
339 | Gentoo | Biscoe | NaN | NaN | NaN | NaN | NaN |
340 | Gentoo | Biscoe | 46.8 | 14.3 | 215.0 | 4850.0 | Female |
341 | Gentoo | Biscoe | 50.4 | 15.7 | 222.0 | 5750.0 | Male |
342 | Gentoo | Biscoe | 45.2 | 14.8 | 212.0 | 5200.0 | Female |
343 | Gentoo | Biscoe | 49.9 | 16.1 | 213.0 | 5400.0 | Male |
344 rows × 7 columns
Ein DataFrame
ist eine Tabelle ähnlich einem Excel-Spreadsheet
- In der ersten Spalte steht der Index, in diesem Fall die laufende Nummer des Pinguins
- Der Index ist eindeutig
NaN
bedeutet "Not a Number"
Histogramm¶
sns.displot(df, x='flipper_length_mm');
Die Anzahl der Fächer (bins) kann eingestellt werden
sns.displot(df, x='flipper_length_mm', bins=20)
<seaborn.axisgrid.FacetGrid at 0x724a75d05d30>
Alternativ kann auch die Breite der Fächer eingestellt werden
sns.histplot(df, x='flipper_length_mm', binwidth=2.5)
<Axes: xlabel='flipper_length_mm', ylabel='Count'>
Balkendiagramm¶
Bei qualitativen Merkmalen spricht man von kategoriellen Daten. Zählt man die Vorkommen, erhält man ein Balkendiagramm.
sns.displot(df, x='species')
<seaborn.axisgrid.FacetGrid at 0x724a6d999d60>
englisch | deutsch |
---|---|
Adelie penguin | Adelie Pinguin |
Chinstrap penguin | Zügelpinguin |
Gentoo penguin | Eselspinguin |
sns.displot(df, col='island', x='species');
sns.displot(df, col='island', x='species', hue='sex', multiple="stack");
DataFrames¶
Bevor wir weitere Graphen ansehen, erst noch ein Blick auf pd.DataFrame
sns.load_dataset
lädt einen der mitgelieferten Datensätze- Der Datensatz kommt als
pd.DataFrame
, das ist eine Tabelle - Variablennamen (z.B.
df
) ohne Anführungszeichen - andere Bezeichner mit Anführungszeichen
"
oder'
- kein Unterschied zwischen
"
und'
, aber vor und hinter dem Wort dasselbe Zeichen verwenden - später mehr zu diesem Thema
Die erste Spalte eines DataFrames ist der Index, in diesem Beispiel die laufende Nummer
df.index
RangeIndex(start=0, stop=344, step=1)
Die Spalten zeigen Ausprägungen von Merkmalen
Wir erhalten die Spalte flipper_length_mm
des DataFrame df
auf einer der beiden folgenden Weisen
df.flipper_length_mm
df['flipper_length_mm']
Wenn der Spaltenname Leerzeichen enthält, funktioniert nur die zweite Variante
df.flipper_length_mm
0 181.0 1 186.0 2 195.0 3 NaN 4 193.0 ... 339 NaN 340 215.0 341 222.0 342 212.0 343 213.0 Name: flipper_length_mm, Length: 344, dtype: float64
NaN
bedeutet "not a number", in der Praxis meist, dass der Wert nicht erhoben werden konnte
Die Daten des Pinguins Nummer 222 erhält man so
df.loc[222]
species Gentoo island Biscoe bill_length_mm 48.7 bill_depth_mm 14.1 flipper_length_mm 210.0 body_mass_g 4450.0 sex Female Name: 222, dtype: object
sns.displot(df, x='flipper_length_mm');
Die Verteilung ist bimodal, d. h. es gibt zwei Maxima.
Das könnte daran liegen, dass die beiden Geschlechter unterschiedliche Flügellängen haben. Wir betrachten nur die weiblichen Pinguine
Wir speichern die Daten der weiblichen Pinguine im DataFrame w
w = df[df.sex=="Female"] # Achtung "==" als Vergleichsoperator"
w
species | island | bill_length_mm | bill_depth_mm | flipper_length_mm | body_mass_g | sex | |
---|---|---|---|---|---|---|---|
1 | Adelie | Torgersen | 39.5 | 17.4 | 186.0 | 3800.0 | Female |
2 | Adelie | Torgersen | 40.3 | 18.0 | 195.0 | 3250.0 | Female |
4 | Adelie | Torgersen | 36.7 | 19.3 | 193.0 | 3450.0 | Female |
6 | Adelie | Torgersen | 38.9 | 17.8 | 181.0 | 3625.0 | Female |
12 | Adelie | Torgersen | 41.1 | 17.6 | 182.0 | 3200.0 | Female |
... | ... | ... | ... | ... | ... | ... | ... |
332 | Gentoo | Biscoe | 43.5 | 15.2 | 213.0 | 4650.0 | Female |
334 | Gentoo | Biscoe | 46.2 | 14.1 | 217.0 | 4375.0 | Female |
338 | Gentoo | Biscoe | 47.2 | 13.7 | 214.0 | 4925.0 | Female |
340 | Gentoo | Biscoe | 46.8 | 14.3 | 215.0 | 4850.0 | Female |
342 | Gentoo | Biscoe | 45.2 | 14.8 | 212.0 | 5200.0 | Female |
165 rows × 7 columns
sns.histplot(w, x="flipper_length_mm");
Immer noch bimodal. Also ist das Geschlecht nicht der Grund. Vielleicht die verschiedenen Arten?
sns.displot(df, x="flipper_length_mm", col="species");
sns.displot(df, x="flipper_length_mm", col="species", hue='sex', binwidth=3, multiple='stack');
displot
¶
displot(df, x, col, hue, binwidth)
- df: DataFrame
- x: Variable auf der x-Achse, deren Elemente gezählt werden sollen, quantitativ oder kategoriell
- col: für jeden Wert dieser Variable wird ein Bild gezeichnet, kategoriell (optional)
- hue: Unterteilung der Zählung, durch Farben ausgedrückt, kategoriell (optional)
- binwidth: Breite der Fächer (optional)
- bins: Anzahl der Fächer (alternativ zu binwidth, optional)
Die Angaben für x
, col
und hue
beziehen sich auf Spaltennamen des DataFrame, sie werden in Anführungszeichen gesetzt
Tortendiagramme¶
- findet man selten in Fachzeitschriften
- daher kein Bestandteil von seaborn
Wie viele Pinguine gibt es von jeder Sorte?
df["species"].value_counts()
species Adelie 152 Gentoo 124 Chinstrap 68 Name: count, dtype: int64
df["species"].value_counts().plot.pie();
pp = sns.light_palette('Navy', as_cmap=True)
df["species"].value_counts().plot.pie(cmap=pp);