Commit 85035ca1 authored by Konrad Völkel's avatar Konrad Völkel
Browse files

kleinere markdown/sphinx fixes

parent 2977b03e
Pipeline #93440 passed with stages
in 4 minutes and 18 seconds
This diff is collapsed.
......@@ -54,6 +54,15 @@ Alle Grundlagen der Mathematik, die Sie zur Bearbeitung der Übungsaufgaben ben
könnte man auch fragen. Hautpsächlich dient uns das Skript als Referenz und Leitfaden für die Übungsaufgaben. Es gibt in der Tat hervorragende MOOCs (massive open online courses) frei im WWW, vor Allem wenn man gut Englisch spricht. Dieses Skript begleitet allerdings, im Gegensatz zu MOOCs, eine Präsenzlehrveranstaltung mit Übungsaufgaben. Es ist für den Lernerfolg entscheidend, die Übungsaufgaben engagiert zu bearbeiten und sich rege mit Kommiliton\*innen auszutauschen. Lehrpersonen können nur Lehren, das Lernen müssen die Student\*innen noch selbst machen.
## Lizenz
Dieses Vorlesungsskript steht unter der [Creative Commons Namensnennung Lizenz 4.0 (CC BY 4.0)](https://creativecommons.org/licenses/by/4.0/). <a href="https://creativecommons.org/licenses/by/4.0/"><img src="https://mirrors.creativecommons.org/presskit/buttons/80x15/png/by.png" height="20"/></a> Jeglicher Code außerdem unter der GPL3.
## Inhaltsverzeichnis
```{tableofcontents}
```
## Quellen
Nichts in diesem Buch ist neu, bis auf die Reihenfolge und sicherlich der ein oder andere Tippfehler.
......@@ -63,9 +72,4 @@ In beiden Büchern ist Stoff für mehr als eine Vorlesung und die Zielgruppen si
Ein lesenswertes ergänzendes Buch mit einigen weiteren Mathematik-Grundlagen (gerade lineare Algebra) ist {cite}`Deisenroth2020`.
```{bibliography}
```
## Lizenz
Dieses Vorlesungsskript steht unter der [Creative Commons Namensnennung Lizenz 4.0 (CC BY 4.0)](https://creativecommons.org/licenses/by/4.0/). <a href="https://creativecommons.org/licenses/by/4.0/"><img src="https://mirrors.creativecommons.org/presskit/buttons/80x15/png/by.png" height="20"/></a> Jeglicher Code außerdem unter der GPL3.
```
\ No newline at end of file
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
%% Cell type:markdown id:3fdf0f52-1f02-4b42-8152-4e632412fd8c tags:
## Die Gausssche Normalverteilung
# Die Gausssche Normalverteilung
%% Cell type:markdown id:3ddc6bdb-9038-41d4-b999-5e80d347b298 tags:
### Approximation der Binomialverteilung
## Approximation der Binomialverteilung
%% Cell type:markdown id:af111971-55f2-4e9e-861c-4874ece317c1 tags:
Betrachten wir eine Folge von Bernoulli-verteilten Zufallsvariablen $X_i$ mit gleichem Parameter $p$ und $S_n := \sum_{i=1}^n X_i$ die Summe über die ersten $n$ davon, so wissen wir bereits, dass $S_n \sim Bin(n,p)$, also dass diese Summe Binomialverteilt ist.
Für die konkreten Werte $n=100,\ p=0.4$ sieht ein Histogramm von $100000$ Samples etwa so aus:
%% Cell type:code id:0ae9357f-96be-4180-8fbb-e5b4269abad5 tags:
``` python
import numpy as np
from scipy.stats import binom, norm
from matplotlib import pyplot as plt
np.random.seed(123123)
binom_samples = binom.rvs(n=100,
p=0.4,
size=100000)
plt.hist(binom_samples, bins=40, density=True)
plt.xlabel("$x$ binomialverteilt")
plt.ylabel("Dichte")
plt.show()
```
%% Output
%% Cell type:markdown id:cf7b3ed2-f44a-4250-9cc4-ee10130f22cb tags:
Da diese Form für große Stichproben stets so aussieht, unabhängig von $p$ (probieren Sie das aus!), könnte man sich vorstellen, dass die Verteilung sich approximieren lässt mit Hilfe einer Funktion, die leichter zu berechnen ist als Binomialkoeffizienten.
Tatsächlich gibt es zur Approximation von Binomialkoeffizienten auch die *Stirling-Formel*
$$
n! \approx \sqrt{2\pi n} {\left(\frac{n}{e}\right)}^n
$$
Damit lässt sich nun (auch wenn es nicht ganz einfach ist) eine Approximation zeigen:
%% Cell type:markdown id:3000f027-bf66-4548-8221-0b5af436c558 tags:
$$
P(S_n = k) \sim
\frac{1}{\sqrt{np(1-p)}} \frac{1}{\sqrt{2\pi}} e^{-\frac{x^2}{2}} \quad \text{ fuer } n \to \infty
$$
%% Cell type:markdown id:7a0e7875-c32a-49d2-aa2c-4ffcde8e40f2 tags:
wobei für $x$ auf der rechten Seite die Folge $x=x_n$ mit
$x_n = x_n(k) = \frac{k-np}{\sqrt{np(1-p)}}$ eingesetzt werden muss. Das Symbol $\sim$ bedeutet: asymptotisch gleich, d.h. der Quotient konvergiert gegen $1$.
Diese Approximation ist insofern hilfreich, als dass wir nun die Funktion $e^{-\frac{x^2}{2}}$ tabellieren können und konkrete Werte für gewisse $n,p$ ablesen können. Das ist wesentlich effizienter, als Binomialkoeffizienten auszurechnen. Die ganze Beobachtung heißt auch **Satz** von deMoivre-Laplace und soll uns zunächst als Motivation dienen, die Funktion $e^{-\frac{x^2}{2}}$ näher zu untersuchen.
%% Cell type:markdown id:340c8b43-2f67-4d19-877e-912d783f5994 tags:
### Ein Integral
## Ein Integral
Um aus der Funktion $e^{-\frac{x^2}{2}}$ eine Wahrscheinlichkeitsdichte zu machen, muss das Integral $1$ ergeben. Wir berechnen, weil es danach sehr nützlich wird, gleich ein etwas allgemeineres Integral:
:::{admonition} Lemma
Sei $v \in \mathbb{R}$ und $v > 0$. Dann gilt
$$
\int_{-\infty}^\infty e^{-\frac{x^2}{2v}} dx = \sqrt{2\pi v}.
$$
:::
:::{admonition} Beweis
Da auf der rechten Seite eine Quadratwurzel steht, bietet es sich an, beide Seiten der Gleichung zu quadrieren. Wir formen die linke Seite dann weiter um, bis wir ein Integral über $\mathbb{R}^2$ in Polarkoordinaten transformieren können und dann leicht Stammfunktionen bestimmen können:
$$
& {\left( \int_{-\infty}^\infty e^{-\frac{x^2}{2v}} dx \right)}^2 \\
=& {\left( \int_{-\infty}^\infty e^{-\frac{x^2}{2v}} dx \right)}{\left( \int_{-\infty}^\infty e^{-\frac{y^2}{2v}} dy \right)} \\
=& \int_{-\infty}^\infty e^{-\frac{x^2}{2v}} {\left( \int_{-\infty}^\infty e^{-\frac{y^2}{2v}} dy \right)} dx \\
=& \int_{-\infty}^\infty {\left( \int_{-\infty}^\infty e^{-\frac{x^2}{2v}} e^{-\frac{y^2}{2v}} dy \right)} dx \\
=& \int_{-\infty}^\infty {\left( \int_{-\infty}^\infty e^{-\frac{x^2+y^2}{2v}} dy \right)} dx \\
=& \int_{\mathbb{R}^2} e^{-\frac{x^2+y^2}{2v}} d(x,y) \\
=& \int_{0}^\infty \int_{0}^{2\pi} r e^{-\frac{r^2}{2v}} d\phi dr \\
=& \int_{0}^\infty {\left[ r e^{-\frac{r^2}{2v}} \phi \right]}_{\phi=0}^{\phi=2\pi} dr \\
=& \int_{0}^\infty r e^{-\frac{r^2}{2v}} (-2\pi) dr \\
=& -2\pi {\left[ -v e^{-\frac{r^2}{2v}} dr \right]}_{r=0}^{r=\infty} \\
=& 2\pi v
$$
:::
%% Cell type:markdown id:05a03b80-9d5c-4ee8-94d4-38d12fc7d48f tags:
Da Integrale in der Statistik häufiger vorkommen, ist es nicht ganz verkehrt, sich bei dieser Rechnung klar zu machen, was genau warum in jedem Schritt passiert.
%% Cell type:markdown id:9fc75e9c-a648-476a-a297-97aa9e313f71 tags:
### Die eindimensionale Normalverteilung
## Die eindimensionale Normalverteilung
:::{admonition} Definition
Seien $\mu,\sigma \in \mathbb{R}$ mit $\sigma > 0$. Dann heißt die Verteilung mit Dichtefunktion
$$
\phi(x) = \phi(x,\mu,\sigma) = \frac{1}{\sigma\sqrt{2\pi}} e^{-\frac{(x-\mu)^2}{2\sigma^2}}
$$
*Normalverteilung* und wir schreiben für eine reelle Zufallsvariable $X$ mit dieser Verteilung auch $X \sim \mathcal{N}(\mu,\sigma^2)$.
:::
%% Cell type:code id:3465b513-ac20-44a5-8c02-906058b2e6af tags:
``` python
x = np.linspace(20,60,100)
plt.hist(binom_samples, bins=40, density=True)
plt.plot(x, norm(loc=40.5, scale=5).pdf(x), color="red")
plt.ylabel('Dichte')
plt.title('Normalverteilungs-Dichte (rot) & Binomial-Histogramm (blau)')
plt.show()
```
%% Output
%% Cell type:markdown id:1b266dac-1d5a-4c47-8b0a-2b08ea2fad78 tags:
:::{admonition} Proposition
Wenn $X \sim \mathcal{N}(\mu,\sigma^2)$, so ist $\mathbb{E}(X) = \mu$ und $\mathbb{V}(X) = \sigma^2$.
:::
:::{admonition} Beweis
Wir setzen die Dichte für $X$ in die Formel für $\mathbb{E}(X)$ ein und transformieren das Integral über $x$ in ein Integral über $x + \mu$:
$$
\mathbb{E}(X) &= \int_{-\infty}^{\infty} x\phi(x) dx \\
&= \int_{-\infty}^{\infty} x \frac{1}{\sigma\sqrt{2\pi}} e^{-\frac{(x-\mu)^2}{2\sigma^2}} dx \\
&= \frac{1}{\sigma\sqrt{2\pi}} \int_{-\infty}^{\infty} x e^{-\frac{(x-\mu)^2}{2\sigma^2}} dx \\
&= \frac{1}{\sigma\sqrt{2\pi}} \int_{-\infty}^{\infty} (x+\mu) e^{-\frac{x^2}{2\sigma^2}} dx \\
&= \frac{1}{\sigma\sqrt{2\pi}} \left( \left( \int_{-\infty}^{\infty} x e^{-\frac{x^2}{2\sigma^2}} dx \right) + \mu \left( \int_{-\infty}^{\infty} e^{-\frac{x^2}{2\sigma^2}} dx \right) \right) \\
&= \frac{1}{\sigma\sqrt{2\pi}} \left( \left( \int_{-\infty}^{\infty} x e^{-\frac{x^2}{2\sigma^2}} dx \right) + \mu \sigma\sqrt{2\pi} \right) \\
&= \mu + \frac{1}{\sigma\sqrt{2\pi}} \left( \int_{-\infty}^{\infty} x e^{-\frac{x^2}{2\sigma^2}} dx \right) = \mu\\
$$
Der Ausdruck nach dem $\mu +$ ist einfach $0$, denn die Funktion ist punktsymmetrisch um $0$ (der Faktor $x$ ist offensichtlich eine ungerade Funktion, der andere Faktor hängt nur von $|x|$ ab).
Genau so kann man bei der Varianz verfahren, indem man diesen Ausdruck vereinfacht:
$$
\mathbb{V}(X) &= \int_{-\infty}^{\infty} x^2\phi(x) dx - {\left( \mathbb{E}(X) \right)}^2 \\
&= \int_{-\infty}^{\infty} x^2\frac{1}{\sigma\sqrt{2\pi}} e^{-\frac{(x-\mu)^2}{2\sigma^2}} dx - \mu^2
$$
:::
%% Cell type:markdown id:e67caa4e-c0d6-4f44-a9e8-620dc7b20bf3 tags:
:::{admonition} Definition
Man nennt eine Zufallsvariable mit $X \sim \mathcal{N}(0,1)$ auch *standardnormalverteilt*
:::
:::{admonition} Proposition
Wenn $X \sim \mathcal{N}(\mu,\sigma^2)$, so ist $\frac{X - \mu}{\sigma} \sim \mathcal{N}(0,1)$.
:::
:::{admonition} Beweis
**Idee:**
Es ist sofort klar, dass $\mathbb{E}(X-\mu) = 0$ und dass $\mathbb{V}\left(\frac{X-\mu}{\sigma}\right) = 1$.
Weniger klar ist, dass die neue Zufallsvariable tatsächlich normalverteilt ist. Das lässt sich z.B. mit der Momenterzeugendenfunktion beweisen.
:::
Alternativ nutzen wir, dass die Summe von unabhängigen Zufallsvariablen mit Dichten $f,g$ selbst wieder eine Dichte hat, nämlich die *Faltung* $f \ast g$. Anstatt das nun rigoros einzuführen und zu beweisen, benutzen wir es ein weiteres Mal, damit lässt sich nämlich zeigen:
:::{admonition} Proposition
Wenn $X \sim \mathcal{N}(\mu_1,\sigma_1^2)$ und $Y \sim \mathcal{N}(\mu_2,\sigma_2^2)$,
so ist $X+Y \sim \mathcal{N}(\mu_1 + \mu_2,\sigma_1^2 + \sigma_2^2)$.
:::
:::{admonition} Satz
Unter allen Verteilungen reeller Zufallsvariablen $X$ mit festem Erwartungswert $\mu = \mathbb{E}(X)$ und Varianz $\sigma^2 = \mathbb{V}(X)$ ist die Normalverteilung diejenige mit der maximalen Entropie.
:::
Um diesen Satz überhaupt präzise formulieren zu können, benötigen wir einen Entropiebegriff für stetige Verteilungen. Anstatt das jetzt zu tun, wollen wir uns später damit beschäftigen, wenn wir auch relative Entropie, die stetige Version davon und Likelihood diskutieren.
Wichtig ist aber die Take-Home-Message des Satzes: Wenn über eine stetige Verteilung reeller Zahlen außer Erwartungswert und Varianz nichts bekannt ist, dann ist die entprechende Normalverteilung die vernünftigste Annahme. In diesem Sinne ist die Normalverteilung ein guter stetiger Ersatz für die diskrete Gleichverteilung, aber nun auf ganz $\mathbb{R}$ (die Normalverteilung hat Träger $\mathbb{R}$).
%% Cell type:markdown id:29d32c3a-91c9-4534-adfa-d0fd87a7680d tags:
## Der zentrale Grenzwertsatz
# Der zentrale Grenzwertsatz
:::{admonition} Satz
Wenn $X_i$ eine Folge von identisch verteilten, voneinander unabhängigen (iid = independent identically distributed) Zufallsvariablen mit Erwartungswert $\mathbb{E}(X_i)=0$ und Varianz $\mathbb{V}(X_i)=\sigma^2$ ist,
und wir die skalierte Summe $S_N := \dfrac{\sqrt{N}}{N} \sum_{i=1}^N X_i$ betrachten, dann gilt die Konvergenz in Verteilung:
$$
S_N \xrightarrow{N \to \infty} \mathcal{N}(0,1)
$$
:::
Konvergenz in Verteilung heißt, dass die Verteilungsfunktion von $S_N$ gegen die Verteilungsfunktion einer Standardnormalverteilung konvergiert.
Von diesem Satz gibt es auch Abschwächungen, die gewisse Abhängigkeiten zwischen den $X_i$ erlauben.
:::{admonition} Bemerkung
Wichtig ist der Satz für uns, weil er erlaubt eine Summe unabhängiger Zufallsvariablen mit einer Normalverteilung zu approximieren. Das tritt in der Praxis häufig auf, wenn man Messungen an physikalischen oder technosozialen Systemen vornimmt, die in der Regel von einer langen Liste weitgehend unabhängiger Störeinflüsse beeinträchtigt werden. Diese Summe an Fehlerquellen ist (für eine hinreichend große Zahl an unabhängigen Fehlerquellen) etwa normalverteilt.
:::
Um zwei konkrete Beispiele zu nennen: der Fehler bei der Ortsbestimmung mit GNSS-Systemen wie GPS ist normalverteilt (auch wenn die atmosphärischen Störungen, die den Wert ungenauer machen, nicht normalverteilt sind). Bei der industriellen Fertigung von Bauteilen gibt es ebenfalls im gesamten Produktionsprozess Fehlerquellen, die am Ende zu einer Normalverteilung aufsummieren - deren Varianz man hinreichend klein halten muss, damit das Bauteil seine Aufgabe erfüllen kann. So darf ein Legostein nicht zu stark von einem baugleichen Legostein abweichen, sonst hält das Bauwerk hinterher nicht richtig.
%% Cell type:markdown id:961bb23c-049c-4367-866c-a840b6fab2e8 tags:
Man kann außerdem die Geschwindigkeit der Konvergenz abschätzen, und damit in Erfahrung bringen, wie gut die Approximation durch eine Normalverteilung ist:
:::{admonition} Satz
Es existiert eine Konstante $C > 0,4409$ mit der folgenden Eigenschaft:
Wenn $X_i$ eine Folge von iid Zufallsvariablen mit Erwartungswert $0$ und Varianz $\sigma^2$ ist, und außerdem die dritten absoluten Momente $\mathbb{E}|X_i^3| = \rho < \infty$ existieren,
wir $F_N$ für die kumulative Verteilungsfunktion von $\frac{\sqrt{N}}{N\sigma} \sum_{i=1}^N X_i$ schreiben und $\Phi$ für die kumulative Verteilungsfunktion der Standardnormalverteilung $\mathcal{N}(0,1)$, so gilt für alle $x$ und alle $N$:
$$
\left| F_n(x) - \Phi(x) \right| \ \leq\ \dfrac{C\rho}{\sigma^3 \sqrt{n}}.
$$
:::
Für konkret bekannte $\sigma,\rho$ können wir also stets das $n$ bestimmen, um die linke Seite beliebig klein abzuschätzen. Mit anderen Worten: es lässt sich zu jeder gewünschten Genauigkeit berechnen, wie viele der iid Zufallsvariablen man (skaliert) aufaddieren muss, um es mit einer Standardnormalverteilung zu approximieren.
Klar: Wenn der Erwartungswert nicht $0$ ist, lässt sich eine Variante als Korollar beweisen (wie auch beim zentralen Grenzwertsatz), sodass die Konvergenz gegen $\mathcal{N}(\mu,1)$ geht. Wenn man anders reskaliert, auch gegen $\mathcal{N}(\mu,\sigma^2)$. In der Praxis sieht es eher so aus, dass man alle unbekannten Fehlerterme mit einer Normalverteilung modelliert, deren Erwartungswert und Varianz man empirisch schätzt.
......
%% Cell type:markdown id: tags:
Pandas
-------------
# Pandas
%% Cell type:markdown id: tags:
<!---
https://pbpython.com/categorical-encoding.html
--->
%% Cell type:markdown id: tags:
Aus der [Pandas Dokumentation, Abschnitt "Comparison with SQL"](https://pandas.pydata.org/docs/getting_started/comparison/comparison_with_sql.html).
%% Cell type:code id: tags:
``` python
import numpy as np
import pandas as pd
url = (
"https://raw.github.com/pandas-dev"
"/pandas/main/pandas/tests/io/data/csv/tips.csv"
)
tips = pd.read_csv(url)
print(tips)
```
%% Output
total_bill tip sex smoker day time size
0 16.99 1.01 Female No Sun Dinner 2
1 10.34 1.66 Male No Sun Dinner 3
2 21.01 3.50 Male No Sun Dinner 3
3 23.68 3.31 Male No Sun Dinner 2
4 24.59 3.61 Female No Sun Dinner 4
.. ... ... ... ... ... ... ...
239 29.03 5.92 Male No Sat Dinner 3
240 27.18 2.00 Female Yes Sat Dinner 2
241 22.67 2.00 Male Yes Sat Dinner 2
242 17.82 1.75 Male No Sat Dinner 2
243 18.78 3.00 Female No Thur Dinner 2
[244 rows x 7 columns]
%% Cell type:markdown id: tags:
Operationen auf Pandas DataFrames erzeugen Kopien, während der ursprüngliche DataFrame unverändert bleibt.
%% Cell type:code id: tags:
``` python
tips.sort_values("total_bill")
print(tips)
print("\nDas ist ja gar nicht sortiert! Das nächste aber:\n")
sorted_tips = tips.sort_values("total_bill")
print(sorted_tips)
```
%% Output
total_bill tip sex smoker day time size
0 16.99 1.01 Female No Sun Dinner 2
1 10.34 1.66 Male No Sun Dinner 3
2 21.01 3.50 Male No Sun Dinner 3
3 23.68 3.31 Male No Sun Dinner 2
4 24.59 3.61 Female No Sun Dinner 4
.. ... ... ... ... ... ... ...
239 29.03 5.92 Male No Sat Dinner 3
240 27.18 2.00 Female Yes Sat Dinner 2
241 22.67 2.00 Male Yes Sat Dinner 2
242 17.82 1.75 Male No Sat Dinner 2
243 18.78 3.00 Female No Thur Dinner 2
[244 rows x 7 columns]
Das ist ja gar nicht sortiert! Das nächste aber:
total_bill tip sex smoker day time size
67 3.07 1.00 Female Yes Sat Dinner 1
92 5.75 1.00 Female Yes Fri Dinner 2
111 7.25 1.00 Female No Sat Dinner 1
172 7.25 5.15 Male Yes Sun Dinner 2
149 7.51 2.00 Male No Thur Lunch 2
.. ... ... ... ... ... ... ...
182 45.35 3.50 Male Yes Sun Dinner 3
156 48.17 5.00 Male No Sun Dinner 6
59 48.27 6.73 Male No Sat Dinner 4
212 48.33 9.00 Male No Sat Dinner 4
170 50.81 10.00 Male Yes Sat Dinner 3
[244 rows x 7 columns]
%% Cell type:markdown id: tags:
Spalten auswählen ist `SELECT`:
%% Cell type:code id: tags:
``` python
# SELECT total_bill, tip, smoker, time FROM tips;
tips[["total_bill", "tip", "smoker", "time"]]
```
%% Output
total_bill tip smoker time
0 16.99 1.01 No Dinner
1 10.34 1.66 No Dinner
2 21.01 3.50 No Dinner
3 23.68 3.31 No Dinner
4 24.59 3.61 No Dinner
.. ... ... ... ...
239 29.03 5.92 No Dinner
240 27.18 2.00 Yes Dinner
241 22.67 2.00 Yes Dinner
242 17.82 1.75 No Dinner
243 18.78 3.00 No Dinner
[244 rows x 4 columns]
%% Cell type:markdown id: tags:
Man kann neue Spalten hinzufügen, die sich aus alten Spalten berechnen:
%% Cell type:code id: tags:
``` python
# SELECT *, tip/total_bill as tip_rate FROM tips;
tips.assign(tip_rate=tips["tip"] / tips["total_bill"])
```
%% Output
total_bill tip sex smoker day time size tip_rate
0 16.99 1.01 Female No Sun Dinner 2 0.059447
1 10.34 1.66 Male No Sun Dinner 3 0.160542
2 21.01 3.50 Male No Sun Dinner 3 0.166587
3 23.68 3.31 Male No Sun Dinner 2 0.139780
4 24.59 3.61 Female No Sun Dinner 4 0.146808
.. ... ... ... ... ... ... ... ...
239 29.03 5.92 Male No Sat Dinner 3 0.203927
240 27.18 2.00 Female Yes Sat Dinner 2 0.073584
241 22.67 2.00 Male Yes Sat Dinner 2 0.088222
242 17.82 1.75 Male No Sat Dinner 2 0.098204
243 18.78 3.00 Female No Thur Dinner 2 0.159744
[244 rows x 8 columns]
%% Cell type:markdown id: tags:
Daten filtern (nach Bedingungen Zeilen auswählen) mit `WHERE`
%% Cell type:code id: tags:
``` python
# SELECT * FROM tips WHERE time = 'Dinner';
is_dinner = tips["time"] == "Dinner" # Bitmaske
tips[is_dinner]
```
%% Output
total_bill tip sex smoker day time size
0 16.99 1.01 Female No Sun Dinner 2
1 10.34 1.66 Male No Sun Dinner 3
2 21.01 3.50 Male No Sun Dinner 3
3 23.68 3.31 Male No Sun Dinner 2
4 24.59 3.61 Female No Sun Dinner 4
.. ... ... ... ... ... ... ...
239 29.03 5.92 Male No Sat Dinner 3
240 27.18 2.00 Female Yes Sat Dinner 2
241 22.67 2.00 Male Yes Sat Dinner 2
242 17.82 1.75 Male No Sat Dinner 2
243 18.78 3.00 Female No Thur Dinner 2
[176 rows x 7 columns]
%% Cell type:markdown id: tags:
Mehrere Bedingungen logisch verknüpfen mit `OR |` oder `AND &`:
%% Cell type:code id: tags:
``` python
# SELECT * FROM tips WHERE time = 'Dinner' AND tip > 6.00;
tips[(tips["time"] == "Dinner") & (tips["tip"] > 6.00)]
```
%% Output
total_bill tip sex smoker day time size
23 39.42 7.58 Male No Sat Dinner 4
59 48.27 6.73 Male No Sat Dinner 4
170 50.81 10.00 Male Yes Sat Dinner 3
183 23.17 6.50 Male Yes Sun Dinner 4
212 48.33 9.00 Male No Sat Dinner 4
214 28.17 6.50 Female Yes Sat Dinner 3
%% Cell type:code id: tags:
``` python
# SELECT * FROM tips WHERE size >= 6 OR total_bill > 45;
tips[(tips["size"] >= 6) | (tips["total_bill"] > 45)]
```
%% Output
total_bill tip sex smoker day time size
59 48.27 6.73 Male No Sat Dinner 4
125 29.80 4.20 Female No Thur Lunch 6
141 34.30 6.70 Male No Thur Lunch 6
143 27.05 5.00 Female No Thur Lunch 6
156 48.17 5.00 Male No Sun Dinner 6
170 50.81 10.00 Male Yes Sat Dinner 3
182 45.35 3.50 Male Yes Sun Dinner 3
212 48.33 9.00 Male No Sat Dinner 4
%% Cell type:markdown id: tags:
Daten in Gruppen aufspalten, aggregierte Statistiken ausrechnen, Gruppen zusammenführen - das ist in SQL ein `GROUP BY`, in Pandas `groupby`:
%% Cell type:code id: tags:
``` python
# SELECT sex, count(*) FROM tips GROUP BY sex;
tips.groupby("sex").size()
# tips.groupby("sex").count() wäre falsch, das zählt nicht-NA-Einträge!
```
%% Output
sex
Female 87
Male 157
dtype: int64
%% Cell type:code id: tags:
``` python
# SELECT day, AVG(tip), COUNT(*) FROM tips GROUP BY day;
tips.groupby("day").agg({"tip": np.mean, "day": np.size})
```
%% Output
tip day
day
Fri 2.734737 19
Sat 2.993103 87
Sun 3.255132 76
Thur 2.771452 62
%% Cell type:code id: tags:
``` python
# SELECT smoker, day, COUNT(*), AVG(tip) FROM tips GROUP BY smoker, day;
tips.groupby(["smoker", "day"]).agg({"tip": [np.size, np.mean]})
```
%% Output
tip
size mean
tip
size mean
smoker day
No Fri 4.0 2.812500
Sat 45.0 3.102889
Sun 57.0 3.167895
Thur 45.0 2.673778
Yes Fri 15.0 2.714000
Sat 42.0 2.875476
Sun 19.0 3.516842
Thur 17.0 3.030000
No Fri 4 2.812500
Sat 45 3.102889
Sun 57 3.167895
Thur 45 2.673778
Yes Fri 15 2.714000
Sat 42 2.875476
Sun 19 3.516842
Thur 17 3.030000
%% Cell type:markdown id: tags:
Tabellen verknüpfen mit `JOIN` bzw. `merge`:
%% Cell type:code id: tags:
``` python
df1 = pd.DataFrame({"key": ["A", "B", "C", "D"], "value": np.random.randn(4)})
df2 = pd.DataFrame({"key": ["B", "D", "D", "E"], "value": np.random.randn(4)})
print(df1, "\n", df2)
```
%% Output
key value
0 A 0.107912
1 B 1.628480
2 C -0.043069
3 D 0.106587
0 A -1.532164
1 B -1.499675
2 C -0.144145
3 D -0.129550
key value
0 B 0.143511
1 D -2.610961
2 D 1.025912
3 E -0.944416
0 B 0.205613
1 D 1.090276
2 D -0.627631
3 E -0.792265
%% Cell type:code id: tags:
``` python
# SELECT * FROM df1 INNER JOIN df2 ON df1.key = df2.key;
pd.merge(df1, df2, on="key") # inner join ist der default
```
%% Output
key value_x value_y
0 B 1.628480 0.143511
1 D 0.106587 -2.610961
2 D 0.106587 1.025912
0 B -1.499675 0.205613
1 D -0.129550 1.090276
2 D -0.129550 -0.627631
%% Cell type:code id: tags:
``` python
# SELECT * FROM df1 LEFT OUTER JOIN df2 ON df1.key = df2.key;
pd.merge(df1, df2, on="key", how="left")
```
%% Output
key value_x value_y
0 A 0.107912 NaN
1 B 1.628480 0.143511
2 C -0.043069 NaN
3 D 0.106587 -2.610961
4 D 0.106587 1.025912
0 A -1.532164 NaN