Wintersemester 2023/24
24.01.2024
© 2024 Prof. Dr. Rüdiger W. Braun
Das bedeutet $$ \Phi\left( \frac{50 - 0.8 \cdot n}{\sqrt{0.16 \cdot n}} \right) = 0.1 $$
import numpy as np
from scipy import stats
Phi = stats.norm()
Phi.ppf(0.1)
-1.2815515655446004
Nenner hochmultiplizieren
-1.28155 * np.sqrt(0.16)
-0.51262
Trick: Wir nennen $\sqrt n$ mal kurz $x$ und bringen alles auf die linke Seite. Dann können wir mit der p-q-Formel weitermachen
$$ 50 - 0.8 x^2 + 0.51262 x = 0 $$50 / 0.8
62.5
0.51262 / 0.8
0.6407749999999999
Die negative Lösung ist unsinnig
x = 0.640775 / 2 + np.sqrt(0.640775**2/4 + 62.5)
x
8.232571026066383
n = x**2
n
67.77522569922769
Also 68 Tiere.
Das ist dasselbe Ergebnis, das wir in Lektion 6 mit zwei anderen Methoden herausbekommen hatten.
Zwei Versuchsreihen liefern Messergebnisse. Der Test soll entscheiden, ob sich diese Ergebnisse signifikant unterscheiden.
Unverbundene Stichproben: Die Messerergebnisse werden an verschiedenen Populationen gewonnen.
Beispiel: 9 Maisfelder werden mit einem Bodenbakterium behandelt, 10 weitere bleiben unbehandelt. Bei allen wird der Befall mit Maiszünsler bestimmt.
Verbundene Stichproben: Beide Messungen werden an derselben Population durchgeführt.
Beispiel: Bei 10 Patienten mit Bluthochdruck wird der Blutdruck vor und nach einer Therapie bestimmt.
stats.t(f)
from scipy import stats
P = stats.t(30)
Die Verteilungsfunktion heißt wie immer cdf
P.cdf(0)
0.5
Das Quantil heißt ppf
P.ppf(0.95)
1.6972608943617378
Zum Vergleich
stats.norm().ppf(0.95)
1.6448536269514722
Heuristisch:
Das benötigte Quantil ist
P = stats.t(9)
P.ppf(0.95)
1.8331129326536335
import pandas as pd
df = pd.DataFrame()
df['x'] = [168, 184, 172, 173, 150, 155, 163, 164, 151, 146]
df['y'] = [176, 145, 150, 163, 136, 168, 164, 139, 145, 112]
df
x | y | |
---|---|---|
0 | 168 | 176 |
1 | 184 | 145 |
2 | 172 | 150 |
3 | 173 | 163 |
4 | 150 | 136 |
5 | 155 | 168 |
6 | 163 | 164 |
7 | 164 | 139 |
8 | 151 | 145 |
9 | 146 | 112 |
df['z'] = df.x - df.y
df.z.describe()
count 10.000000 mean 12.800000 std 17.364075 min -13.000000 25% 0.750000 50% 12.000000 75% 24.250000 max 39.000000 Name: z, dtype: float64
t = 12.8 / 17.3641 * np.sqrt(10)
t
2.3310827540820003
Das ist größer als das Quantil: Die Nullhypothese kann abgelehnt werden. Die Wirksamkeit des Blutdruchsenkers ist zu dem angegebenen Signifikanzniveau nachgewiesen.
stats.ttest_rel(df.x, df.y, alternative="greater")
TtestResult(statistic=2.331086069657434, pvalue=0.02233380789226441, df=9)
res = stats.ttest_rel(df.x, df.y, alternative="greater")
res.statistic # Die Teststatistik
2.331086069657434
res.pvalue # Der p-Wert
0.02233380789226441
Der p-Wert ist kleiner als das Signifikanzniveau $\alpha=0.05$, also kann $H_0$ abgelehnt werden
res.df # Die Anzahl der Freiheitsgrade
9
Das ist der Spezialfall, bei dem der zweite Datensatz für alle Einträge gleich dem Referenzwert ist
Beispiel
u = "https://www.math.uni-duesseldorf.de/~braun/bio2324/data/schadstoffe.csv"
df = pd.read_csv(u, index_col=0)
df
Messstelle | Konzentration | |
---|---|---|
0 | 5 | 0.000867 |
1 | 3 | 0.000490 |
2 | 1 | 0.000589 |
3 | 1 | 0.000950 |
4 | 4 | 0.001152 |
... | ... | ... |
75 | 5 | 0.000918 |
76 | 3 | 0.000528 |
77 | 3 | 0.000961 |
78 | 4 | 0.001272 |
79 | 3 | 0.001012 |
80 rows × 2 columns
df.loc[0].Konzentration
0.0008665284923875
df.describe()
Messstelle | Konzentration | |
---|---|---|
count | 80.000000 | 80.000000 |
mean | 2.987500 | 0.000905 |
std | 1.409675 | 0.000341 |
min | 1.000000 | 0.000061 |
25% | 2.000000 | 0.000701 |
50% | 3.000000 | 0.000938 |
75% | 4.000000 | 0.001158 |
max | 5.000000 | 0.001605 |
df['referenz'] = 0.08 / 100
res = stats.ttest_rel(df.Konzentration, df.referenz, alternative="greater")
res
TtestResult(statistic=2.768040010585661, pvalue=0.0035114445640696246, df=79)
res.pvalue
0.0035114445640696246
Zum Signifikanzniveau $\alpha=0.01$ ist die Überschreitung der Grenzwerte nachgewiesen
Bestimme arithmetische Mittelwerte $$ \overline x = \frac1{n_1} \sum_{j=1}^{n_1} x_j \text{ und } \overline y = \frac1{n_2} \sum_{j=1}^{n_2} y_j $$
und Stichprobenstreuungen
df = pd.DataFrame()
# so gehts es leider nicht
#df['unbehandelt'] = [55 , 69 , 64 , 70 , 75 , 70 , 83 , 69 , 75 , 69]
#df['behandelt'] = [61 , 60 , 62 , 58 , 75 , 63 , 52 , 66 , 59]
df1 = pd.DataFrame()
df1['Befall'] = [61 , 60 , 62 , 58 , 75 , 63 , 52 , 66 , 59]
df1['Behandlung'] = 'ja'
df2 = pd.DataFrame()
df2['Befall'] = [55 , 69 , 64 , 70 , 75 , 70 , 83 , 69 , 75 , 69]
df2['Behandlung'] = 'nein'
df = pd.concat([df1, df2], ignore_index=True)
df
Befall | Behandlung | |
---|---|---|
0 | 61 | ja |
1 | 60 | ja |
2 | 62 | ja |
3 | 58 | ja |
4 | 75 | ja |
5 | 63 | ja |
6 | 52 | ja |
7 | 66 | ja |
8 | 59 | ja |
9 | 55 | nein |
10 | 69 | nein |
11 | 64 | nein |
12 | 70 | nein |
13 | 75 | nein |
14 | 70 | nein |
15 | 83 | nein |
16 | 69 | nein |
17 | 75 | nein |
18 | 69 | nein |
import seaborn as sns
sns.set_theme()
sns.displot(data=df, x='Befall', hue='Behandlung', multiple='stack');
/az076/miniconda3/envs/bio/lib/python3.11/site-packages/seaborn/axisgrid.py:118: UserWarning: The figure layout has changed to tight self._figure.tight_layout(*args, **kwargs)
df1.describe()
Befall | |
---|---|
count | 9.000000 |
mean | 61.777778 |
std | 6.280481 |
min | 52.000000 |
25% | 59.000000 |
50% | 61.000000 |
75% | 63.000000 |
max | 75.000000 |
df2.describe()
Befall | |
---|---|
count | 10.000000 |
mean | 69.900000 |
std | 7.324995 |
min | 55.000000 |
25% | 69.000000 |
50% | 69.500000 |
75% | 73.750000 |
max | 83.000000 |
zaehler = 9*7.325**2 + 8*6.281**2
nenner = 17
std_pool = np.sqrt( zaehler / nenner )
std_pool
6.853544866366173
faktor = 10*9 / (10+9)
t = (61.778 - 69.9) / std_pool * np.sqrt(faktor)
t # Teststatistik
-2.579242516807668
P = stats.t(17)
P.ppf(0.95)
1.7396067260750672
Es gilt $t < -t_{17,0.95}$, also wird die Nullhypothese abgelehnt
stats.ttest_ind(df1.Befall, df2.Befall, alternative="less")
TtestResult(statistic=-2.5793982980797687, pvalue=0.009746177193200247, df=17.0)
Der p-Wert ist 0.01
stats.ttest_rel(x,y,alternative)
t-Test für verbundene Stichproben (engl: related)stats.ttest_ind(x,y,alternative)
t-Test für unverbundene Stichproben (engl: independent)less
, greater
oder two-sided
df = sns.load_dataset("penguins")
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
Unterscheiden sich die Flügellängen von Adelie- und Zügelpinguinen?
adelie = df[df.species=='Adelie']
zuegel = df[df.species=='Chinstrap']
# stats.ttest_ind(adelie, zuegel) # scheitert wegen NaN
adelie.dropna()
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 |
4 | Adelie | Torgersen | 36.7 | 19.3 | 193.0 | 3450.0 | Female |
5 | Adelie | Torgersen | 39.3 | 20.6 | 190.0 | 3650.0 | Male |
... | ... | ... | ... | ... | ... | ... | ... |
147 | Adelie | Dream | 36.6 | 18.4 | 184.0 | 3475.0 | Female |
148 | Adelie | Dream | 36.0 | 17.8 | 195.0 | 3450.0 | Female |
149 | Adelie | Dream | 37.8 | 18.1 | 193.0 | 3750.0 | Male |
150 | Adelie | Dream | 36.0 | 17.1 | 187.0 | 3700.0 | Female |
151 | Adelie | Dream | 41.5 | 18.5 | 201.0 | 4000.0 | Male |
146 rows × 7 columns
stats.ttest_ind(adelie.flipper_length_mm.dropna(),
zuegel.flipper_length_mm.dropna()) # two-sided ist Voreinstellung
TtestResult(statistic=-5.9740408058206125, pvalue=9.378738333570485e-09, df=217.0)
Der Unterschied ist signifikant
Offizielle Klausurtermine auf den Seiten der Biologie https://www.biologie.hhu.de/
Die Klausur am 22.02.2024 richtet sich ausschließlich an Wiederholer