You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Data-Science-For-Beginners/translations/de/1-Introduction/04-stats-and-probability/notebook.ipynb

581 lines
19 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Einführung in Wahrscheinlichkeit und Statistik\n",
"In diesem Notebook werden wir mit einigen der zuvor besprochenen Konzepte spielen. Viele Konzepte aus Wahrscheinlichkeit und Statistik sind gut vertreten in wichtigen Bibliotheken für die Datenverarbeitung in Python, wie `numpy` und `pandas`.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import pandas as pd\n",
"import random\n",
"import matplotlib.pyplot as plt"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Zufallsvariablen und Verteilungen\n",
"Beginnen wir damit, eine Stichprobe von 30 Werten aus einer Gleichverteilung von 0 bis 9 zu ziehen. Wir werden auch Mittelwert und Varianz berechnen.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"sample = [ random.randint(0,10) for _ in range(30) ]\n",
"print(f\"Sample: {sample}\")\n",
"print(f\"Mean = {np.mean(sample)}\")\n",
"print(f\"Variance = {np.var(sample)}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Um visuell abzuschätzen, wie viele verschiedene Werte in der Stichprobe vorhanden sind, können wir das **Histogramm** zeichnen:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.hist(sample)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Analyse realer Daten\n",
"\n",
"Mittelwert und Varianz sind beim Analysieren realer Daten sehr wichtig. Laden wir die Daten über Baseballspieler von [SOCR MLB Height/Weight Data](http://wiki.stat.ucla.edu/socr/index.php/SOCR_Data_MLB_HeightsWeights) herunter.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df = pd.read_csv(\"../../data/SOCR_MLB.tsv\",sep='\\t', header=None, names=['Name','Team','Role','Weight','Height','Age'])\n",
"df\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> Wir verwenden hier ein Paket namens [**Pandas**](https://pandas.pydata.org/) für die Datenanalyse. Später in diesem Kurs werden wir mehr über Pandas und die Arbeit mit Daten in Python sprechen.\n",
"\n",
"Lassen Sie uns den Durchschnittswert für Alter, Größe und Gewicht berechnen:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df[['Age','Height','Weight']].mean()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Kommen wir nun zur Größe und berechnen die Standardabweichung und Varianz:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(list(df['Height'])[:20])"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"mean = df['Height'].mean()\n",
"var = df['Height'].var()\n",
"std = df['Height'].std()\n",
"print(f\"Mean = {mean}\\nVariance = {var}\\nStandard Deviation = {std}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Zusätzlich zum Mittelwert ist es sinnvoll, den Median und die Quartile zu betrachten. Diese können mithilfe eines **Boxplots** visualisiert werden:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.figure(figsize=(10,2))\n",
"plt.boxplot(df['Height'].ffill(), vert=False, showmeans=True)\n",
"plt.grid(color='gray', linestyle='dotted')\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Wir können auch Boxplots von Teilmengen unseres Datensatzes erstellen, zum Beispiel gruppiert nach Spielerrolle.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df.boxplot(column='Height', by='Role', figsize=(10,8))\n",
"plt.xticks(rotation='vertical')\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> **Hinweis**: Dieses Diagramm legt nahe, dass im Durchschnitt die Körpergrößen der First Basemen höher sind als die der Second Basemen. Später werden wir lernen, wie wir diese Hypothese formaler testen können und wie wir zeigen können, dass unsere Daten statistisch signifikant sind, um dies zu belegen. \n",
"\n",
"Alter, Größe und Gewicht sind alle stetige Zufallsvariablen. Was denkst du, wie ihre Verteilung aussieht? Eine gute Möglichkeit, das herauszufinden, ist es, ein Histogramm der Werte zu zeichnen: \n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df['Weight'].hist(bins=15, figsize=(10,6))\n",
"plt.suptitle('Weight distribution of MLB Players')\n",
"plt.xlabel('Weight')\n",
"plt.ylabel('Count')\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Normalverteilung\n",
"\n",
"Lassen Sie uns eine künstliche Stichprobe von Gewichten erstellen, die einer Normalverteilung mit demselben Mittelwert und derselben Varianz wie unsere echten Daten folgt:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"generated = np.random.normal(mean, std, 1000)\n",
"generated[:20]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.figure(figsize=(10,6))\n",
"plt.hist(generated, bins=15)\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.figure(figsize=(10,6))\n",
"plt.hist(np.random.normal(0,1,50000), bins=300)\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Da die meisten Werte im wirklichen Leben normalverteilt sind, sollten wir keinen gleichmäßigen Zufallszahlengenerator verwenden, um Beispieldaten zu erzeugen. So sieht es aus, wenn wir versuchen, Gewichte mit einer gleichmäßigen Verteilung (generiert mit `np.random.rand`) zu erzeugen:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"wrong_sample = np.random.rand(1000)*2*std+mean-std\n",
"plt.figure(figsize=(10,6))\n",
"plt.hist(wrong_sample)\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Konfidenzintervalle\n",
"\n",
"Lassen Sie uns nun Konfidenzintervalle für das Gewicht und die Größe von Baseballspielern berechnen. Wir verwenden den Code [aus dieser Stackoverflow-Diskussion](https://stackoverflow.com/questions/15033511/compute-a-confidence-interval-from-sample-data):\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import scipy.stats\n",
"\n",
"def mean_confidence_interval(data, confidence=0.95):\n",
" a = 1.0 * np.array(data)\n",
" n = len(a)\n",
" m, se = np.mean(a), scipy.stats.sem(a)\n",
" h = se * scipy.stats.t.ppf((1 + confidence) / 2., n-1)\n",
" return m, h\n",
"\n",
"for p in [0.85, 0.9, 0.95]:\n",
" m, h = mean_confidence_interval(df['Weight'].fillna(method='pad'),p)\n",
" print(f\"p={p:.2f}, mean = {m:.2f} ± {h:.2f}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Hypothesentest\n",
"\n",
"Lassen Sie uns verschiedene Positionen in unserem Baseball-Spielerdatensatz untersuchen:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df.groupby('Role').agg({ 'Weight' : 'mean', 'Height' : 'mean', 'Age' : 'count'}).rename(columns={ 'Age' : 'Count'})"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Lassen Sie uns die Hypothese testen, dass Erste Basisspieler größer sind als Zweite Basisspieler. Die einfachste Methode dafür ist, die Konfidenzintervalle zu überprüfen:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"for p in [0.85,0.9,0.95]:\n",
" m1, h1 = mean_confidence_interval(df.loc[df['Role']=='First_Baseman',['Height']],p)\n",
" m2, h2 = mean_confidence_interval(df.loc[df['Role']=='Second_Baseman',['Height']],p)\n",
" print(f'Conf={p:.2f}, 1st basemen height: {m1-h1[0]:.2f}..{m1+h1[0]:.2f}, 2nd basemen height: {m2-h2[0]:.2f}..{m2+h2[0]:.2f}')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Wir können sehen, dass sich die Intervalle nicht überschneiden.\n",
"\n",
"Eine statistisch korrektere Methode, um die Hypothese zu überprüfen, ist die Verwendung eines **Student-t-Tests**:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from scipy.stats import ttest_ind\n",
"\n",
"tval, pval = ttest_ind(df.loc[df['Role']=='First_Baseman',['Height']], df.loc[df['Role']=='Second_Baseman',['Height']],equal_var=False)\n",
"print(f\"T-value = {tval[0]:.2f}\\nP-value: {pval[0]}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Die beiden von der Funktion `ttest_ind` zurückgegebenen Werte sind: \n",
"* Der p-Wert kann als die Wahrscheinlichkeit betrachtet werden, dass zwei Verteilungen den gleichen Mittelwert haben. In unserem Fall ist er sehr niedrig, was darauf hinweist, dass es starke Hinweise darauf gibt, dass erste Basemen größer sind. \n",
"* Der t-Wert ist der Zwischenschritt des normalisierten Mittelwertunterschieds, der im t-Test verwendet wird und mit einem Schwellwert für einen bestimmten Vertrauenswert verglichen wird.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Simulation einer Normalverteilung mit dem Zentralen Grenzwertsatz\n",
"\n",
"Der Pseudozufallsgenerator in Python ist so konzipiert, dass er uns eine gleichmäßige Verteilung liefert. Wenn wir einen Generator für die Normalverteilung erstellen möchten, können wir den zentralen Grenzwertsatz verwenden. Um einen normalverteilten Wert zu erhalten, berechnen wir einfach den Mittelwert einer gleichmäßig generierten Stichprobe.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def normal_random(sample_size=100):\n",
" sample = [random.uniform(0,1) for _ in range(sample_size) ]\n",
" return sum(sample)/sample_size\n",
"\n",
"sample = [normal_random() for _ in range(100)]\n",
"plt.figure(figsize=(10,6))\n",
"plt.hist(sample)\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Korrelation und Evil Baseball Corp\n",
"\n",
"Korrelation ermöglicht es uns, Beziehungen zwischen Datenfolgen zu finden. In unserem einfachen Beispiel tun wir so, als gäbe es eine böse Baseballfirma, die ihre Spieler entsprechend ihrer Körpergröße bezahlt je größer der Spieler ist, desto mehr Geld erhält er/sie. Angenommen, es gibt ein Grundgehalt von 1000 $, und einen zusätzlichen Bonus von 0 bis 100 $, abhängig von der Körpergröße. Wir nehmen die echten Spieler der MLB und berechnen deren imaginäres Gehalt:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"heights = df['Height'].fillna(method='pad')\n",
"salaries = 1000+(heights-heights.min())/(heights.max()-heights.mean())*100\n",
"print(list(zip(heights, salaries))[:10])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Berechnen wir nun die Kovarianz und Korrelation dieser Sequenzen. `np.cov` liefert uns eine sogenannte **Kovarianzmatrix**, die eine Erweiterung der Kovarianz auf mehrere Variablen darstellt. Das Element $M_{ij}$ der Kovarianzmatrix $M$ ist eine Kovarianz zwischen den Eingangsvariablen $X_i$ und $X_j$, und die Diagonalwerte $M_{ii}$ sind die Varianz von $X_{i}$. Ähnlich liefert `np.corrcoef` uns die **Korrelationsmatrix**.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(f\"Covariance matrix:\\n{np.cov(heights, salaries)}\")\n",
"print(f\"Covariance = {np.cov(heights, salaries)[0,1]}\")\n",
"print(f\"Correlation = {np.corrcoef(heights, salaries)[0,1]}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Eine Korrelation von 1 bedeutet, dass eine starke **lineare Beziehung** zwischen zwei Variablen besteht. Wir können die lineare Beziehung visuell sehen, indem wir einen Wert gegen den anderen auftragen:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.figure(figsize=(10,6))\n",
"plt.scatter(heights,salaries)\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Mal sehen, was passiert, wenn die Beziehung nicht linear ist. Angenommen, unser Unternehmen hätte beschlossen, die offensichtliche lineare Abhängigkeit zwischen Größen und Gehältern zu verbergen und eine gewisse Nicht-Linearität in die Formel einzuführen, wie zum Beispiel `sin`:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"salaries = 1000+np.sin((heights-heights.min())/(heights.max()-heights.mean()))*100\n",
"print(f\"Correlation = {np.corrcoef(heights, salaries)[0,1]}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In diesem Fall ist die Korrelation etwas geringer, aber immer noch ziemlich hoch. Nun, um die Beziehung noch weniger offensichtlich zu machen, könnten wir etwas zusätzliche Zufälligkeit hinzufügen, indem wir eine Zufallsvariable zum Gehalt addieren. Mal sehen, was passiert:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"salaries = 1000+np.sin((heights-heights.min())/(heights.max()-heights.mean()))*100+np.random.random(size=len(heights))*20-10\n",
"print(f\"Correlation = {np.corrcoef(heights, salaries)[0,1]}\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.figure(figsize=(10,6))\n",
"plt.scatter(heights, salaries)\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> Können Sie erraten, warum die Punkte sich zu solchen vertikalen Linien anordnen?\n",
"\n",
"Wir haben die Korrelation zwischen einem künstlich entwickelten Konzept wie dem Gehalt und der beobachteten Variable *Größe* untersucht. Schauen wir uns nun an, ob die beiden beobachteten Variablen, wie Größe und Gewicht, ebenfalls korrelieren:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"np.corrcoef(df['Height'].ffill(),df['Weight'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Leider haben wir keine Ergebnisse erhalten nur einige seltsame `nan`-Werte. Dies liegt daran, dass einige Werte in unserer Serie undefiniert sind, dargestellt als `nan`, was dazu führt, dass auch das Ergebnis der Operation undefiniert ist. Wenn wir uns die Matrix ansehen, erkennen wir, dass `Weight` die problematische Spalte ist, da die Selbstkorrelation zwischen den `Height`-Werten berechnet wurde.\n",
"\n",
"> Dieses Beispiel zeigt die Bedeutung von **Datenvorbereitung** und **Datenbereinigung**. Ohne richtige Daten können wir nichts berechnen.\n",
"\n",
"Lassen Sie uns die Methode `fillna` verwenden, um die fehlenden Werte zu füllen, und die Korrelation berechnen: \n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"np.corrcoef(df['Height'].fillna(method='pad'), df['Weight'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Es gibt tatsächlich eine Korrelation, aber keine so starke wie in unserem künstlichen Beispiel. Wenn wir uns tatsächlich das Streudiagramm eines Werts gegen den anderen ansehen, wäre die Beziehung viel weniger offensichtlich:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.figure(figsize=(10,6))\n",
"plt.scatter(df['Weight'],df['Height'])\n",
"plt.xlabel('Weight')\n",
"plt.ylabel('Height')\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Fazit\n",
"\n",
"In diesem Notebook haben wir gelernt, wie man grundlegende Operationen an Daten durchführt, um statistische Funktionen zu berechnen. Wir wissen jetzt, wie man ein solides Arsenal an Mathematik und Statistik einsetzt, um Hypothesen zu überprüfen, und wie man Konfidenzintervalle für beliebige Variablen anhand einer Datenstichprobe berechnet. \n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n\n<!-- CO-OP TRANSLATOR DISCLAIMER START -->\n**Haftungsausschluss**: \nDieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir um Genauigkeit bemüht sind, können automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten. Das Originaldokument in seiner Ausgangssprache sollte als maßgebliche Quelle angesehen werden. Für wichtige Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die aus der Nutzung dieser Übersetzung entstehen.\n<!-- CO-OP TRANSLATOR DISCLAIMER END -->\n"
]
}
],
"metadata": {
"interpreter": {
"hash": "86193a1ab0ba47eac1c69c1756090baa3b420b3eea7d4aafab8b85f8b312f0c5"
},
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.6"
},
"coopTranslator": {
"original_hash": "0f899e3c5019f948e7c787b22f3b2304",
"translation_date": "2026-01-16T08:21:36+00:00",
"source_file": "1-Introduction/04-stats-and-probability/notebook.ipynb",
"language_code": "de"
}
},
"nbformat": 4,
"nbformat_minor": 4
}