---
title: "Tutorial 5"
author: "Lars Abt"
format: pdf
editor: visual
---

## Aufgabe 1: Nadaraya-Watson

Wir laden unsere Pakete mit Hilfe von 'pacman'.

```{r}
pacman::p_load(data.table, ggplot2)
```

Nun laden wir unsere Daten herunter, über den angegebenen Link:

```{r}
miete <- fread("https://tinyurl.com/yn9ttfcu", header = TRUE)
miete <- miete[miete$wfl <= 200, ]
```

Letztlich verschaffen wir uns einen kleinen Überblick über die Daten.

```{r}
# Schauen wir uns die Struktur der Daten an
str(miete)

# Betrachten wir die ersten 6 Zeilen
head(miete)
```


## Aufgabe 1a
Nun erstellen wir ein Streudiagramm der Wohnfläche (wfl) gegen den Nettomietpreis pro Quadratmeter (nmqm).

```{r}
# Ein Streudiagramm mit Hilfe von R-Base:
plot(miete$wfl, miete$nmqm, pch = 16, bty = "n",
xlab = "Wohnfläche", ylab = "Nettomiete pro qm")

# Die Werte von "wfl" aus dem Intervall [140,160] identifizieren, da uns die Stelle wfl = 150 interessiert:
ind <- which(140 <= miete$wfl & miete$wfl <= 160)

# Werte der Zielvariable "nm" auf dem Intervall:
head(miete$nmqm[ind])

# Dort den lokalen Mittelwert berechnen:
m150 <- mean(miete$nmqm[ind])
m150

# Und einzeichnen:
points(150, m150, col = "orange", pch = 16)
```

```{r}
# Jetzt noch einmal mit ggplot2:
ggplot(miete, aes(x = wfl, y = nmqm)) +
  geom_point() + 
  geom_point(aes(x = 150, y = m150), color = "orange", size = 3)
  labs(x = "Wohnfläche", y = "Nettomiete pro qm") +
  theme_minimal()
```

Kurze Erklärung zu unserem Vorgehen: Wir betrachten lediglich die Werte zwischen 140 und 160, da der Rechteckkern lediglich Werte in Betracht zieht, welche für den Ausdruck (x-xi)/b kleiner als 0.5 sind. Dies ist der Fall, wenn x in [x-b/2, x+b/2] liegt. Für den Punkt xi = 150 und b = 20 ergibt sich also das Intervall [140,160]. Somit schauen wir zuerst, welche Wohnungen eine Wohnfläche in diesem Bereich aufweisen, und bilden anschließend den Mittelwert des Nettopreises pro Quadratmeter über genau diese Werte.

## Aufgabe 1b

Wir übernehmen die Funktion von unserem Übungsblatt:

```{r}
K <- function(z){ifelse(abs(z)>0.5, 0, 1)}
```

Nun probieren wir diese Funktion für einige Werte aus:

```{r}
K(10)
K(2)
K(0.1)
K(0.5)
```

Nun berechnen wir den Nadaraya-Watson-Schätzer für die Stelle wfl = 150:

```{r}
b <- 20 # Bandweite definieren

sum(K((150 - miete$wfl)/b) * miete$nmqm) /
sum(K((150 - miete$wfl)/b))
```

Wir sehen, dass der Nadaraya-Watson-Schätzer für die Stelle wfl = 150 den Wert 10.22276 berechnet.


## Aufgabe 1c

Nun betrachten wir den Gaußkern (statt des Rechteckskerns), und betrachten unseren Plot, ergänzt durch unsere Schätzungen.

```{r}
b <- 20 # Bandweite definieren

m150norm <- sum(dnorm((150 - miete$wfl) / b) * miete$nmqm) /
sum(dnorm((150 - miete$wfl) / b))
m150norm
```

Mit dem Gaußkern ergibt sich ein Wert von 10,36849, welcher nahe an unserem anderen berechneten Wert befindet. Nun möchten wir unseren Schätzer auch noch einzeichnen in unser Streudiagramm:

```{r}
# Mit R-Base:
plot(miete$wfl, miete$nmqm, pch = 16, bty = "n",
     xlab = "Wohnfläche", ylab = "Nettomiete pro qm")

points(150, m150norm, col = "orange", pch = 16)

# Nadaraya Watson Schätzung
NWS <- ksmooth(miete$wfl, miete$nmqm,
               kernel = "normal", bandwidth = 55)
# ?ksmooth

lines(NWS$x,NWS$y,col="lightblue",lwd=2)
```

Und nun noch einmal mit ggplot2:

```{r}
# Vorbereitung:
NWS <- ksmooth(miete$wfl, miete$nmqm, kernel = "normal", bandwidth = 55)
NWS_data <- data.table(x = NWS$x, y = NWS$y)

# Plot:
ggplot(miete, aes(x = wfl, y = nmqm)) +
  geom_point() +
  geom_point(aes(x = 150, y = m150norm), color = "orange", size = 3) +
  geom_line(data = NWS_data, aes(x = x, y = y), 
            color = "lightblue", linewidth = 1) + 
  labs(x = "Wohnfläche", y = "Nettomiete pro qm") +
  theme_minimal()
```


## Aufgabe 2: Bandweitenwahl & Kreuzvalidierung
## Aufgabe 2a

Nun möchten wir die Bandweite b variieren und uns die Auswirkungen auf den Schätzer anschauen. Wir verwenden dazu die Funktion ksmooth().

```{r}
# So können wir mehrere Plots gemeinsam betrachten:
par(mfrow = c(2, 2))

# Klassisch mit RBase:
plot(miete$wfl, miete$nmqm, pch = 16, bty = "n", main = "b=1")
NWS <- ksmooth(miete$wfl, miete$nmqm, kernel = "normal", bandwidth = 1)
lines(NWS$x, NWS$y, col = "blue", lwd = 3)

plot(miete$wfl, miete$nmqm, pch = 16, bty = "n", main = "b=10")
NWS <- ksmooth(miete$wfl, miete$nmqm, kernel = "normal", bandwidth = 10)
lines(NWS$x, NWS$y, col = "green", lwd = 3)

plot(miete$wfl, miete$nmqm, pch = 16, bty = "n", main = "b=20")
NWS <- ksmooth(miete$wfl, miete$nmqm, kernel = "normal", bandwidth = 20)
lines(NWS$x, NWS$y, col = "yellow", lwd = 3)

plot(miete$wfl, miete$nmqm, pch = 16, bty = "n", main = "b=50")
NWS<-ksmooth(miete$wfl, miete$nmqm, kernel = "normal", bandwidth = 50)
lines(NWS$x, NWS$y, col = "red", lwd = 3)
```

Wir sehen, dass eine Bandweite im Bereich von 10 bis 20 eine gute Wahl scheint.

Jetzt schauen wir auch auf die Darstellung mit Hilfe von ggplot2:

```{r}
# Wir bereiten unsere Daten für's plotten vor:
NWS_1 <- ksmooth(miete$wfl, miete$nmqm, kernel = "normal", bandwidth = 1)
NWS_bw_1 <- data.table(x = NWS_1$x, y = NWS_1$y)

NWS_10 <- ksmooth(miete$wfl, miete$nmqm, kernel = "normal", bandwidth = 10)
NWS_bw_10 <- data.table(x = NWS_10$x, y = NWS_10$y)

NWS_20 <- ksmooth(miete$wfl, miete$nmqm, kernel = "normal", bandwidth = 20)
NWS_bw_20 <- data.table(x = NWS_20$x, y = NWS_20$y)

NWS_50 <- ksmooth(miete$wfl, miete$nmqm, kernel = "normal", bandwidth = 50)
NWS_bw_50 <- data.table(x = NWS_50$x, y = NWS_50$y)

# Und plotten anschließend unsere verschiedenen Bandweiten:
ggplot(miete, aes(x = wfl, y = nmqm)) +
  geom_point() +
  geom_line(data = NWS_bw_1, aes(x = x, y = y), color = "blue", linewidth = 1) +
  geom_line(data = NWS_bw_10, aes(x = x, y = y), color = "green", linewidth = 1) +
  geom_line(data = NWS_bw_20, aes(x = x, y = y), color = "yellow", linewidth = 1) +
  geom_line(data = NWS_bw_50, aes(x = x, y = y), color = "red", linewidth = 1) +
  labs(x = "Wohnfläche", y = "Nettomiete pro qm", main = "Bandweitenvergleich") +
  theme_minimal()

# Oder als einzelne Plots:
ggplot(miete, aes(x = wfl, y = nmqm)) +
  geom_point() +
  geom_line(data = NWS_bw_1, aes(x = x, y = y), color = "blue", linewidth = 1) +
  labs(x = "Wohnfläche", y = "Nettomiete pro qm", main = "Bandweite 1") +
  theme_minimal()

ggplot(miete, aes(x = wfl, y = nmqm)) +
  geom_point() +
  geom_line(data = NWS_bw_10, aes(x = x, y = y), color = "green", linewidth = 1) +
  labs(x = "Wohnfläche", y = "Nettomiete pro qm", main = "Bandweite 10") +
  theme_minimal()

ggplot(miete, aes(x = wfl, y = nmqm)) +
  geom_point() +
  geom_line(data = NWS_bw_20, aes(x = x, y = y), color = "yellow", linewidth = 1) +
  labs(x = "Wohnfläche", y = "Nettomiete pro qm", main = "Bandweite 20") +
  theme_minimal()

ggplot(miete, aes(x = wfl, y = nmqm)) +
  geom_point() +
  geom_line(data = NWS_bw_50, aes(x = x, y = y), color = "red", linewidth = 1) +
  labs(x = "Wohnfläche", y = "Nettomiete pro qm", main = "Bandweite 50") +
  theme_minimal()

```


## Aufgabe 2b

Nun möchten wir uns mit dem Thema der Kreuzvalidierung beschäftigen. Wir beginnen dafür mit dem Kreuzvalidierungskriterium für i = 1.

```{r}
# Berechnen des Kreuzvalidierungskriteriums für i = 1
mcv <- ksmooth(miete$wfl[-1], miete$nmqm[-1],
              kernel = "normal",
              bandwidth = 10,
              x.points = miete$wfl[1])$y

# Berechnen der quadrierten Abweichung
(miete$nmqm[1] - mcv)^2
```

Nun nutzen wir eine For-Schleife, um CV(10) zu berechnen:

```{r}
# Initialisieren unserer Variablen
n <- nrow(miete)
CV <- rep(NA, n)

# For-Schleife zur Berechnung
for(i in 1:n){
  mcv <- ksmooth(miete$wfl[-i], miete$nmqm[-i],
                 kernel = "normal",
                 bandwidth = 10,
                 x.points = miete$wfl[i])$y
  CV[i] <- (miete$nmqm[i] - mcv)^2
}

# Werte der Kreuzvalidierung
sum(CV)
```

Nun wollen wir noch die Bandweite variieren, zwischen 10 und 20, in Schritten von 0,1.

```{r}
# Initialisieren unserer Variablen
b <- seq(10, 20, by = 0.1)
nb <- length(b)
n <- nrow(miete)
CVb <- rep(NA,nb)

# For-Schleife zur Berechnung (etwas zeitintensiv)
for(k in 1:nb){     # äußere For-Schleife für verschiedene Werte von b
  CV <- rep(NA, n)
  for (i in 1:n){   # innere For-Schleife für die Kreuzvalidierung
    mcv <- ksmooth(miete$wfl[-i], miete$nmqm[-i],
                   kernel = "normal",
                   bandwidth = b[k],
                   x.points = miete$wfl[i])$y
    CV[i] <- (miete$nmqm[i] - mcv)^2
  }
  CVb[k] <- sum(CV)
}

# Nun plotten wir unsere Ergebnisse:
par(mfrow = c(1, 1)) # um das Fenster anzupassen
plot(b, CVb, type = "l")

# Oder mit ggplot2:
# Daten in ein data.table bringen
cv_data <- data.table(b = b, CVb = CVb)

# Linienplot mit ggplot2
ggplot(cv_data, aes(x = b, y = CVb)) +
  geom_line() +
  theme_minimal() +
  labs(x = "b", y = "CVb", title = "Kreuzvalidierung für unsere Bandweitenwahl")
```

Jetzt möchten wir noch einmal exakt nachschauen, an welcher Stelle das Kreuzvalidierungskriterium den niedrigsten Wert aufweist, und welcher das ist.

```{r}
# An welcher Stelle hat der Vektor CVb seinen kleinsten Wert (Index)?
which.min(CVb)

# Was ist dieser kleinste Wert (welches b hat den besten CV-Wert)?
b[which.min(CVb)]
```

Wir sehen, das der niedrigste CV Wert bei 66 liegt, und dieser zur Bandweite 16.5 gehört. Dies passt zu unserem Plot, und unserer Vermutung in Aufgabe 1.


## Aufgabe 2c

Zum Abschluss werfen wir noch einen kurzen Blick auf den Bias-Varianz-Trade-off. Das Kreuzvalidierungskriterium gibt uns diesbezüglich klare Anhaltspunkte.
Der Wert von CV ist hoch für (zu) kleines b, da wir dann eine zu große Varianz haben. Analog dazu ist der Wert von CV auch hoch für (zu) große b, da wir dann einen hohen Bias haben. Ein mittlerer Wert von b scheint also optimal zu sein, und stellt einen Kompromiss zwischen Varianz (Überanpassung) und Bias (Unteranpassung) dar, welchen auch das Kreuzvalidierungskriterium bevorzugt.

Wenn wir das mit unserem Plot der CV-Werte vergleichen möchten, sehen wir das Tal (den Tiefpunkt) des Graphen als den Kompromiss, welchen das Kreuzvalidierungskriterium als optimalen Wert für b vorschlägt. Dies ist der Punkt, an dem der Bias und die Varianz in einem optimalen Verhältnis zueinander stehen. Links davon, bei kleinerer Bandweite, sehen wir die Gefahr von Overfitting, also einer zu hohen Varianz. Die Auswirkungen dieser geringen Bandweite (eine sehr sprunghafte Linie) haben wir in einer vorangehenden Aufgabe bereits beleuchtet. Rechts vom Tiefpunkt sehen wir die Gefahr von Underfitting, also einer zu hohen Bias. Auch hier haben wir bereits in einer vorangehenden Aufgabe die Auswirkungen (eine zu flache Linie) beleuchtet.








