Häufigkeitsverteilung

Deskriptive Statistik

Zusammenfassung
In diesem Kapitel wird das Konzept der Häufigkeitsverteilung eines Merkmals mit gegebener Stichprobe beschrieben, die dazu dient Daten sinnvoll zusammenzufassen. Dazu werden absolute und relative Häufigkeiten von Merkmalsausprägungen eingeführt. Begleitet wird das Kapitel von anschaulichen Beispielen und Aufgaben, die mit R bearbeitet werden können.

Lernziele: Am Ende des Kapitels können Sie

  • Beobachtungen einer Stichprobe ordnen (händisch und mit R).
  • absolute und relative Häufigkeiten berechnen (händisch und mit R).

Hinweis: Die mit einem gekennzeichneten Aufgaben können Sie durch schriftliches Rechnen lösen. Die mit gekennzeichneten Aufgaben setzen Grundkenntnisse der Programmierung mit der statistischen Software R voraus. Sie können R hier installieren, falls Sie R nicht auf Ihrem Rechner installiert haben. Zusätzlich empfiehlt sich die Installation einer integrierten Entwicklungsumgebung (IDE), wie zum Beispiel RStudio. Alternativ zur Installation können Sie die Web-Version webR direkt im Browser verwenden.

1 Einführung

Wir haben eine Stichprobe (x_1, x_2, \dots, x_n) eines Merkmals X gegeben. Diese Stichprobe enthält alle Informationen, die wir zur Analyse zur Verfügung haben. Allerdings fällt es uns schwer diese Informationen aus den unverarbeiteten Daten herauszulesen, insbesondere, wenn die Stichprobe (genauer die Stichprobengröße n) sehr groß ist und das Merkmal viele verschiedene Ausprägungen besitzt.

Beispiel 1 (Blutgruppe und Körpergröße bei 12 Personen)

Es wurden in einer Umfrage 12 Personen nach ihrer Blutgruppe und Körpergröße gefragt. Folgende Tabelle zeigt die Ergebnisse:

ID 1 2 3 4 5 6 7 8 9 10 11 12
Blutgruppe A A B AB 0 0 A 0 B A 0 A
Größe 170.5 183.0 174.5 158.0 167.5 179.5 192.0 177.5 186.5 161.5 181.0 164.0

Mögliche Fragen:

  • Wie viele Personen haben Blutgruppe A?

  • Wie viele Personen sind zwischen 170-180 cm groß?

Schon bei einer so kleinen Stichprobe wie in diesem Beispiel 1 können wir die Fragen nicht auf den ersten Blick beantworten. Daher lernen wir in diesem Kapitel die Häufigkeitsverteilung der Stichprobe kennen, die es uns ermöglichen relevante Informationen schnell herauszulesen. Dazu führen wir zunächst geordnete Stichproben und dann absolute und relative Häufigkeiten ein.

2 Geordnete Stichprobe

Unter einer Urliste versteht man die bei einer statistischen Untersuchung erhobenen (beobachteten) Merkmalsausprägungen in ungeordneter Reihenfolge. Im obigen Beispiel zu Blutgruppe und Körpergröße sind die Daten in Form von Urlisten gegeben.

Um einen ersten besseren Überblick zu erhalten, können wir die Stichprobe ordnen. Ist das Merkmal X mindestens ordinal skaliert, ergibt sich eine natürliche Ordnung durch die Rangfolge der Merkmalsausprägungen. Um die ursprüngliche und geordnete Stichprobe voneinander zu unterscheiden, notiert man letztere gesondert:

Definition 1 (Ordnungsstatistik)

Sei X ein mindestens ordinal skaliertes Merkmal und (x_1, \dots, x_n) eine (ungeordnete) Stichprobe dieses Merkmals. Dann bezeichnen wir mit (x_{(1)}, \dots, x_{(n)}) die geordnete Stichprobe, auch Ordnungsstatistik, sodass x_{(i)} \le x_{(j)} für alle i \le j gilt.

Eine weitere Schreibweise für Ordnungsstatistiken, die auch oft in der Literatur verwendet wird, ist (x_{1:n}, \dots, x_{n:n}).

Bei einem nominal skalierten Merkmal gibt es hingegen keine natürliche Ordnung und somit auch keine Ordnungsstatistik. Allerdings können wir zur besseren Lesbarkeit Beobachtungen mit gleicher Merkmalsausprägung nebeneinander schreiben.

Beispiel 2 (Fortsetzung: Blutgruppe und Körpergröße bei 12 Personen)

Die Blutgruppe ist ein nominal skaliertes Merkmal. Wir können die Stichprobe z.B. auf folgende zwei Arten sortieren:

(A, A, A, A, A, B, B, AB, 0, 0, 0, 0) oder (0, 0, 0, 0, A, A, A, A, A, AB, B, B)

Die Körpergröße ist ein kardinal skaliertes Merkmal. Hier sortieren wir nach der natürlichen Ordnung von klein nach groß:

(158.0, 161.5, 164.0, 167.5, 170.5, 174.5, \, 177.5, 179.5, 181.0, 183.0, 186.5, 192.0)

Nun sehen wir schon viel leichter:

  • 5 Personen haben Blutgruppe A

  • 4 Personen sind zwischen 170 cm und 180 cm groß

Wir können beim Sortieren der Beobachtungen auch die Hilfe von R in Anspruch nehmen. Eine Möglichkeit bietet dabei die Funktion sort(). Vektoren des Datentyps character werden hierbei alphabetisch sortiert, wobei vorkommende Ziffern vor Buchstaben sortiert werden. Bei Verwendung des Datentyps Faktor kann die Sortierung mithilfe des Arguments levels selbst festgelegt werden.

# Erstellen eines Datensatzes, der die Variablen Größe und 
# Blutgruppe enthält:
data <- data.frame(groesse = c(170.5, 183.0, 174.5, 158.0, 167.5, 179.5,
                               192.0, 177.5, 186.5, 161.5, 181.0, 164.0),
                   blutgruppe = c("A", "A", "B", "AB", "0", "0", "A", "0",
                                  "B", "A", "0", "A"))
# Betrachtung der Struktur des erzeugten Datensatzes 
str(data)
'data.frame':   12 obs. of  2 variables:
 $ groesse   : num  170 183 174 158 168 ...
 $ blutgruppe: chr  "A" "A" "B" "AB" ...
# Sortieren des numerischen Merkmals 'Groesse'
sort(data$groesse)
 [1] 158.0 161.5 164.0 167.5 170.5 174.5 177.5 179.5 181.0 183.0 186.5 192.0
# Sortieren des nominalen Merkmals 'Blutgruppe' (datentyp character)
sort(data$blutgruppe)
 [1] "0"  "0"  "0"  "0"  "A"  "A"  "A"  "A"  "A"  "AB" "B"  "B" 
# Sortieren des nominalen Merkmals 'Blutgruppe' (datentyp factor)
sort(factor(data$blutgruppe, levels = c("A", "AB", "B", "0")))
 [1] A  A  A  A  A  AB B  B  0  0  0  0 
Levels: A AB B 0

Anmerkung.

Das Ordnen der Stichprobe kann uns helfen relevante Informationen aus dieser zu ziehen, obwohl das Ordnen an sich ein Informationsverlust bedeutet, da die ursprüngliche Reihenfolge der Beobachtungen verloren geht.

Damit ist gemeint, dass wir die Urliste zu einer geordneten Liste transformieren können, aber aus der geordneten Liste können wir die Urliste ohne zusätzliche Hilfe nicht mehr rekonstruieren.

Anhand des penguins Datensatzes aus dem Paket palmerpenguins1(Horst, Hill, und Gorman 2020) können Sie nun einmal selbst Aufgaben zur Datenverarbeitung ausprobieren. Dafür müssen Sie das Paket palmerpenguins mit den Funktionen install.packages() und library() installieren und laden.

Aufgabe 1

Sortieren Sie die Schnabellänge der Pinguine, die in der Variablen bill_length_mm in Millimetern angegeben ist. Welche Fragen lassen sich gut anhand des sortierten Datensatzes beantworten?

Unterscheiden Sie nun zusätzlich nach dem Geschlecht der Vögel, welches in der Variablen sex angegeben ist. Stellen Sie einen Unterschied bezügliche der minimalen und maximalen Schnabellängen in den Gruppen fest?

Zum Sortieren können wir die Funktion sort() benutzen.

3 Absolute und relative Häufigkeiten

Noch kompakter kann man die Stichprobe aufschreiben, wenn man jede (beobachtete) Ausprägung nur einmal gemeinsam mit der Häufigkeit aufschreibt, mit der sie in der Stichprobe vorkommt. Dies bringt uns zum Begriff der absoluten und relativen Häufigkeit:



\#A gibt die Mächtigkeit der Menge A an. Bei einer endlichen Menge also die Anzahl der Elemente in A. Beispiel: A = \{1, 6, 3.4\} Dann gilt \# A = 3.

\mathbb{1}(\cdot = a) heißt Indikatorfunktion. Es gilt \mathbb{1}\left(x_i = a \right) = \begin{cases} 1, & \text{falls } x_i = a \\ 0, & \text{falls } x_i \neq a \end{cases}~~.

Definition 2 (Absolute und relative Häufigkeit)

Sei (x_1, \dots, x_n) eine Stichprobe eines Merkmals X und \{a_j \mid j \in J\} die Menge der möglichen Merkmalsausprägungen (kurz: MA) von X. Dann bezeichnen wir mit \begin{align*} H(a_j) & = \# \{x_i \mid x_i = a_j\} = \sum_{i = 1}^n \mathbb{1}\left(x_i = a_j\right) \\ & \widehat{=} ~~ \text{Anzahl der Beobachtungen mit MA $a_j$} \end{align*} die absolute Häufigkeit der Merkmalsausprägungen a_j in der Stichprobe (x_1,\dots,x_n) und mit \begin{align*} h(a_j) & = \frac{H(a_j)}{n} \\ & \widehat{=} ~~ \text{Anteil der Beobachtungen mit MA $a_j$} \end{align*} die relative Häufigkeit der Merkmalsausprägungen a_j in der Stichprobe (x_1,\dots,x_n).

Bemerkungen:

  • Die absoluten Häufigkeiten summieren sich zu n auf: \sum\limits_{j \in J} H(a_j) = n.

  • Die relativen Häufigkeiten liegen zwischen 0 und 1: 0 \le h(a_j) \le 1
    und summieren sich zu 1 auf: \sum\limits_{j \in J} h(a_j) = \sum\limits_{j \in J} \dfrac{H(a_j)}{n} = \dfrac{1}{n} \cdot \sum\limits_{j \in J} H(a_j) = \dfrac{n}{n} = 1.

  • Notation: Wenn wir hervorheben möchten, dass wir die absoluten oder relativen Häufigkeiten eines bestimmten Merkmals X meinen, so schreiben wir auch H_X(a_j) und h_X(a_j).

Beispiel 3 (Fortsetzung: Blutgruppe und Körpergröße bei 12 Personen)

Relative und absolute Häufigkeiten des Merkmals Blutgruppe:

MA a_j: A B AB 0 \sum
abs. Häufigkeit H(a_j): 5 2 1 4 12
rel. Häufigkeit h(a_j): 5/12 2/12 1/12 4/12 1

Die letzte Spalte der Tabelle dient zur Kontrolle.

Relative und absolute Häufigkeiten des Merkmals Körpergröße:

(beob.) MA a_j: 158.0 161.5 164.0 167.5 170.5 \sum
abs. Häufigkeit H(a_j): 1 1 1 1 1 12
rel. Häufigkeit h(a_j): 1/12 1/12 1/12 1/12 1/12 1

Die beobachteten Merkmalsausprägungen des Merkmals Körpergröße haben alle die gleichen Häufigkeiten, da jede genau einmal beobachtet wird.
Außerdem gilt für alle nicht-beobachteten Merkmalsausprägungen (z.B. 160.0, 160.1, usw.), eine absolute und relative Häufigkeit von 0, denn sie sind im Datensatz nicht vorhanden.

Auch die absoluten und relativen Häufigkeiten können wir mit R bestimmen. Um die absoluten Häufigkeiten zu erhalten, kann die Funktion table() verwendet werden. Die absoluten Häufigkeiten können wir dann durch den Stichprobenumfang n teilen, um so relative Häufigkeiten zu berechnen.

# Stichprobengumfang
n <-  nrow(data)

# Absolute Häufigkeiten des Merkmals Blutgruppe
table(data$blutgruppe)

 0  A AB  B 
 4  5  1  2 
# Relative Häufigkeiten des Merkmals Blutgruppe
MASS::fractions(table(data$blutgruppe) / n)

   0    A   AB    B 
 1/3 5/12 1/12  1/6 

Mithilfe der Funktion fractions() aus dem R-Paket MASS werden die Ergebnisse als Brüche und nicht als Dezimalzahlen dargestellt.

# Absolute Häufigkeiten des Merkmals Größe
table(data$groesse)

  158 161.5   164 167.5 170.5 174.5 177.5 179.5   181   183 186.5   192 
    1     1     1     1     1     1     1     1     1     1     1     1 
# Relative Häufigkeiten des Merkmals Größe
MASS::fractions(table(data$groesse) / n)

  158 161.5   164 167.5 170.5 174.5 177.5 179.5   181   183 186.5   192 
 1/12  1/12  1/12  1/12  1/12  1/12  1/12  1/12  1/12  1/12  1/12  1/12 

Wie am Beispiel der Körpergröße zu sehen, fassen die absoluten und relativen Häufigkeiten die Informationen der Stichprobe nicht sinnvoll zusammen, wenn die Beobachtungen einer Stichprobe (fast) alle verschieden sind. Dies kommt vor, wenn ein Merkmal sehr viele Ausprägungen besitzt, wie dies zum Beispiel häufig bei quantitativen Merkmalen der Fall ist.

Oftmals interessieren wir uns allerdings nicht für den exakten Wert der Beobachtungen, sondern eher für die Region, in der sie liegt. Daher kann es bei quantitativen Merkmalen sinnvoll sein eine Klassierung vorzunehmen.

Erinnerung: Beim Klassieren teilen wir den Wertebereich der Merkmalsausprägungen in disjunkte Intervalle (k_{j−1},k_j]. Diese verwenden wir als Klassen. Ausführlich wurde dies im ersten Kapitel ‘Einführung: Statistische Untersuchung’ erklärt.

Wir können nun auch für das klassierte Merkmal absoluten und relativen Häufigkeiten berechnen, welche nun die Stichprobe sinnvoll zusammenfassen:



\mathbb{1}(\cdot \in K) heißt Indikatorfunktion. Es gilt \mathbb{1}\left(x_i \in K\right) = \begin{cases} 1, & \text{falls } x_i \in K \\ 0, & \text{falls } x_i \notin K \end{cases}~~.

Definition 3 (Absolute und relative Häufigkeit von klassierten Merkmalen)

Sei (x_1, \dots, x_n) eine Stichprobe eines Merkmals X mit Klassen K_1 = (k_0, k_1], \dots,K_l = (k_{l-1},k_l]. Dann bezeichnen wir mit \begin{align*} H(K_j) & = \#\{x_i \mid x_i \in K_j\} = \sum_{i = 1}^n \mathbb{1}\left(x_i \in (k_{j-1},k_j]\right)\\ & \widehat{=} ~~ \text{Anzahl der Beobachtungen in der $j$-ten Klasse} \end{align*} die absolute Häufigkeit und mit \begin{align*} h(K_j) & = \frac{H(K_j)}{n} \\ & \widehat{=} ~~ \text{Anteil der Beobachtungen in der $j$-ten Klasse} \end{align*} die relative Häufigkeit der j-ten Klasse.

Beispiel 4 (Fortsetzung: Körpergröße bei 12 Personen)

Die originalen Werte der Beobachtungen lauten:

158.0, 161.5, 164.0, 167.5, 170.5, 174.5, 177.5, 179.5, 181.0, 183.0, 186.5, 192.0

Wir definieren nun Bereiche, sogenannte Klassen, denen wir die Beobachtungen zuordnen. Z.B. (150, 160], (160, 170], (170, 180], (180, 190], (190, 200]. Dann ergeben sich die absoluten und relativen Häufigkeiten der Klassen wie folgt:

Klassen K_j: (150,160] (160,170] (170,180] (180,190] (190,200] \sum
Beobachtungen in Klasse K_j: 158.0 161.5, 164.0, 167.5 170.5, 174.5, 177.5, 179.5 181.0, 183.0, 186.5 192.0
abs. Häufigkeiten H(K_j): 1 3 4 3 1 12
rel. Häufigkeiten h(K_j): 1/12 1/4 1/3 1/4 1/12 1

Wenn die Klassenbreiten allerdings unterschiedlich groß sind, lassen sich die relativen Häufigkeiten zweier oder mehrerer Klassen nicht gut miteinander vergleichen. Nehmen wir z.B. an, dass die Beobachtungen gleichmäßig auf dem Wertebereich verteilt liegen und wir die Klassenbreite einer Klasse K_1 doppelt so groß wie die Klassenbreite einer weiteren Klasse K_2 wählen. Dann liegen in der Klasse K_1 offensichtlich doppelt so viele Beobachtungen wie in Klasse K_2, sodass h(K_1) = 2 \cdot h(K_2) gilt.

Dieses Problem kann mit der Häufigkeitsdichte gelöst werden. Hier wird die relative Häufigkeit mit der Klassenbreite normiert, sodass in unserem Beispiel die Häufigkeitsdichte in beiden Klassen gleich groß wäre.

Definition 4 (Häufigkeitsdichte von klassierten Merkmalen)

Sei (x_1, \dots, x_n) eine Stichprobe eines Merkmals X mit Klassen K_1 = (k_0, k_1], \dots,K_l = (k_{l-1},k_l]. Dann bezeichnen wir mit \begin{align} f_n(K_j) & = \frac{h(K_j)}{k_j - k_{j-1}}\end{align} die Häufigkeitsdichte der Klasse K_j und mit \begin{align} f_n(x) = \frac{h(K_j)}{k_j - k_{j-1}}, ~~\text{falls } x \in (k_{j-1}, k_j] \end{align} die Häufigkeitsdichte an der Stelle x.

Bei der Klassierung von Merkmalen kann uns R erneut helfen. Dazu verwenden wir die Funktion hist() und setzen plot = FALSE. Eigentlich ist diese Funktion zum Berechnen und Darstellen von Histogrammen, welche wir im nächsten Kapitel dieser Lerneinheit kennenlernen. Als Nebenprodukt erhalten wir allerdings auch die absoluten Häufigkeiten und die Häufigkeitsdichten der Klassen:

# Anwendung der hist-Funktion auf die Körpergröße
hist(data$groesse, plot = FALSE)
$breaks
[1] 155 160 165 170 175 180 185 190 195

$counts
[1] 1 2 1 2 2 2 1 1

$density
[1] 0.01666667 0.03333333 0.01666667 0.03333333 0.03333333 0.03333333 0.01666667
[8] 0.01666667

$mids
[1] 157.5 162.5 167.5 172.5 177.5 182.5 187.5 192.5

$xname
[1] "data$groesse"

$equidist
[1] TRUE

attr(,"class")
[1] "histogram"

Man kann die Anzahl der Klassen und die Klassengrenzen auch mit dem Argument breaks selbst festlegen.

# Anwendung der hist-Funktion auf die Körpergröße mit den Klassen 
# [150, 160], (160, 170], (170, 180], (180, 190], (190, 200]
hist(data$groesse, breaks = c(150, 160, 170, 180, 190, 200), plot = FALSE)
$breaks
[1] 150 160 170 180 190 200

$counts
[1] 1 3 4 3 1

$density
[1] 0.008333333 0.025000000 0.033333333 0.025000000 0.008333333

$mids
[1] 155 165 175 185 195

$xname
[1] "data$groesse"

$equidist
[1] TRUE

attr(,"class")
[1] "histogram"

Aufgabe 2

Überlegen Sie sich, was die einzelnen Listeneinträge des Outputs der Funktion hist() bedeuten.

Mit der Eingabe ?hist oder help(hist) öffnet sich in R die Hilfeseite zu der Funktion hist(). Falls Sie allein nicht weiter kommen, könnte die Hilfeseite Ihnen helfen.

Was die Funktion hist() nicht macht, ist das Angeben der Klasseneinteilung, also welche Beobachtung zu welcher Klasse geordnet wurde. Daher schreiben wir nun eine eigene Funktion:


Falls Sie das Schreiben einer Funktion noch überfordert, dann berechnen Sie für das Merkmal Gewicht (body_mass_g) des Datensatzes penguins die geforderten 7 Vektoren (classes, breaks, mids, widths, counts, freq und density).

Aufgabe 3

Schreiben Sie eine Funktion my_class(), die eine quantitative Stichprobe klassiert. Als Input sollten Sie mindestens die Stichprobe und einen Vektor mit den Klassengrenzen eingeben können. Als Output soll die Funktion eine Liste mit den folgenden Einträgen zurückgeben:

  • $classes ist ein Vektor, der die Klassen der einzelnen Beobachtungen der Stichprobe enthält,

  • $breaks ist ein Vektor mit den Klassengrenzen,

  • $mids ist ein Vektor mit den Klassenmitten,

  • $widths ist ein Vektor mit den Klassenbreiten,

  • $counts ist ein Vektor mit den absoluten Häufigkeiten,

  • $freq ist ein Vektor mit den relativen Häufigkeiten und

  • $density ist ein Vektor mit den Häufgkeitsdichten der Klassen.

Probieren Sie Ihre Funktion an dem Merkmal body_mass_g des Datensatzes penguins aus, die das Gewicht der Pinguine angibt.

Eine Funktion wird in R nach folgenden Schema geschrieben:

func_name <- function(arg1, arg2) {
  # Beliebig viele Berechnungen z.B.
  result <- arg1 + arg2
  # Das Ergebnis, welches ausgegeben werden soll:
  return(result)
}

# Funktion anwenden:
func_name(arg1 = 1, arg2 = 2)
[1] 3

Außerdem könnte Ihnen helfen:

  • Mit list() erzeugen Sie eine Liste.
  • Um die Stichprobe in Klassen zu ordnen, könnten if() {...} else {...} Bedingungen und Schleifen, wie die for-Schleife helfen.
  • Wir sollten uns Gedanken darüber machen, wie unsere Funktion fehlende Werte behandelt.
  • Kontrollieren Sie Ihre geschriebene Funktion, indem Sie sie mit den Ergebnissen der hist() Funktion vergleichen.

Nun kommen wir als letztes zum Begriff der Häufigkeitsverteilung:

Definition 5 (Häufigkeitsverteilung)

Als Häufigkeitsverteilung einer Stichprobe (x_1,\dots, x_n) eines Merkmals X bezeichnet man die beobachteten Merkmalsausprägungen mit ihren absoluten oder relativen Häufigkeiten.

Bei klassierten Merkmalen werden die absoluten oder relativen Häufigkeiten der Klassen oder die Häufigkeitsdichte angegeben.

Wie wir schon in den obigen Beispielen gesehen haben, können wir die Häufigkeitsverteilung in einer Tabelle darstellen. Eine weitere Möglichkeit sind grafische Darstellungen, die vor allem als Kommunikationsmedium dienen und übersichtlicher als Tabellen sein können. Eine Auswahl davon werden wir im nächsten Kapitel dieser Lerneinheit kennenlernen.

4 Zusammenfassung

Eine Urliste, also eine ungeordnete Stichprobe eines Merkmals X, enthält alle uns zur Verfügung stehenden Informationen. Doch ist es ohne Verarbeitung der Daten schwierig die gesuchten Informationen herauszulesen besonders dann, wenn der Stichprobenumfang sehr groß ist. In diesem Kapitel haben wir zur Verarbeitung der Urliste die Häufigkeitsverteilung kennengelernt, die eine solche Stichprobe sinnvoll zusammenfasst. Man kann diese in Form einer Tabelle darstellen oder man nutzt verschiedene grafische Darstellungen.

Die Häufigkeitsverteilung eines Merkmals X mit gegebener Stichprobe (x_1,\dots,x_n) ist Zusammenfassung der Daten in absoluten oder relativen Häufigkeiten der Merkmalsausprägungen. Da sich die Beobachtungen von Merkmalen mit sehr vielen möglichen Merkmalsausprägungen oftmals fast alle voneinander unterscheiden, kann man eine Klassierung durchführen. Dabei werden die Beobachtungen in Klassen, die verschiedene Regionen des Wertebereichs abdecken, zugeordnet. So gehen zwar die konkreten Beobachtungswerte verloren, doch man kann einfacher sehen, in welcher Klasse bzw. Region sich die Beobachtungen häufen.

Lösungen der Aufgaben

Zum sortieren können wir die Funktion sort() verwenden.

#install.packages("palmerpenguins")
library("palmerpenguins")

sort(penguins$bill_length_mm)
  [1] 32.1 33.1 33.5 34.0 34.1 34.4 34.5 34.6 34.6 35.0 35.0 35.1 35.2 35.3 35.5
 [16] 35.5 35.6 35.7 35.7 35.7 35.9 35.9 36.0 36.0 36.0 36.0 36.2 36.2 36.2 36.3
 [31] 36.4 36.4 36.5 36.5 36.6 36.6 36.7 36.7 36.8 36.9 37.0 37.0 37.2 37.2 37.3
 [46] 37.3 37.3 37.5 37.5 37.6 37.6 37.6 37.7 37.7 37.7 37.8 37.8 37.8 37.8 37.8
 [61] 37.9 37.9 38.1 38.1 38.1 38.1 38.2 38.2 38.3 38.5 38.6 38.6 38.6 38.7 38.8
 [76] 38.8 38.8 38.9 38.9 39.0 39.0 39.0 39.1 39.2 39.2 39.2 39.3 39.5 39.5 39.5
 [91] 39.6 39.6 39.6 39.6 39.6 39.7 39.7 39.7 39.7 39.8 40.1 40.2 40.2 40.2 40.3
[106] 40.3 40.5 40.5 40.6 40.6 40.6 40.6 40.7 40.8 40.8 40.9 40.9 40.9 40.9 41.0
[121] 41.1 41.1 41.1 41.1 41.1 41.1 41.1 41.3 41.3 41.4 41.4 41.5 41.5 41.6 41.7
[136] 41.8 42.0 42.0 42.0 42.1 42.2 42.2 42.3 42.4 42.5 42.5 42.5 42.6 42.7 42.7
[151] 42.8 42.8 42.9 42.9 43.1 43.2 43.2 43.2 43.2 43.3 43.3 43.4 43.5 43.5 43.5
[166] 43.6 43.8 44.0 44.1 44.1 44.4 44.5 44.5 44.5 44.9 44.9 45.0 45.1 45.1 45.1
[181] 45.2 45.2 45.2 45.2 45.2 45.2 45.3 45.3 45.4 45.4 45.5 45.5 45.5 45.5 45.5
[196] 45.6 45.6 45.7 45.7 45.7 45.8 45.8 45.8 45.9 46.0 46.0 46.1 46.1 46.1 46.2
[211] 46.2 46.2 46.2 46.2 46.3 46.4 46.4 46.4 46.4 46.5 46.5 46.5 46.5 46.5 46.6
[226] 46.6 46.7 46.7 46.8 46.8 46.8 46.8 46.9 46.9 47.0 47.2 47.2 47.3 47.3 47.4
[241] 47.5 47.5 47.5 47.5 47.6 47.6 47.7 47.8 48.1 48.1 48.2 48.2 48.4 48.4 48.4
[256] 48.5 48.5 48.5 48.6 48.7 48.7 48.7 48.8 49.0 49.0 49.0 49.1 49.1 49.1 49.2
[271] 49.2 49.3 49.3 49.4 49.5 49.5 49.5 49.6 49.6 49.6 49.7 49.8 49.8 49.8 49.9
[286] 50.0 50.0 50.0 50.0 50.0 50.1 50.1 50.2 50.2 50.2 50.3 50.4 50.4 50.5 50.5
[301] 50.5 50.5 50.5 50.6 50.7 50.7 50.8 50.8 50.8 50.8 50.9 50.9 51.0 51.1 51.1
[316] 51.3 51.3 51.3 51.3 51.4 51.5 51.5 51.7 51.9 52.0 52.0 52.0 52.1 52.2 52.2
[331] 52.5 52.7 52.8 53.4 53.5 54.2 54.3 55.1 55.8 55.9 58.0 59.6

Anhand der sortierten Daten können wir gut das Maximum und Minimum ablesen. Die kleinste Schnabellänge beträgt somit 32.1 Millimeter und die längste Schnabellänge 59.6 Millimeter. Damit liegen Maximum und Minimum 27.5 Millimeter auseinander. Die längsten Schnäbel sind somit fast doppelt so lang wie die kürzesten. Außerdem sticht kein Wert besonders heraus. Wäre z.B. der Wert 484 Millimeter im Datensatz enthalten, könnten wir uns fragen, ob hier der Dezimalpunkt vergessen wurde und es sich eigentlich um 48.4 Millimeter handelt, da er sich so stark von den restlichen Beobachtungen unterscheidet. Anstelle des gesamten sortierten Vektors können wir mithilfe der Funktionen head() und tail() uns nur den Anfang und das Ende des Vektors ausgeben lassen.

# Anfang des Vektors
head(sort(penguins$bill_length_mm))
[1] 32.1 33.1 33.5 34.0 34.1 34.4
# Ende des Vektors
tail(sort(penguins$bill_length_mm))
[1] 54.3 55.1 55.8 55.9 58.0 59.6

Mit der Funktion split() können wir den Datensatz nach Geschlecht aufteilen. Wir erhalten zwei Datensätze, welche in einer Liste gespeichert werden.

penguins_splitted <- split(penguins, f = penguins$sex)

Auch hier können wir wieder die Funktionen head() und tail() benutzen, um nur den Anfang und das Ende des sortierten Vektors zu betrachten.

# Weibliche Pinguine

# Anfang des Vektors
head(sort(penguins_splitted$female$bill_length_mm))
[1] 32.1 33.1 33.5 34.0 34.4 34.5
# Ende des Vektors
tail(sort(penguins_splitted$female$bill_length_mm))
[1] 50.1 50.2 50.5 50.5 50.9 58.0
# Männliche Pinguine

# Anfang des Vektors
head(sort(penguins_splitted$male$bill_length_mm))
[1] 34.6 35.1 36.3 37.2 37.2 37.3
# Ende des Vektors
tail(sort(penguins_splitted$male$bill_length_mm))
[1] 54.2 54.3 55.1 55.8 55.9 59.6

Sowohl die maximale als auch die minimale Schnabellänge der weiblichen Pinguine ist etwas geringer als bei den männlichen Pinguinen. Die Werte liegen mit 32.1 und 34.6, sowie 58.0 und 59.6 jeweils nah beieinander.

Zurück zu Aufgabe 1

Listeneinträge des Outputs von hist():

  • $breaks: Ein Vektor mit den Klassengrenzen
  • $counts: Ein Vektor mit der Beobachtungsanzahl leder Klassen
  • $density: Ein Vektor mit der Häufigkeitsdichte, d.h. die relativen Häufigkeit geteilt durch die Klassenbreite
  • $mids: Ein Vektor mit den Klassenmitten
  • $xname: Ein Character, der den Namen des in hist() eingesetzten Arguments x enthält
  • $equidist: Ein logischer Wert (TRUE oder FALSE), der angibt, ob die Klassen des Histogramms äquidistant sind, also alle Klassen die gleiche Klassenbreite besitzen
  • attr(,“class”): Gibt die Klasse des zurückgegebenen R-Objekts an (histogram)

Zurück zu Aufgabe 2

Wir müssen zunächst eine Funktion schreiben, die unter Angabe der Klassengrenzen eine Stichprobe klassiert.

In der hier vorgeschlagenen Funktion werden die Stichprobe x und die Klassengrenzen breaks jeweils als Vektoren in die Funktion eingegeben. Die Funktion ist so geschrieben, dass die Untergrenze nur in der ersten Klasse und die jeweilige Obergrenze in allen Klassen enthalten ist. Fehlende Werte werden zur Berechnung der relativen Häufigkeiten und Häufigkeitsdichte nicht mit einbezogen, d.h. die Stichprobengröße verringert sich um die Anzahl der fehlenden Werte. Im klassierten Merkmal, werden die Fehlenden Werte erneut mit NA markiert, damit der Vektor classes die gleiche Länge hat, wie die Ursprungsstichprobe.

my_class <- function(x, breaks){
  # Stichprobe ohne fehlende Werte
  x1 <- x[!is.na(x)]
  # die Klassengrenzen sollten als sortierter Vektor angegeben werden, 
  # zur Sicherheit sortieren wir nochmal
  breaks <- sort(breaks)
  # Anzahl der Klassengrenzen -> es gibt also l - 1 Klassen
  l <- length(breaks) 
  # wir prüfen, ob die Klassen den gesamten Wertebereich der Stichprobe 
  # überdecken. Falls dies nicht der Fall ist, wird der Vorgang abgebrochen
  # und eine Warnung zurückgegeben.
  if(breaks[1] > min(x1) | breaks[l] < max(x1)){
    return("Die Klassen decken nicht den gesamten Wertebereich der Stichprobe ab")
  }
  # im Vektor classes des Typ factor werden in der Schleife die zu den
  # Beobachtungen zugehörigen Klassen eingetragen
  # ein fehlender Wert in x erzeugt auch im Vektor classes einen fehlenden Wert
  else{
    classes <- numeric(length(x))
    for (i in seq_along(x)) {
      if(is.na(x[i])) {
        classes[i] <- NA
      } else {
        classes[i] <- min(which(breaks[-1] >= x[i]))
      }
    }
    classes <- factor(classes, levels = 1:(l-1), 
                      labels = paste("(",breaks[-l], ", ", breaks[-1],"]", sep = ""))
    return(
      list(
        classes = classes,
        breaks = breaks,
        # Klassenmitten
        mids = (breaks[-1] + breaks[-l]) / 2,
        # Klassenbreite
        widths = breaks[-1] - breaks[-l], 
        # absolute Häufigkeit der einzelnen Klassen
        counts = unname(table(classes)),
        # relative Häufigkeit der einzelnen Klassen
        freq = MASS::fractions(unname(table(classes)) / length(x1)),
        # Häufigkeitsdichte = relative Häufigkeit / Klassenbreite
        density = unname(table(classes)) /
          (length(x1) * (breaks[-1] - breaks[-l]))
     )
    )
  }
}

Zum Klassieren müssen wir Grenzen auswählen. In dem Lösungsvorschlag nehmen wir beispielsweise die Grenzen:

seq(2600, 6600, 400)
 [1] 2600 3000 3400 3800 4200 4600 5000 5400 5800 6200 6600

Nun wenden wir unsere Funktion auf penguins$body_mass_g an.

#install.packages("palmerpenguins")
library("palmerpenguins")

body_mass_g_classified <- my_class(penguins$body_mass_g, 
                                   seq(2600,6600, 400))
body_mass_g_classified
$classes
  [1] (3400, 3800] (3400, 3800] (3000, 3400] <NA>         (3400, 3800]
  [6] (3400, 3800] (3400, 3800] (4600, 5000] (3400, 3800] (4200, 4600]
 [11] (3000, 3400] (3400, 3800] (3000, 3400] (3400, 3800] (4200, 4600]
 [16] (3400, 3800] (3400, 3800] (4200, 4600] (3000, 3400] (3800, 4200]
 [21] (3000, 3400] (3400, 3800] (3400, 3800] (3800, 4200] (3400, 3800]
 [26] (3400, 3800] (3400, 3800] (3000, 3400] (3000, 3400] (3800, 4200]
 [31] (3000, 3400] (3800, 4200] (3000, 3400] (3800, 4200] (3000, 3400]
 [36] (3800, 4200] (3800, 4200] (3400, 3800] (3000, 3400] (4600, 5000]
 [41] (3000, 3400] (3800, 4200] (3000, 3400] (4200, 4600] (2600, 3000]
 [46] (4200, 4600] (3400, 3800] (2600, 3000] (3400, 3800] (3800, 4200]
 [51] (3400, 3800] (4200, 4600] (3400, 3800] (3800, 4200] (2600, 3000]
 [56] (3400, 3800] (3400, 3800] (3400, 3800] (2600, 3000] (3400, 3800]
 [61] (3000, 3400] (4200, 4600] (3400, 3800] (3800, 4200] (2600, 3000]
 [66] (3800, 4200] (3000, 3400] (3800, 4200] (3000, 3400] (4200, 4600]
 [71] (3400, 3800] (3800, 4200] (3400, 3800] (3800, 4200] (3400, 3800]
 [76] (4200, 4600] (3400, 3800] (3800, 4200] (3400, 3800] (3800, 4200]
 [81] (3000, 3400] (4600, 5000] (3400, 3800] (3800, 4200] (3000, 3400]
 [86] (3400, 3800] (3400, 3800] (3400, 3800] (3800, 4200] (3400, 3800]
 [91] (3400, 3800] (4200, 4600] (3000, 3400] (4200, 4600] (3000, 3400]
 [96] (4200, 4600] (3400, 3800] (4200, 4600] (2600, 3000] (3800, 4200]
[101] (3400, 3800] (4600, 5000] (3000, 3400] (4200, 4600] (2600, 3000]
[106] (3400, 3800] (3400, 3800] (3800, 4200] (3000, 3400] (4600, 5000]
[111] (3800, 4200] (4200, 4600] (3000, 3400] (4200, 4600] (3800, 4200]
[116] (3800, 4200] (2600, 3000] (3400, 3800] (3000, 3400] (3000, 3400]
[121] (3000, 3400] (3400, 3800] (3400, 3800] (3800, 4200] (3000, 3400]
[126] (3800, 4200] (3000, 3400] (4200, 4600] (3000, 3400] (3800, 4200]
[131] (3000, 3400] (3400, 3800] (3400, 3800] (4200, 4600] (3400, 3800]
[136] (3800, 4200] (3000, 3400] (3800, 4200] (3000, 3400] (4200, 4600]
[141] (3000, 3400] (3400, 3800] (3000, 3400] (3400, 3800] (2600, 3000]
[146] (3400, 3800] (4200, 4600] (3400, 3800] (3400, 3800] (3400, 3800]
[151] (3400, 3800] (3800, 4200] (4200, 4600] (5400, 5800] (4200, 4600]
[156] (5400, 5800] (5000, 5400] (4200, 4600] (4600, 5000] (5000, 5400]
[161] (4200, 4600] (5000, 5400] (4600, 5000] (5400, 5800] (4600, 5000]
[166] (5800, 6200] (3800, 4200] (5800, 6200] (3800, 4200] (6200, 6600]
[171] (4600, 5000] (5000, 5400] (5400, 5800] (4600, 5000] (4200, 4600]
[176] (5000, 5400] (4600, 5000] (5000, 5400] (3800, 4200] (5400, 5800]
[181] (4200, 4600] (5400, 5800] (5000, 5400] (4600, 5000] (5000, 5400]
[186] (5800, 6200] (5000, 5400] (5000, 5400] (4600, 5000] (5000, 5400]
[191] (4200, 4600] (5000, 5400] (3800, 4200] (5400, 5800] (4200, 4600]
[196] (4600, 5000] (5400, 5800] (4600, 5000] (3800, 4200] (5000, 5400]
[201] (5000, 5400] (5000, 5400] (4600, 5000] (5000, 5400] (4200, 4600]
[206] (4600, 5000] (4600, 5000] (5000, 5400] (4200, 4600] (4600, 5000]
[211] (4200, 4600] (5400, 5800] (3800, 4200] (5000, 5400] (4200, 4600]
[216] (5400, 5800] (4600, 5000] (5400, 5800] (4600, 5000] (5400, 5800]
[221] (4600, 5000] (5400, 5800] (4600, 5000] (4600, 5000] (5000, 5400]
[226] (5000, 5400] (4600, 5000] (5400, 5800] (4200, 4600] (5800, 6200]
[231] (4600, 5000] (5800, 6200] (4600, 5000] (5400, 5800] (4600, 5000]
[236] (5000, 5400] (4600, 5000] (5400, 5800] (4200, 4600] (5000, 5400]
[241] (4600, 5000] (5400, 5800] (4600, 5000] (5000, 5400] (4600, 5000]
[246] (5400, 5800] (4600, 5000] (5000, 5400] (4600, 5000] (4600, 5000]
[251] (4600, 5000] (5000, 5400] (4600, 5000] (5400, 5800] (4600, 5000]
[256] (5400, 5800] (4600, 5000] (5400, 5800] (4600, 5000] (5400, 5800]
[261] (4200, 4600] (5400, 5800] (4600, 5000] (5800, 6200] (4600, 5000]
[266] (5400, 5800] (4200, 4600] (5800, 6200] (4600, 5000] (5800, 6200]
[271] (4600, 5000] <NA>         (4600, 5000] (5400, 5800] (5000, 5400]
[276] (5000, 5400] (3400, 3800] (3800, 4200] (3400, 3800] (3400, 3800]
[281] (3400, 3800] (3800, 4200] (3000, 3400] (3400, 3800] (3800, 4200]
[286] (3400, 3800] (3400, 3800] (3400, 3800] (3400, 3800] (3800, 4200]
[291] (3400, 3800] (3800, 4200] (3000, 3400] (3400, 3800] (3400, 3800]
[296] (4200, 4600] (3400, 3800] (3000, 3400] (2600, 3000] (3400, 3800]
[301] (3000, 3400] (3800, 4200] (3000, 3400] (3400, 3800] (3400, 3800]
[306] (4200, 4600] (3000, 3400] (4200, 4600] (3000, 3400] (3800, 4200]
[311] (3400, 3800] (3800, 4200] (3800, 4200] (4600, 5000] (2600, 3000]
[316] (4200, 4600] (3800, 4200] (3400, 3800] (3400, 3800] (3400, 3800]
[321] (3400, 3800] (4200, 4600] (3000, 3400] (4200, 4600] (3000, 3400]
[326] (3400, 3800] (3000, 3400] (3800, 4200] (3400, 3800] (3800, 4200]
[331] (3000, 3400] (3400, 3800] (3000, 3400] (3800, 4200] (3400, 3800]
[336] (3400, 3800] (3800, 4200] (3400, 3800] (3400, 3800] (3800, 4200]
[341] (3000, 3400] (3400, 3800] (3800, 4200] (3400, 3800]
10 Levels: (2600, 3000] (3000, 3400] (3400, 3800] (3800, 4200] ... (6200, 6600]

$breaks
 [1] 2600 3000 3400 3800 4200 4600 5000 5400 5800 6200 6600

$mids
 [1] 2800 3200 3600 4000 4400 4800 5200 5600 6000 6400

$widths
 [1] 400 400 400 400 400 400 400 400 400 400

$counts
 [1] 11 47 83 52 42 46 27 25  8  1

$freq
 [1] 11/342 47/342 83/342 26/171   7/57 23/171   3/38 25/342  4/171  1/342

$density
 [1] 8.040936e-05 3.435673e-04 6.067251e-04 3.801170e-04 3.070175e-04
 [6] 3.362573e-04 1.973684e-04 1.827485e-04 5.847953e-05 7.309942e-06

Die Elemente breaks, mids, counts und density sind auch im Output der Funktion hist() enthalten. Daher können wir den Output mit dem von hist() vergleichen, um my_class() auf Fehler zu kontrollieren.

hist(penguins$body_mass_g, breaks = seq(2600,6600, 400), plot = FALSE)
$breaks
 [1] 2600 3000 3400 3800 4200 4600 5000 5400 5800 6200 6600

$counts
 [1] 11 47 83 52 42 46 27 25  8  1

$density
 [1] 8.040936e-05 3.435673e-04 6.067251e-04 3.801170e-04 3.070175e-04
 [6] 3.362573e-04 1.973684e-04 1.827485e-04 5.847953e-05 7.309942e-06

$mids
 [1] 2800 3200 3600 4000 4400 4800 5200 5600 6000 6400

$xname
[1] "penguins$body_mass_g"

$equidist
[1] TRUE

attr(,"class")
[1] "histogram"

hist() und my_class() stimmen in den Elementen breaks, mids, counts sowie density überein. Unsere Funktion macht also das, was wir gefordert haben.

Zurück zu Aufgabe 3

Autor:innen

Diese Lerneinheit “Deskriptive Statistik” wurde von Roland Fried und Christina Mathieu unter Mithilfe von Merle Mendel und Klemens Schmidt an der Technischen Universität Dortmund entwickelt. Es ist lizenziert unter der CC-BY-SA 4.0 Lizenz und ist verfügbar auf ORCA.nrw.

Literatur

Horst, Allison Marie, Alison Hill, und Kristen B. Gorman. 2020. palmerpenguins: Palmer Archipelago (Antarctica) penguin data. https://doi.org/10.5281/zenodo.3960218.

Fußnoten

  1. Weitere Informationen zum palmerpenguins Datensatz finden Sie auf https://allisonhorst.github.io/palmerpenguins.↩︎