<- data.frame(a = 1:3,
df b = c(TRUE, FALSE, TRUE),
c = c('a','b','c'))
df
a b c
1 1 TRUE a
2 2 FALSE b
3 3 TRUE c
Wie alle anderen Programme zur statistischen Auswertung hat R natürlich neben den Vektoren auch rechteckige Datenformate.
Das typische rechteckige Datenformat in base R
ist der data.frame
. Im Prinzip nichts anderes, als spaltenweise zusammengeklebte Vektoren. Der Konstruktor für ein solches Objekt ist die gleichnamige Funktion, die die Spalten als benannte Argumente nimmt:
<- data.frame(a = 1:3,
df b = c(TRUE, FALSE, TRUE),
c = c('a','b','c'))
df
a b c
1 1 TRUE a
2 2 FALSE b
3 3 TRUE c
Das Indizieren im Datensatz geht dann am lesbarsten, durch das Angeben der gewünschten Spalte mit dem $
-Operator und der Auswahl der Zeile durch den schon bekannten []
-Operator.
$c[2] ## 2. Wert in der 'c'-Spalte. df
[1] "b"
Wie könnte ich den 3. Wert in der b
-Spalte indizieren?
df$b[3]
Der iris
-Datensatz ist ein im Grundumfang von R mitgelieferter Datensatz, der historische botanische Daten nach Anderson (1935) enthält.
%>%
iris head()
Sepal.Length Sepal.Width Petal.Length
1 5.1 3.5 1.4
2 4.9 3.0 1.4
3 4.7 3.2 1.3
4 4.6 3.1 1.5
5 5.0 3.6 1.4
6 5.4 3.9 1.7
Petal.Width Species
1 0.2 setosa
2 0.2 setosa
3 0.2 setosa
4 0.2 setosa
5 0.2 setosa
6 0.4 setosa
Das ist natürlich ein bisschen unübersichtlich, wie kann man damit umgehen?
Wenn man iris explizit in das Environment nimmt, kann man die Oberfläche von RStudio nutze, um sich einen Überblick zu verschaffen 1
1 Dabei nutzt die RStudio-IDE aber nur die str()
(für structure)-Funktion.
<- iris iris
Die summary
-Funktion, die genau das macht, was ihr Name suggeriert:
summary(iris)
Sepal.Length Sepal.Width Petal.Length
Min. :4.300 Min. :2.000 Min. :1.000
1st Qu.:5.100 1st Qu.:2.800 1st Qu.:1.600
Median :5.800 Median :3.000 Median :4.350
Mean :5.843 Mean :3.057 Mean :3.758
3rd Qu.:6.400 3rd Qu.:3.300 3rd Qu.:5.100
Max. :7.900 Max. :4.400 Max. :6.900
Petal.Width Species
Min. :0.100 setosa :50
1st Qu.:0.300 versicolor:50
Median :1.300 virginica :50
Mean :1.199
3rd Qu.:1.800
Max. :2.500
Wir wollen für diesen Datensatz jetzt die folgenden Schritte der Auswertung vollziehen:
Ausschluss der Blumen, die breitere Blütenblätter als das 1.5-fache der mittleren Blütenblätter haben und Kelche, die kürzer als das Mittel der Kelchlänge sind
Darstellung der Mittelwerte und Streuungen der Blütenblattlänge und -breite pro verbleibende Spezies als Tabelle
<- iris[iris$Petal.Width <= 1.5 * mean(iris$Petal.Width) &
df $Sepal.Length >= mean(iris$Sepal.Length),]
iris<- aggregate(cbind(df$Petal.Length,df$Petal.Width),
means by = list(Species = df$Species),
FUN = mean)
<- aggregate(cbind(df$Petal.Length,df$Petal.Width),
sds by = list(Species = df$Species),
FUN = sd)
<- data.frame(means, sds[,2:3])
tab names(tab)[2:5] = c('m_Length', 'm_Width', 'sd_Length', 'sd_Width')
tab
Species m_Length m_Width sd_Length
1 versicolor 4.560 1.424 0.2783882
2 virginica 5.375 1.500 0.3862210
sd_Width
1 0.14798649
2 0.08164966
Die selbe Aufgabe wie gerade, jetzt mit dem tidyverse
:
library(tidyverse)
%>%
iris filter(Petal.Width <= 1.5 * mean(Petal.Width) &
>= mean(Sepal.Length)) %>%
Sepal.Length group_by(Species) %>%
summarise(m_Length = mean(Petal.Length),
sd_Length = sd(Petal.Length),
m_Width = mean(Petal.Width),
sd_Width = sd(Petal.Width))
# A tibble: 2 × 5
Species m_Length sd_Length m_Width sd_Width
<fct> <dbl> <dbl> <dbl> <dbl>
1 versicolor 4.56 0.278 1.42 0.148
2 virginica 5.38 0.386 1.5 0.0816
Das tidyverse
(Wickham et al., 2019) ist eine Sammlung von Paketen, deren Hauptziel es ist, Datenaufbereitung in R intuitiver und leichter lesbar zu machen.
Ein zentrales Element dabei ist der %>%
-Operator, die sogenannte Pipeline2. Beim Skript-Lesen und -Schreiben kann man sich diese am Besten als ‘dann’ vorstellen
2 base
-R hat mit Version 4.1 auch eine native pipe eingeführt (|>
), da wir aber eh das tidyverse nutzen bleiben wir bei der magrittr
-pipe
Mit ihrer Hilfe werden Aufbereitungsschritte in einer stringenten Reihe an Operationen formuliert, die sich am Besten als Satz verstehen lassen.
Da die Funktionen im tidyverse alle mit einfachen Verben benannt sind, lässt sich die Operation von eben auch so lesen.
1library(tidyverse)
2%>%
iris 3filter(Petal.Width <= 1.5 * mean(Petal.Width) &
>= mean(Sepal.Length)) %>%
Sepal.Length 4group_by(Species) %>%
5summarise(m_Length = mean(Petal.Length),
sd_Length = sd(Petal.Length),
m_Width = mean(Petal.Width),
sd_Width = sd(Petal.Width))
tidyverse
geladen werden
iris
, dann …
Zweite Beispielaufgabe:
Wir möchten für den iris
-Datensatz:
Eine Spalte hinzufügen, die die z-transformierte Blattlänge enthält
Eine Spalte hinzufügen, die als character das Ergebnis eines Mediansplits der gerade erstellten Variable enthält
Einen Datensatz erstellen, der nur die Spezies, die z-Transformierte und die Mediansplit-Variable enthält
Die Häufigkeiten der Kombinationen von Mediansplit-Gruppe und Spezies auszählen
1<- iris %>%
df 2mutate(
3z_length = (Petal.Length-mean(Petal.Length))/sd(Petal.Length),
4med_split = case_when(
5>= median(z_length) ~ 'upper',
z_length 6~ 'lower')) %>%
T 7select(Species, z_length, med_split)
df
. Nimm dazu iris
, dann …
case_when
eine Spalte anlegst, die …
Species
, z_length
und med_split
aus.
Hat das geklappt?
Wie könnte ich das überprüfen?
summary(df)
Species z_length
setosa :50 Min. :-1.5623
versicolor:50 1st Qu.:-1.2225
virginica :50 Median : 0.3354
Mean : 0.0000
3rd Qu.: 0.7602
Max. : 1.7799
med_split
Length:150
Class :character
Mode :character
Jetzt noch Häufigkeiten auszählen:
df
, dann …
Species
und med_split
, dann…
`summarise()` has grouped output by 'Species'.
You can override using the `.groups` argument.
# A tibble: 4 × 3
# Groups: Species [3]
Species med_split n
<fct> <chr> <int>
1 setosa lower 50
2 versicolor lower 25
3 versicolor upper 25
4 virginica upper 50
Machen Sie sich mit dem swiss
-Datensatz vertraut. Lesen Sie dazu auch die Hilfeseite zu dem Datensatz, diese können Sie mit ?swiss
aufrufen. Erstellen Sie mit Hilfe einer pipeline einen Datensatz, der…
nur Provinzen enthält, deren Einwohner zu mehr als 10% und weniger als 35% Bestnoten bei der Armee-Untersuchung erhalten haben
nur den Anteil der männlichen Population in der Landwirtschaft, die Kindersterblichkeit, das Bildungsniveau und den Anteil der katholischen Familien enthält
eine numerische Variable enthält, die für die so ausgewählten Fälle einen Mediansplit der Kindersterblichkeit codiert.
eine Variable enthält, die angibt, ob der Anteil der männlichen Population an der Landwirtschaft über oder unter dem Mittelwert (mean
) liegt
Lassen Sie sich die absoluten Häufigkeiten der Kombination der beiden gerade erstellten Variablen ausgeben.
Zusatz: Erstellen Sie anschließend eine kurze pipeline, die den gerade erstellten Datensatz mit dem Absteigenden Bildungsniveau als ersten Sortierschlüssel und dem aufsteigenden Anteil katholischer Familien als zweitem Schlüssel sortiert. Nutzen Sie dafür die Hilfeseite der arrange
-Funktion.
library(tidyverse)
<- swiss %>%
df filter(Education > 10,
< 35) %>%
Education select(Agriculture,
Infant.Mortality,
Education,%>%
Catholic) mutate(
mediansplit_mortality = case_when(
>= median(Infant.Mortality) ~ 1,
Infant.Mortality ~ -1),
T meansplit_agriculture = case_when(
> mean(Agriculture) ~ 'high',
Agriculture < mean(Agriculture) ~ 'low',
Agriculture ~ 'mean'
T
)
)
%>%
df count(mediansplit_mortality,meansplit_agriculture)
mediansplit_mortality meansplit_agriculture n
1 -1 high 4
2 -1 low 4
3 1 high 4
4 1 low 4
<- df %>%
df2 arrange(-Education,
Catholic)