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 | 0.817915 |
1 | 1 | -0.984298 |
2 | 2 | -3.775090 |
3 | 3 | -6.125030 |
4 | 4 | -8.319028 |
5 | 5 | -11.003132 |
6 | 6 | -11.809764 |
7 | 7 | -13.118088 |
8 | 8 | -14.341614 |
9 | 9 | -18.172484 |
10 | 10 | -19.242826 |
11 | 11 | -22.360211 |
12 | 12 | -26.361336 |
13 | 13 | -25.407310 |
14 | 14 | -27.765344 |
15 | 15 | -28.871056 |
16 | 16 | -32.861575 |
17 | 17 | -33.346099 |
18 | 18 | -35.740095 |
19 | 19 | -38.113468 |
20 | 20 | -41.292656 |
21 | 21 | -41.391056 |
22 | 22 | -44.840173 |
23 | 23 | -44.915220 |
24 | 24 | -48.043995 |
25 | 25 | -50.034775 |
26 | 26 | -52.250311 |
27 | 27 | -54.097706 |
28 | 28 | -56.108222 |
29 | 29 | -57.821771 |
In [7]:
sns.regplot(df1, x='x', y='y');
In [8]:
df1.corr()
Out[8]:
x | y | |
---|---|---|
x | 1.000000 | -0.998955 |
y | -0.998955 | 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.596320 |
1 | 1 | 1.955290 |
2 | 2 | -1.423429 |
3 | 3 | 0.916467 |
4 | 4 | 0.249895 |
5 | 5 | -0.196226 |
6 | 6 | -0.958411 |
7 | 7 | -0.217308 |
8 | 8 | 1.946565 |
9 | 9 | -0.041887 |
10 | 10 | 0.904979 |
11 | 11 | -0.926685 |
12 | 12 | 0.272166 |
13 | 13 | 1.185755 |
14 | 14 | -0.819968 |
15 | 15 | -0.401578 |
16 | 16 | -0.480274 |
17 | 17 | -0.057313 |
18 | 18 | -0.322542 |
19 | 19 | 0.184700 |
20 | 20 | 1.114620 |
21 | 21 | -1.145277 |
22 | 22 | -0.038550 |
23 | 23 | 0.601807 |
24 | 24 | 0.152455 |
25 | 25 | 0.182674 |
26 | 26 | -0.723546 |
27 | 27 | 0.999886 |
28 | 28 | -1.152555 |
29 | 29 | -0.738527 |
In [10]:
sns.regplot(df2, x='x', y='y');
In [11]:
df2.corr()
Out[11]:
x | y | |
---|---|---|
x | 1.000000 | -0.147891 |
y | -0.147891 | 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 | unkontaminiert |
1 | 12 | 67 | unkontaminiert |
2 | 6 | 55 | unkontaminiert |
3 | 6 | 42 | unkontaminiert |
4 | 11 | 73 | unkontaminiert |
5 | 13 | 69 | unkontaminiert |
6 | 12 | 73 | unkontaminiert |
7 | 10 | 75 | unkontaminiert |
8 | 9 | 58 | unkontaminiert |
9 | 8 | 50 | unkontaminiert |
10 | 8 | 70 | kontaminiert |
11 | 10 | 60 | kontaminiert |
12 | 4 | 53 | kontaminiert |
13 | 4 | 50 | kontaminiert |
14 | 9 | 77 | kontaminiert |
15 | 11 | 78 | kontaminiert |
16 | 10 | 81 | kontaminiert |
17 | 8 | 65 | kontaminiert |
18 | 7 | 64 | kontaminiert |
19 | 6 | 67 | kontaminiert |
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 | 0.0 | 0.0 |
mean | NaN | NaN |
std | NaN | NaN |
min | NaN | NaN |
25% | NaN | NaN |
50% | NaN | NaN |
75% | NaN | NaN |
max | NaN | NaN |
In [15]:
df_u.describe()
Out[15]:
Alter | Belastung | |
---|---|---|
count | 0.0 | 0.0 |
mean | NaN | NaN |
std | NaN | NaN |
min | NaN | NaN |
25% | NaN | NaN |
50% | NaN | NaN |
75% | NaN | NaN |
max | NaN | NaN |
- 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')
/tmp/ipykernel_22669/579058202.py:1: SmallSampleWarning: One or more sample arguments is too small; all returned values will be NaN. See documentation for sample size requirements. stats.ttest_ind(df_u.Belastung, df_b.Belastung, alternative='less')
Out[16]:
TtestResult(statistic=nan, pvalue=nan, df=nan)
- 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 | NaN | NaN |
Belastung | NaN | NaN |
In [18]:
df_u.corr(numeric_only=True)
Out[18]:
Alter | Belastung | |
---|---|---|
Alter | NaN | NaN |
Belastung | NaN | NaN |
Wir plotten beide Regressionen in ein Bild, ähnlich wie bei distplot
In [19]:
sns.lmplot(df, x='Alter', y='Belastung', hue='Gelände');