Mathematik für Biologiestudierende II¶
Sommersemester 2025
29.04.2025
© 2025 Prof. Dr. Rüdiger W. Braun
import numpy as np
np.set_printoptions(legacy='1.21')
import pandas as pd
from scipy import stats
import seaborn as sns
sns.set_theme()
Themen¶
- Verteilung und Verteilungsfunktion
- Prinzip der ANOVA
- Heteroskedastizität
- Levene-Test
- Alexander-Govern-Test
Wiederholung: Verteilung und Verteilungsfunktion¶
diskrete Verteilungen¶
- Wir kennen nur eine diskrete Verteilung, nämlich die Binomialverteilung
- Beispiel Binomialverteilung $$ B_{n,p}(k) = \begin{pmatrix} n \\ k \end{pmatrix} p^k (1-p)^{n-k} $$
P = stats.binom(22, 0.34)
an eine diskrete Verteilung haben wir zwei Typen von Fragen:
(1) Was ist der Wert der Verteilung für ein bestimmtes $k$ (Lektion 5)
P.pmf(7)
0.17593323858999418
pmf
probabiliy mass distribution
Das können wir auch zu Fuß ausrechnen
from scipy import special
special.binom(22, 7) * 0.34**7 * (1-0.34)**15
0.17593323858999396
0.17593323858999418 / 0.17593323858999396
1.0000000000000013
(2) Was ist der Wert der Verteilungsfunktion (Lektion 8)
P.cdf(7)
0.5133586582890823
P.cdf
cumulative distribution function
Das ist zu Fuß schon ziemlich umständlich:
P.pmf(0) + P.pmf(1) + P.pmf(2) + P.pmf(3) + P.pmf(4) + P.pmf(5) + P.pmf(6) + P.pmf(7)
0.513358658289081
kontinuierliche Verteilungen¶
wir kennen drei kontinuierliche Verteilungen
- Normalverteilung
stats.norm
- $t$-Verteilung
stats.t
- $F$-Verteilung
stats.f
Beispiel Normalverteilung:
P = stats.norm(22.4, 7.2)
für uns wichtig ist nur die Frage nach der Verteilungsfunktion
P.cdf(22.9)
0.5276820736327322
Was hat ANOVA mit Varianzen bzw. Stichprobenstreuungen zu tun?¶
ANOVA: "Analysis of Variance"
Wir gehen zurück zum Beispiel Schadstoffkonzentration
u_schad = "https://www.math.uni-duesseldorf.de/~braun/bio2324/data/schadstoffe.csv"
df = pd.read_csv(u_schad, index_col=0)
df.head()
Messstelle | Konzentration | |
---|---|---|
0 | 5 | 0.000867 |
1 | 3 | 0.000490 |
2 | 1 | 0.000589 |
3 | 1 | 0.000950 |
4 | 4 | 0.001152 |
g1 = df[df.Messstelle==1].Konzentration
g2 = df[df.Messstelle==2].Konzentration
g3 = df[df.Messstelle==3].Konzentration
g4 = df[df.Messstelle==4].Konzentration
g5 = df[df.Messstelle==5].Konzentration
df.Konzentration.std()
0.00034083567416156316
g1.std()
0.0003088278193577403
g2.std()
0.0004360906113112883
g3.std()
0.00033459177573784817
g4.std()
0.00032047637643428304
g5.std()
0.0003095504974203532
Die Stichprobenstreuung des gesamten Datensatzes ist ungefähr dieselbe wie die jeder einzelnen Gruppe
sns.scatterplot(df, y='Konzentration', x='Messstelle', hue='Messstelle', legend=False);
Jetzt dasselbe mit den Pinguinen
df = sns.load_dataset("penguins")
gA = df[df.species=='Adelie'].bill_length_mm.dropna()
gG = df[df.species=='Gentoo'].bill_length_mm.dropna()
gC = df[df.species=='Chinstrap'].bill_length_mm.dropna()
df.bill_length_mm.std()
5.4595837139265315
gA.std()
2.663404848368619
gG.std()
3.081857372114287
gC.std()
3.3392558959358865
- Die Stichprobenstreuung im gesamten Datensatz ist größer als in den einzelnen Gruppen.
- Der Unterschied kommt daher, dass sich die Gruppenmittelwerte stärker unterscheiden, als sich das durch Variation innerhalb der Gruppen erklären lässt
sns.scatterplot(df, y='bill_length_mm', x='species', hue='species', legend=False);
In der tatsächlich benutzen Formel kommt anstelle der Stichprobenstreuung die Varianz vor, daher der Name "Analysis of Varianz"
Heteroskedastizität¶
- Die ANOVA vergleicht die Varianzen innerhalb der einzelnen Gruppen mit der Varianz im gesamten Datensatz, um die Unterschiede zwischen den Gruppen zu untersuchen
- À priori geht das erstmal nur, wenn die Varianzen innerhalb der Gruppen gleich sind
- Ein Datensatz ist heteroskedastisch, wenn die verschiedenen Gruppen unterschiedliche Varianz haben
- Sonst ist er homoskedastisch
Der Levene-Test¶
Der Levene-Test testet auf Gleichheit der Varianzen
Drei verschiedene Lehrmethoden werden angewandt. Die Ergebnisse der Probandinnen und Probanden im Abschlusstest werden verglichen. Führen verschiedene Lehrmethoden zu unterschiedlichen Ergebnissen?
dfa = pd.DataFrame()
dfb = pd.DataFrame()
dfc = pd.DataFrame()
dfa['A'] = [42, 115, 73, 58, 64, 100, 112, 112, 52, 70,
152, 215, 176, 97, 145, 100, 82, 94, 165, 97]
dfb['B'] = [165, 165, 152, 173, 225, 173, 136, 145, 188, 155,
197, 233, 236, 264, 200, 252, 258, 212, 145, 273]
dfc['C'] = [236, 185, 339, 255, 264, 325, 267, 215, 233, 295,
255, 264, 224, 245, 248, 309, 264, 273, 294, 230]
Test auf Heteroskedastizität
stats.levene(dfa.A, dfb.B, dfc.C)
LeveneResult(statistic=0.6457341109631508, pvalue=0.5280694573759905)
- Der p-Wert ist 0.53. Hetereskedastizizät kann nicht nachgewiesen werden.
- Wir fahren mit der ANOVA fort
stats.f_oneway(dfa.A, dfb.B, dfc.C)
F_onewayResult(statistic=67.41573785674242, pvalue=9.532727011700098e-16)
Beispiel: Barsche¶
Es werden Barsche gleichen Alters verglichen
df = pd.read_csv('barsche.csv')
df.head()
Art | Länge | |
---|---|---|
0 | gestreift | 9.890006 |
1 | gestreift | 9.343944 |
2 | gestreift | 9.867069 |
3 | gestreift | 10.302781 |
4 | gestreift | 10.066964 |
sns.boxplot(data=df, x="Art", y="Länge");
Sieht heteroskedastisch aus.
ds = df[df.Art=='gestreift'].Länge
dl = df[df.Art=='gefleckt'].Länge
db = df[df.Art=='blau'].Länge
dr = df[df.Art=='braun'].Länge
stats.levene(ds, dl, dr, db)
LeveneResult(statistic=13.459492972830807, pvalue=1.3472893996510424e-07)
Probleme beim Test auf Heteroskedastizität¶
- Die Nullhypothese beim Levene-Test ist
$H_0$: Die Daten sind homoskedastisch
- Ein Hypothesentest "beweist" nie die Nullhypothese
- bei starken Indizien dagegen lehnt er sie ab
- bei starken Indizien dafür behält er sie bei
- bei unklaren Indizien behält er sie auch bei
- um zu erkennen, ob der Levene-Test Heteroskedastizität überhaupt erkennen kann, wäre eine Poweranalyse für den Levene-Test nötig, das ist aber unrealistisch
- auch das andere Extrem ist möglich: Der Stichprobenumfang ist so groß, dass kleine Unterschiede schon signifikant werden
👁️eyeballing (scharfes Hinsehen)
Alexander-Govern-Test¶
Wenn die Daten heteroskedastisch, aber normalverteilt sind, dann rechnet man einen Alexander-Govern-Test
stats.alexandergovern(ds, dl, dr, db)
AlexanderGovernResult(statistic=113.40810114676775, pvalue=2.02668339537414e-24)
Im homoskedastischen Fall ist der p-Wert des Alexander-Govern-Tests meist schlechter als der von f_oneway
stats.alexandergovern(dfa.A, dfb.B, dfc.C)
AlexanderGovernResult(statistic=56.825380493158306, pvalue=4.576415099851176e-13)
stats.f_oneway(dfa.A, dfb.B, dfc.C)
F_onewayResult(statistic=67.41573785674242, pvalue=9.532727011700098e-16)