--- title: "Eigenes Histogramm" output: html_document: default pdf_document: default --- # Eigenes Histogramm Es soll ein eigenes Histogramm erzeugt werden. Der Dateiname für das Skript ist `myhistogram.R`. ## Funktion `myhistogram` Programmieren Sie in R die Funktion `myhistogram`, die als Parameter `x` einen Vektor aus Zahlen erhält. Die Zahlen werden in `n` Intervalle einsortiert, und es wird gezählt, wie oft eine Zahl in einem Intervall vorkommt. Der Rückgabewert ist eine Liste mit den Einträgen `borders`, die die $n+1$ Intervallgrenzen enthalten und `counts`, der die Anzahlen enthält. * Die $n$ Intervalle sollen gleich groß sein ($\Delta b$), d.h. für die Intervallgrenzen $b_1, b_2, \ldots, b_{n+1}$ gilt $\frac{b_{i+1}-b_{i}}{n}=\Delta b$ für $i=1, 2, \ldots n$. * Die äußeren Grenzen $b_1$ und $b_n$ sollen als optionale Parametern `min` und `max` an die Funktion übergeben werden. Werte aus `x`, die zu keinem Intervall gehören, sollen ignoriert werden. Es wird aber eine Warnung ausgegeben, die sagt, welche Zahlen außerhalb des Bereichs liegen. * Eine Zahl $z$ gehört zum $i$-ten Intervall, falls $b_i \leq z < b_{i+1}$ gilt. Bis auf `x` sollen alle Parameter optional sein. Überlegen Sie sinnvolle Default-Werte. Es ist natürlich **nicht** erlaubt, in der eigenen Funktion andere Funktionen zu nutzen, die ein Histogramm erzeugen. Hier ein Beispiel: ```{r eval = T} # Bitte mit echter Lösung in myhistogram.R ersetzen: myhistogram = function(x, n, min, max) { if (missing(min)) min <- base::min(x) if (missing(max)) max <- base::max(x) if (missing(n)) n <- 10 if (min >= max) { stop("min muss kleiner als max sein.") } range <- min + max borders <- seq(min, max, length.out = n + 1) counts <- rep(0, n) outside <- x[x < min | x >= max] if (length(outside) > 0) { warning(paste("Zahl(en) außerhalb Intervallgrenzen:", paste(outside, collapse = ", "))) } for(value in x) { for (i in 1:n){ if (value >= borders[i] && value < borders[i+1]){ counts[i] <- counts[i] + 1 break } } } list(borders=borders, counts = counts) } x = seq(-5, 6, by = 1 / 3) l = myhistogram(x) print(l$borders) print(l$counts) ``` ## Beispieldaten Hier zunächst zwei Beispiele. ### Beispiel 1 Es wird eine Warnung ausgeben: ``` ## Warning in myhistogram(x, n = 10, min = -5, max = 6): Zahl(en) außerhalb ## Intervallgrenzen: 6 ``` ```{r} x = seq(-5, 6, by = 1 / 3) l = myhistogram(x, n = 10, min = -5, max = 6) solution = list( borders = c(-5.0, -3.9, -2.8, -1.7, -0.6, 0.5, 1.6, 2.7, 3.8, 4.9, 6.0), counts = c(4, 3, 3, 4, 3, 3, 4, 3, 3, 3) ) print(l$borders) print(l$counts) ``` ### Beispiel 2 ```{r} x = seq(-5, 6, by = 1 / 3) myhistogram(x, n = 5, min = -10, max = 10) solution = list(borders = c(-10, -6, -2, 2, 6, 10), counts = c(0, 9, 12, 12, 1)) ``` ### Beispiel 3 Ganze Zahlen mit Wiederholungen, Default-Werte für `n`, `min` und `max`. Da $b_{n+1}$ selbst zu keinem Intervall gehört, wird das Maximum (10) als außerhalb gemeldet: ```{r} x = c(1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 6, 7, 8, 9, 10) l = myhistogram(x) print(l$borders) print(l$counts) ``` ### Beispiel 4 Werte unterhalb von `min` und oberhalb von `max` werden ignoriert und in der Warnung aufgelistet: ```{r} x = c(-3, -1, 0, 0.5, 1, 2.5, 4, 4.99, 5, 7) l = myhistogram(x, n = 5, min = 0, max = 5) solution = list(borders = c(0, 1, 2, 3, 4, 5), counts = c(2, 1, 1, 0, 2)) print(l$borders) print(l$counts) ``` ### Beispiel 5 Normalverteilte Zufallszahlen, deren Bereich vollständig innerhalb von `min` und `max` liegt (keine Warnung): ```{r} set.seed(42) x = rnorm(100, mean = 0, sd = 1) l = myhistogram(x, n = 8, min = -4, max = 4) print(l$borders) print(l$counts) print(sum(l$counts)) # muss 100 ergeben ``` ## Barplot Nutzen Sie Ihre Funktion `myhistogram` und erzeugen Sie einen Barplot mit _ggplot_. Die _x_-Achse zeigt dabei die Mitte des Intervalls und die _y_-Achse die Anzahl der Elemente in dieser Klasse. Tipp: Der Parameter `stat` von `geom_bar` ist wichtig. Vervollständigen Sie den Chunk. Die Kommentare sollen zu Anweisungen umgewandelt werden: ```{r} library("ggplot2") set.seed(1) x = rnorm(0, 1, n = 1000) h = myhistogram(x, n = 10) bins = (h$borders[-1]+h$borders[-length(h$borders)])/2 # letzte und erste Grenze entfernen sodass nebeneinanderliegende Grenzen in den Vektoren jeweils auf der gleichen Indexposition liegen. Man verschiebt die Grenzen also #print(h$borders[-1]) #print(h$borders[length(-h$borders)]) print(h$borders) count = h$counts #/sum(h$counts) # Damit kann man die relative statt der absoluten Häufigkeit anzeigen ggplot() + geom_bar(aes(x=bins, y=count), stat="identity")+ labs(title="Histogramm für normalverteilte Daten", y="Absolute Häufigkeit", x="Intervalle") ```