Es soll ein eigenes Histogramm erzeugt werden. Der Dateiname für das
Skript ist myhistogram.R.
myhistogramProgrammieren 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.
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.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:
# 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) + 10^-12 # sonst fällt max(x) wegen b_i <= z < b_{i+1} raus
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)
## [1] -5.0 -3.9 -2.8 -1.7 -0.6 0.5 1.6 2.7 3.8 4.9 6.0
print(l$counts)
## [1] 4 3 3 4 3 3 4 3 3 4
Hier zunächst zwei Beispiele.
Es wird eine Warnung ausgeben:
## Warning in myhistogram(x, n = 10, min = -5, max = 6): Zahl(en) außerhalb
## Intervallgrenzen: 6
x = seq(-5, 6, by = 1 / 3)
l = myhistogram(x, n = 10, min = -5, max = 6)
## Warning in myhistogram(x, n = 10, min = -5, max = 6): Zahl(en) außerhalb
## Intervallgrenzen: 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)
## [1] -5.0 -3.9 -2.8 -1.7 -0.6 0.5 1.6 2.7 3.8 4.9 6.0
print(l$counts)
## [1] 4 3 3 4 3 3 4 3 3 3
x = seq(-5, 6, by = 1 / 3)
myhistogram(x, n = 5, min = -10, max = 10)
## $borders
## [1] -10 -6 -2 2 6 10
##
## $counts
## [1] 0 9 12 12 1
solution = list(borders = c(-10, -6, -2, 2, 6, 10),
counts = c(0, 9, 12, 12, 1))
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:
x = c(1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 6, 7, 8, 9, 10)
l = myhistogram(x)
print(l$borders)
## [1] 1.0 1.9 2.8 3.7 4.6 5.5 6.4 7.3 8.2 9.1 10.0
print(l$counts)
## [1] 1 2 3 4 1 1 1 1 1 1
Werte unterhalb von min und oberhalb von
max werden ignoriert und in der Warnung aufgelistet:
x = c(-3, -1, 0, 0.5, 1, 2.5, 4, 4.99, 5, 7)
l = myhistogram(x, n = 5, min = 0, max = 5)
## Warning in myhistogram(x, n = 5, min = 0, max = 5): Zahl(en) außerhalb
## Intervallgrenzen: -3, -1, 5, 7
solution = list(borders = c(0, 1, 2, 3, 4, 5),
counts = c(2, 1, 1, 0, 2))
print(l$borders)
## [1] 0 1 2 3 4 5
print(l$counts)
## [1] 2 1 1 0 2
Normalverteilte Zufallszahlen, deren Bereich vollständig innerhalb
von min und max liegt (keine Warnung):
set.seed(42)
x = rnorm(100, mean = 0, sd = 1)
l = myhistogram(x, n = 8, min = -4, max = 4)
print(l$borders)
## [1] -4 -3 -2 -1 0 1 2 3 4
print(l$counts)
## [1] 0 4 11 31 37 15 2 0
print(sum(l$counts)) # muss 100 ergeben
## [1] 100
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:
library("ggplot2")
set.seed(1)
x = rnorm(0, 1, n = 1000)
h = myhistogram(x)
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)
## [1] -3.0080486 -2.3262161 -1.6443835 -0.9625510 -0.2807185 0.4011140
## [7] 1.0829466 1.7647791 2.4466116 3.1284442 3.8102767
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")
print(h$counts)
## [1] 17 40 122 225 248 206 96 41 4 1