Mathematik für Biologiestudierende II¶
Sommersemester 2024
04.06.2024
© 2024 Prof. Dr. Rüdiger W. Braun
Vorlesungsevaluation¶
- Bitte füllen Sie den Evaluationsbogen aus
- Der Bogen hat drei Seiten, die als zwei getrennte Blätter durchgereicht werden
- Bitte stecken Sie den ausgefüllten Bogen in den Briefumschlag, der durch die Reihen geht
Nr | Tag | Zeit | Leitung | Nr | Tag | Zeit | Leitung | |
---|---|---|---|---|---|---|---|---|
1 | Di | 14:30 | Adams | 6 | Do | 12:30 | Dreher (online) | |
2 | Do | 10:30 | Dubovci | 7 | Do | 17:30 | Dreher (online) | |
3 | Do | 11:30 | Dubovci | 8 | Fr | 11:30 | Mones | |
4 | Di | 13:30 | Adams | 9 | Fr | 12:30 | Mones | |
5 | Mi | 12:30 | Pukhova |
In [1]:
import numpy as np
import pandas as pd
from scipy import stats
import seaborn as sns
sns.set_theme()
Korrelation¶
- Eine Korrelation zwischen zwei Datensätzen ist eine gemeinsame oder gegenläufige Tendenz.
- Beispielsweise steigt der Blutdruck tendenziell mit dem Alter.
- Gemessen wird die Korrelation durch den empirischen Korrelationskoeffizienten.
- Der empirischen Korrelationskoeffizient beantwortet die Frage
Gibt es eine Korrelation?
- Die Antwort ist "ja", wenn der empirische Korrelationskoeffizient nahe bei $1$ oder bei $-1$ liegt.
Empirischer Korrelationskoeffizient¶
- Kennzahl zur Überprüfung gemeinsamer Tendenz
- $s_x$ sei die Stichprobenstreuung der $x_j$ und $s_y$ die Stichprobenstreuung der $y_j$
- dann ist der empirische Korrelationskoeffizient gleich $$ r = \frac{\text{covar}_{\text{emp}}(x,y)}{s_x \cdot s_y} $$
- Der Korrelationskoeffizient ist dimensionslos
Beispiel: Blutdruckdaten¶
Wir hatten in der letzten Woche die Kovarianz für die Blutdruckdaten bestimmt
In [2]:
df = pd.read_csv('blutdruckdaten.csv')
df.cov()
Out[2]:
Alter | Blutdruck | Größe | |
---|---|---|---|
Alter | 231.131034 | 348.572414 | 36.128966 |
Blutdruck | 348.572414 | 750.271264 | 69.805057 |
Größe | 36.128966 | 69.805057 | 28.617195 |
In [3]:
df.describe()
Out[3]:
Alter | Blutdruck | Größe | |
---|---|---|---|
count | 30.000000 | 30.000000 | 30.000000 |
mean | 44.800000 | 147.933333 | 176.373333 |
std | 15.202994 | 27.391080 | 5.349504 |
min | 17.000000 | 108.000000 | 165.300000 |
25% | 37.250000 | 125.250000 | 173.350000 |
50% | 45.000000 | 144.500000 | 176.650000 |
75% | 56.000000 | 173.250000 | 179.075000 |
max | 69.000000 | 199.000000 | 189.000000 |
In [4]:
cor = 348.57 / (15.203*27.391)
cor
Out[4]:
0.837052741260317
Berechnung mit pandas
¶
In [5]:
df.corr()
Out[5]:
Alter | Blutdruck | Größe | |
---|---|---|---|
Alter | 1.000000 | 0.837056 | 0.444235 |
Blutdruck | 0.837056 | 1.000000 | 0.476392 |
Größe | 0.444235 | 0.476392 | 1.000000 |
Interpretation¶
Der Korrelationskoeffizient zeigt an, ob zwei Datensätze eine gemeinsame Tendenz aufweisen
- wenn er nahe bei $1$ liegt, dann wachsen $x$ und $y$ gemeinsam (gemeinsame Tendenz)
- wenn er nahe bei $-1$ liegt, dann fällt $y$, wenn $x$ wächst (gegenläufige Tendenz)
- wenn er nahe bei $0$ liegt, dann gibt es kein gemeinsames Verhalten
- auch ein negativer Korrelationskoeffizient hat eine Bedeutung
- Beispiel: Je weniger Pestizide ich im Garten ausbringe, desto mehr Bienen habe ich
Beispiele¶
Sehr gute Korrelation¶
In [6]:
df1 = pd.DataFrame()
P = stats.norm()
df1['x'] = np.arange(30)
df1['y'] = -2*df1['x'] + P.rvs(size=30)
df1
Out[6]:
x | y | |
---|---|---|
0 | 0 | -1.486591 |
1 | 1 | -1.184042 |
2 | 2 | -4.739556 |
3 | 3 | -7.513850 |
4 | 4 | -8.014537 |
5 | 5 | -8.981178 |
6 | 6 | -12.287466 |
7 | 7 | -11.871206 |
8 | 8 | -15.786740 |
9 | 9 | -16.194542 |
10 | 10 | -19.393258 |
11 | 11 | -23.270504 |
12 | 12 | -24.049817 |
13 | 13 | -27.855954 |
14 | 14 | -28.356145 |
15 | 15 | -28.294222 |
16 | 16 | -33.086458 |
17 | 17 | -33.262553 |
18 | 18 | -35.568785 |
19 | 19 | -38.689206 |
20 | 20 | -39.626321 |
21 | 21 | -40.555186 |
22 | 22 | -42.716049 |
23 | 23 | -46.663774 |
24 | 24 | -49.322046 |
25 | 25 | -49.358499 |
26 | 26 | -52.406558 |
27 | 27 | -54.241921 |
28 | 28 | -55.718896 |
29 | 29 | -56.107155 |
In [7]:
sns.regplot(df1, x='x', y='y');
In [8]:
df1.corr()
Out[8]:
x | y | |
---|---|---|
x | 1.000000 | -0.998036 |
y | -0.998036 | 1.000000 |
schlechte Korrelation¶
In [9]:
df2 = pd.DataFrame()
df2['x'] = np.arange(30)
df2['y'] = P.rvs(size=30)
df2
Out[9]:
x | y | |
---|---|---|
0 | 0 | -0.343372 |
1 | 1 | -0.178586 |
2 | 2 | -1.617203 |
3 | 3 | 0.307267 |
4 | 4 | 0.168177 |
5 | 5 | -1.267749 |
6 | 6 | -1.318201 |
7 | 7 | 0.612708 |
8 | 8 | 0.642231 |
9 | 9 | -0.341919 |
10 | 10 | 0.500022 |
11 | 11 | 0.340752 |
12 | 12 | 0.685111 |
13 | 13 | 0.533139 |
14 | 14 | 0.315408 |
15 | 15 | -0.212932 |
16 | 16 | 0.156780 |
17 | 17 | 1.960430 |
18 | 18 | 0.506358 |
19 | 19 | -0.687712 |
20 | 20 | -0.128412 |
21 | 21 | 1.016593 |
22 | 22 | -0.119794 |
23 | 23 | 0.103425 |
24 | 24 | 1.545967 |
25 | 25 | -0.917972 |
26 | 26 | -0.292383 |
27 | 27 | -0.467781 |
28 | 28 | -0.079759 |
29 | 29 | -1.099349 |
In [10]:
sns.regplot(df2, x='x', y='y');
In [11]:
df2.corr()
Out[11]:
x | y | |
---|---|---|
x | 1.000000 | 0.101917 |
y | 0.101917 | 1.000000 |
- Man kann immer eine lineare Regression berechnen. Bei schlechter Korrelation ist sie allerdings bedeutungslos.
Regression zum Mittelwert¶
- Der Begriff Regression kommt von Francis Galton, einem Neffen von Charles Darwin
- Er hatte den auf der nächsten Folie gezeigten Datensatz analysiert
- Auf der $x$-Achse stehen die Größen der Väter in Zoll
- Auf der $y$-Achse stehen die Größen der Söhne in Zoll
Regression zum Mittelwert: Interpretation¶
- Die Söhne ungewöhnlich großer oder kleiner Väter sind im Mittel selbst zwar auch größer bzw. kleiner als der Mittelwert, aber diese Differenz ist kleiner als bei den Vätern
- Galton bezeichnet dies (ziemlich unfreundlich) als "Regression to mediocrity"
- Das gilt aber nur für die Individuen, nicht für die Population als Ganzes
- auch in der nächsten Generation gibt es wieder ungewöhnlich große Individuen, aber in anderen Familien
Korrelation $\ne$ Kausalität¶
- Wenn der Korrelationskoeffizient von $x$ und $y$ nahe $0$ liegt, dann gibt es keinen kausalen Zusammenhang zwischen ihnen (seltene nichtlineare Pänomene mal ausgenommen)
- Man kann aber im umgekehrten Fall von einem Korrelationskoeffizienten nahe bei $1$ nicht auf einen kausalen Zusammenhang schließen
- Zum Beispiel nimmt seit Jahrzehnten in Deutschland sowohl die Zahl der Geburten als auch die Zahl der Störche ab
- Der kausale Zusammenhang ist aber umstritten
- Beispiel aus der Schlafforschung: Mittagsschlafdauern über 90 Minuten sind ungesund
- Bei Menschen korreliert die Rechtschreibfähigkeit mit der Schuhgröße
- zumindest bei Menschen unter zehn Jahren
Quelle: http://xkcd.com/552
Beispiel: Bleibelastung im Gewebe von Ratten¶
- kontaminiertes Gelände: fange 10 Ratten
- unbelastetes Vergleichsgelände: fange 10 Ratten
- für jede Ratte wird ihr Alter in Monaten und der Bleigehalt im Gewebe bestimmt
In [12]:
df = pd.read_csv('ratten.csv')
df
Out[12]:
Alter | Belastung | Gelände | |
---|---|---|---|
0 | 10 | 63 | unbelastet |
1 | 12 | 67 | unbelastet |
2 | 6 | 55 | unbelastet |
3 | 6 | 42 | unbelastet |
4 | 11 | 73 | unbelastet |
5 | 13 | 69 | unbelastet |
6 | 12 | 73 | unbelastet |
7 | 10 | 75 | unbelastet |
8 | 9 | 58 | unbelastet |
9 | 8 | 50 | unbelastet |
10 | 8 | 70 | belastet |
11 | 10 | 60 | belastet |
12 | 4 | 53 | belastet |
13 | 4 | 50 | belastet |
14 | 9 | 77 | belastet |
15 | 11 | 78 | belastet |
16 | 10 | 81 | belastet |
17 | 8 | 65 | belastet |
18 | 7 | 64 | belastet |
19 | 6 | 67 | belastet |
In [13]:
df_b = df[df.Gelände=='belastet']
df_u = df[df.Gelände=='unbelastet']
In [14]:
df_b.describe()
Out[14]:
Alter | Belastung | |
---|---|---|
count | 10.000000 | 10.000000 |
mean | 7.700000 | 66.500000 |
std | 2.451757 | 10.384283 |
min | 4.000000 | 50.000000 |
25% | 6.250000 | 61.000000 |
50% | 8.000000 | 66.000000 |
75% | 9.750000 | 75.250000 |
max | 11.000000 | 81.000000 |
In [15]:
df_u.describe()
Out[15]:
Alter | Belastung | |
---|---|---|
count | 10.000000 | 10.000000 |
mean | 9.700000 | 62.500000 |
std | 2.451757 | 11.017663 |
min | 6.000000 | 42.000000 |
25% | 8.250000 | 55.750000 |
50% | 10.000000 | 65.000000 |
75% | 11.750000 | 72.000000 |
max | 13.000000 | 75.000000 |
- Es gibt einen Unterschied in der Bleibelastung; aber auch eine große Stichprobenstreuung.
In [16]:
stats.ttest_ind(df_u.Belastung, df_b.Belastung, alternative='less')
Out[16]:
TtestResult(statistic=-0.8354714854531734, pvalue=0.20720251637482168, df=18.0)
- Der Unterschied ist nicht signifikant.
- Es fällt aber auf, dass die Ratten von dem belasteten Gebiet im Mittel jünger als die anderen sind.
- Wir wollen das Alter herausrechnen
- Steigt die Bleibelastung mit dem Alter
In [17]:
df_b.corr(numeric_only=True)
Out[17]:
Alter | Belastung | |
---|---|---|
Alter | 1.000000 | 0.796465 |
Belastung | 0.796465 | 1.000000 |
In [18]:
df_u.corr(numeric_only=True)
Out[18]:
Alter | Belastung | |
---|---|---|
Alter | 1.00000 | 0.82883 |
Belastung | 0.82883 | 1.00000 |
Wir plotten beide Regressionen in ein Bild, ähnlich wie bei distplot
In [19]:
sns.lmplot(df, x='Alter', y='Belastung', hue='Gelände');