26  Schritt 3: Umgang mit Datensätzen

Das Paket dplyr bietet zahlreiche Funktionen, die den Umgang mit Datensätzen erleichtern.

26.1 Daten filtern und sortieren

Mit der Funktion filter() kann der Datensatz nach Kriterien gefiltert werden. Beachten Sie, dass die Funktion mit stats::filter() kollidiert. Rufen Sie sie daher sicherheitshalber mit dplyr::filter() auf.

pf8 %>% 
    # Nur Daten von Personen jünger 40
    dplyr::filter(Alter<40) %>% 
      glimpse()
## Rows: 443
## Columns: 16
## $ Standort       <fct> Münster, Münster, Münster, Münster, Münster, Münster, M…
## $ Alter          <int> 18, 24, 21, 22, 19, 18, 17, 21, 28, 19, 21, 28, 26, 21,…
## $ Geschlecht     <fct> weiblich, männlich, weiblich, männlich, weiblich, weibl…
## $ Größe          <int> 172, 173, 177, 206, 163, 172, 158, 163, 181, 175, 186, …
## $ Gewicht        <dbl> 69, 68, 60, 130, 52, 68, 48, 54, 70, 65, 70, 85, 60, 65…
## $ Bildung        <fct> Abitur, Abitur, Abitur, Fachabitur, Abitur, mittlere Re…
## $ Beruf          <fct> Inspektor*in, Student*in, Student*in, Kaufmann/frau, St…
## $ Familienstand  <fct> Partnerschaft, ledig, Partnerschaft, ledig, ledig, ledi…
## $ Kinder         <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
## $ Wohnort        <fct> ländlich, städtisch, städtisch, ländlich, städtisch, st…
## $ Rauchen        <fct> nein, nein, ja, nein, nein, nein, nein, nein, nein, nei…
## $ SportHäufig    <dbl> NA, 4.0, 1.0, 4.0, 5.0, 2.5, 1.0, 4.0, NA, 0.5, 1.0, 5.…
## $ SportMinuten   <dbl> NA, 60, 60, 90, 20, 120, 120, 80, NA, 120, 60, 50, 30, …
## $ SportWie       <fct> Allein, Allein, Gruppe, Gruppe, Allein, Gruppe, Gruppe,…
## $ SportWarum     <fct> Arbeitsweg, Gewichtsreduktion, Fitness, Fitness, Vorbeu…
## $ LebenZufrieden <dbl> 5, 9, 8, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 9, 8, 8, 6, 7, 8…

Die Kriterien können auch kombiniert werden.

pf8 %>% 
  dplyr::filter(Alter>20 , Geschlecht == "weiblich", Bildung=="Abitur") %>% 
      glimpse()
## Rows: 56
## Columns: 16
## $ Standort       <fct> Münster, Münster, Münster, Bahn, Bahn, Rheine, Rheine, …
## $ Alter          <int> 21, 21, 21, 21, 21, 22, 23, 22, 30, 52, 45, 23, 49, 41,…
## $ Geschlecht     <fct> weiblich, weiblich, weiblich, weiblich, weiblich, weibl…
## $ Größe          <int> 177, 163, 175, 170, 170, 170, 168, 163, 173, 174, 168, …
## $ Gewicht        <dbl> 60, 54, 61, 58, 80, 59, 70, 63, 71, 72, 70, 56, 70, 49,…
## $ Bildung        <fct> Abitur, Abitur, Abitur, Abitur, Abitur, Abitur, Abitur,…
## $ Beruf          <fct> Student*in, Student*in, Student*in, Student*in, Student…
## $ Familienstand  <fct> Partnerschaft, Partnerschaft, Partnerschaft, NA, ledig,…
## $ Kinder         <int> 0, 0, 0, NA, 0, 0, 0, 0, 0, 1, 2, 0, 2, 0, 3, 2, 0, 1, …
## $ Wohnort        <fct> städtisch, städtisch, städtisch, ländlich, ländlich, st…
## $ Rauchen        <fct> ja, nein, nein, nein, nein, nein, nein, nein, nein, nei…
## $ SportHäufig    <dbl> 1.0, 4.0, 3.0, 5.0, 1.0, 1.0, 2.0, 4.0, 3.0, 4.0, 1.0, …
## $ SportMinuten   <dbl> 60, 80, 60, 75, 60, 90, 45, 60, 60, 20, 60, 90, 30, 120…
## $ SportWie       <fct> Gruppe, beides, Gruppe, Allein, Allein, Allein, beides,…
## $ SportWarum     <fct> Fitness, Vorbeugung, Fitness, Fitness, Fitness, Gewicht…
## $ LebenZufrieden <dbl> 8, 8, 8, 9, 8, 8, 10, 8, 7, 6, 7, 8, 7, 7, 7, 7, 8, 8, …

Beachten Sie, dass wir doppelte Gleichheitszeichen (==) verwenden müssen, da mit einem Gleichheitszeichen (=) Variablen zugewiesen werden (so wie mit <-).

Möchte man nach mehreren bestimmten Werte filtern, kann der %in% Operator verwendet werden. Hierdurch übergeben Sie einen Vektor an möglichen Ausprägungen. Angenommen, Sie möchten nur solche Fälle auswählen, in denen das Alter 20 oder 25 oder 40 Jahre beträgt, lautet der Aufruf:

# nach mehreren Werten filtern
# Suche Fälle, die 20 oder 25 oder 40 Jahre alt sind
pf8 %>% 
  dplyr::filter(Alter %in% c(20, 25, 40)) %>% 
  head(10)
##    Standort Alter Geschlecht Größe Gewicht     Bildung
## 1   Münster    25   männlich   182    75.0  Ausbildung
## 2      Bahn    25   männlich   180    72.0  Hochschule
## 3    Rheine    25   weiblich   168    75.0  Hochschule
## 4    Rheine    40   weiblich   163    68.0 Hauptschule
## 5    Rheine    20   weiblich   158    70.0 Hauptschule
## 6    Rheine    20   weiblich   170    85.0  Hochschule
## 7    Rheine    20   weiblich   170    65.0      Abitur
## 8    Rheine    20   weiblich   160    48.5      Abitur
## 9    Rheine    25   männlich   186    70.0  Hochschule
## 10     Bahn    40   weiblich   181    64.0  Hochschule
##                           Beruf Familienstand Kinder   Wohnort Rauchen
## 1                    Finanzwirt         ledig      0 städtisch    nein
## 2  Kaufmann/frau + Betriebswirt         ledig      0  ländlich    nein
## 3                    Student*in         ledig      0 städtisch      ja
## 4                 Angestellte*r         ledig      2 städtisch    nein
## 5                    Schüler*in         ledig      0  ländlich    nein
## 6                         Azubi         ledig      3  ländlich    nein
## 7                         Azubi         ledig      0  ländlich    nein
## 8                    Student*in         ledig      0  ländlich    nein
## 9                    Student*in         ledig      0 städtisch    nein
## 10                Angestellte*r   verheiratet      2 städtisch    nein
##    SportHäufig SportMinuten SportWie        SportWarum LebenZufrieden
## 1          2.0           90   Allein           Fitness              8
## 2          4.0           30   Allein           Fitness              9
## 3          2.0           20   Allein           Fitness              9
## 4           NA           NA     <NA>              <NA>              6
## 5          3.0           60   Allein Gewichtsreduktion              7
## 6          2.0          120   Gruppe        Vorbeugung              8
## 7          5.0          120   beides           Fitness              7
## 8          3.0           60   Allein           Fitness              7
## 9          3.0           30   Allein        Vorbeugung              9
## 10         1.5           60   Gruppe        Vorbeugung              7

Über den Operator != können Fälle ausgeschlossen werden. Wir schließen für dieses Beispiel alle Fälle aus, die verheiratet sind:

# schließe alle verheirateten Fälle aus
pf8 %>% 
  dplyr::filter(Familienstand != "verheiratet") %>% 
  head(10)
##    Standort Alter Geschlecht Größe Gewicht        Bildung            Beruf
## 1   Münster    18   weiblich   172      69         Abitur     Inspektor*in
## 2   Münster    67   weiblich   165      67 mittlere Reife       Rentner*in
## 3   Münster    60   weiblich   175      NA     Hochschule Ergotherapeut*in
## 4   Münster    61   männlich   182      90 mittlere Reife       Beamter*in
## 5   Münster    24   männlich   173      68         Abitur       Student*in
## 6   Münster    21   weiblich   177      60         Abitur       Student*in
## 7   Münster    56   weiblich   156      60     Ausbildung  Pflegehelfer*in
## 8   Münster    22   männlich   206     130     Fachabitur    Kaufmann/frau
## 9   Münster    19   weiblich   163      52         Abitur       Student*in
## 10  Münster    18   weiblich   172      68 mittlere Reife       Schüler*in
##    Familienstand Kinder   Wohnort Rauchen SportHäufig SportMinuten SportWie
## 1  Partnerschaft      0  ländlich    nein          NA           NA   Allein
## 2     geschieden      0  ländlich    nein         2.0           60   Gruppe
## 3  Partnerschaft      0 städtisch    nein         2.0           45   beides
## 4          ledig      0  ländlich    nein         4.0          120   Allein
## 5          ledig      0 städtisch    nein         4.0           60   Allein
## 6  Partnerschaft      0 städtisch      ja         1.0           60   Gruppe
## 7     geschieden      2 städtisch      ja         1.0           90   beides
## 8          ledig      0  ländlich    nein         4.0           90   Gruppe
## 9          ledig      0 städtisch    nein         5.0           20   Allein
## 10         ledig      0 städtisch    nein         2.5          120   Gruppe
##           SportWarum LebenZufrieden
## 1         Arbeitsweg              5
## 2         Vorbeugung              7
## 3         Vorbeugung              7
## 4            Fitness              2
## 5  Gewichtsreduktion              9
## 6            Fitness              8
## 7         Vorbeugung              8
## 8            Fitness              8
## 9         Vorbeugung              7
## 10 Gewichtsreduktion              8

Mit der Funktion arrange() können die Daten sortiert werden. Dabei wird standardmäßig aufsteigend sortiert.

# sortiere Datensatz "pf8"
pf8 %>% 
  arrange(Alter, Größe, Gewicht) %>% 
     head(.)
##   Standort Alter Geschlecht Größe Gewicht        Bildung      Beruf
## 1 Internet    15   weiblich   165    51.6           <NA>           
## 2  Münster    17   weiblich   158    48.0 mittlere Reife Schüler*in
## 3 Internet    17   weiblich   160    75.0           <NA>           
## 4 Internet    17   weiblich   163    57.0           <NA>           
## 5 Internet    17   weiblich   168    59.0           <NA>           
## 6 Internet    17   weiblich   175    80.0           <NA>           
##   Familienstand Kinder   Wohnort Rauchen SportHäufig SportMinuten SportWie
## 1 Partnerschaft      5 städtisch    nein           6           60   Allein
## 2         ledig      0 städtisch    nein           1          120   Gruppe
## 3 Partnerschaft      0  ländlich    nein           2           60   Gruppe
## 4 Partnerschaft      0  ländlich    nein           2           70   Allein
## 5         ledig      0 städtisch    nein           3          120   Allein
## 6         ledig      0 städtisch    nein          NA           30   Allein
##   SportWarum LebenZufrieden
## 1       <NA>              7
## 2  Beruflich              7
## 3       <NA>              8
## 4       <NA>              5
## 5       <NA>              7
## 6       <NA>              8

Die Daten werden zunächst aufsteigend nach Alter sortiert. Gibt es Fälle mit dem selben Alter, wird nach dem zweiten Kriterium (in diesem Falle Größe) sortiert. Gibt es Fälle mit der selben Größe und dem selben Alter, wird in- nerhalb dieser Gruppe nach Gewicht sortiert.

Für eine absteigende Sortierung muss die Funktion desc() verwendet werden.

# sortiere Datensatz "pf8"
# diesmal absteigend
pf8 %>% 
  arrange(desc(Alter), desc(Größe), desc(Gewicht)) %>% 
     head(.)
##    Standort Alter Geschlecht Größe Gewicht     Bildung        Beruf
## 1   Münster    86   weiblich   162      70 Hauptschule   Rentner*in
## 2    Rheine    86   weiblich   160      60      Abitur  Postbote*in
## 3    Rheine    84   weiblich   164      70 Hauptschule Verkäufer*in
## 4    Rheine    84   weiblich   160      60 Hauptschule   Rentner*in
## 5 Ladbergen    83   männlich   182      88 Hauptschule  Rentener*in
## 6   Münster    83       <NA>   165     175        <NA>   Rentner*in
##   Familienstand Kinder   Wohnort Rauchen SportHäufig SportMinuten SportWie
## 1     verwitwet      0  ländlich    nein           2           45   Gruppe
## 2     verwitwet      1 städtisch    nein           2           45   Gruppe
## 3     verwitwet      0 städtisch    nein          NA           NA     <NA>
## 4     verwitwet      0 städtisch    nein           2           60   Allein
## 5   verheiratet      0  ländlich      ja           5           60   Gruppe
## 6         ledig      0 städtisch    nein          NA           25   Allein
##   SportWarum LebenZufrieden
## 1    Fitness              7
## 2   Freizeit              8
## 3       <NA>              5
## 4    Fitness              8
## 5 Vorbeugung              5
## 6 Vorbeugung              4

26.2 Fälle auswählen

Mit der Funktion slice() können gewünschte Datenreihen (Fälle) ausgegeben werden.

pf8 %>% 
  # zeige Fälle (Reihen) 98 bis 105
  slice(98:105) %>% 
    glimpse()
## Rows: 8
## Columns: 16
## $ Standort       <fct> Rheine, Rheine, Rheine, Rheine, Rheine, Rheine, Rheine,…
## $ Alter          <int> 23, 30, 26, 35, 22, 50, 35, 22
## $ Geschlecht     <fct> männlich, weiblich, männlich, männlich, männlich, männl…
## $ Größe          <int> 194, 173, 189, 184, 181, 204, 172, 175
## $ Gewicht        <dbl> 110, 71, 89, 79, 92, 102, 86, 75
## $ Bildung        <fct> Abitur, Abitur, Hauptschule, mittlere Reife, mittlere R…
## $ Beruf          <fct> Außendienst, Innendienst, Angestellte*r,  Produktionsle…
## $ Familienstand  <fct> Partnerschaft, verheiratet, Partnerschaft, verheiratet,…
## $ Kinder         <int> 0, 0, 0, 3, 0, 1, 2, 0
## $ Wohnort        <fct> ländlich, ländlich, städtisch, ländlich, ländlich, länd…
## $ Rauchen        <fct> ja, nein, ja, ja, nein, nein, ja, nein
## $ SportHäufig    <dbl> 1, 3, 1, 3, 2, 4, 1, 0
## $ SportMinuten   <dbl> 30, 60, 60, 90, 30, 30, 60, 0
## $ SportWie       <fct> Allein, Allein, Gruppe, Gruppe, Gruppe, beides, Gruppe,…
## $ SportWarum     <fct> Fitness, Fitness, Freizeit, Fitness, Fitness, Vorbeugun…
## $ LebenZufrieden <dbl> 9, 7, 6, 6, 7, 8, 7, 7

Mit slice_min() und slice_max() können die kleinsten und größten Werte eingesehen werden.

pf8 %>% 
  # zeige die leichtesten Gewichte
  slice_min(Gewicht)%>% 
      glimpse()
## Rows: 5
## Columns: 16
## $ Standort       <fct> Münster, Münster, Münster, Internet, Internet
## $ Alter          <int> 26, 24, 24, 24, 19
## $ Geschlecht     <fct> männlich, weiblich, weiblich, weiblich, weiblich
## $ Größe          <int> 180, 164, 160, 159, 155
## $ Gewicht        <dbl> 45, 45, 45, 45, 45
## $ Bildung        <fct> Hauptschule, Abitur, Abitur, NA, NA
## $ Beruf          <fct> Kaufmann/frau, Student*in, Student*in, , 
## $ Familienstand  <fct> ledig, Partnerschaft, Partnerschaft, Partnerschaft, led…
## $ Kinder         <int> 0, 0, 0, 0, 0
## $ Wohnort        <fct> ländlich, städtisch, städtisch, ländlich, städtisch
## $ Rauchen        <fct> ja, nein, nein, nein, nein
## $ SportHäufig    <dbl> NA, 2.0, 3.0, 4.0, 2.5
## $ SportMinuten   <dbl> NA, 60, 60, 60, 90
## $ SportWie       <fct> NA, Gruppe, Allein, Allein, Allein
## $ SportWarum     <fct> NA, Vorbeugung, Vorbeugung, NA, NA
## $ LebenZufrieden <dbl> 10, 8, 9, 10, 9

Die Tabelle wird nach Gewicht sortiert ausgegeben. Im Datensatz pf8 haben insgesamt 5 Fälle das kleinste Gewicht.

Der Parameter n gibt an, wieviele “Stufen” gezählt werden sollen, also z.B. der kleinste (n=1) oder auch der zweit-kleinste Wert (n=2) usw..

Intern zählt n allerdings mit, wieviele Fälle (Reihen) bereits ausgegeben wurde. Das ist am Anfang etwas un-intuitiv.

pf8 %>% 
  # zeigen die leichtesten Gewichte
  slice_min(Gewicht, n=3)%>% 
      glimpse()
## Rows: 5
## Columns: 16
## $ Standort       <fct> Münster, Münster, Münster, Internet, Internet
## $ Alter          <int> 26, 24, 24, 24, 19
## $ Geschlecht     <fct> männlich, weiblich, weiblich, weiblich, weiblich
## $ Größe          <int> 180, 164, 160, 159, 155
## $ Gewicht        <dbl> 45, 45, 45, 45, 45
## $ Bildung        <fct> Hauptschule, Abitur, Abitur, NA, NA
## $ Beruf          <fct> Kaufmann/frau, Student*in, Student*in, , 
## $ Familienstand  <fct> ledig, Partnerschaft, Partnerschaft, Partnerschaft, led…
## $ Kinder         <int> 0, 0, 0, 0, 0
## $ Wohnort        <fct> ländlich, städtisch, städtisch, ländlich, städtisch
## $ Rauchen        <fct> ja, nein, nein, nein, nein
## $ SportHäufig    <dbl> NA, 2.0, 3.0, 4.0, 2.5
## $ SportMinuten   <dbl> NA, 60, 60, 60, 90
## $ SportWie       <fct> NA, Gruppe, Allein, Allein, Allein
## $ SportWarum     <fct> NA, Vorbeugung, Vorbeugung, NA, NA
## $ LebenZufrieden <dbl> 10, 8, 9, 10, 9

Das Ergebnis ist evtl. anders, als Sie es erwarten. Es werden weiterhin 5 Fälle angezeigt, obwohl n auf 3 gesetzt wurde. Das liegt daran, dass 5 Fälle das kleinste Gewicht haben, und diese werden vollständig angezeigt. Intern ist n dabei auf 5 angewachsen, weshalb keine zweit-kleinsten Gewichte mehr ausgegeben werden.

Lassen wir uns die Älteste Probanden auswählen.

pf8 %>% 
  # zeige die ältesten 
  slice_max(Alter, n=2) %>% 
      glimpse()
## Rows: 2
## Columns: 16
## $ Standort       <fct> Münster, Rheine
## $ Alter          <int> 86, 86
## $ Geschlecht     <fct> weiblich, weiblich
## $ Größe          <int> 162, 160
## $ Gewicht        <dbl> 70, 60
## $ Bildung        <fct> Hauptschule, Abitur
## $ Beruf          <fct> Rentner*in, Postbote*in
## $ Familienstand  <fct> verwitwet, verwitwet
## $ Kinder         <int> 0, 1
## $ Wohnort        <fct> ländlich, städtisch
## $ Rauchen        <fct> nein, nein
## $ SportHäufig    <dbl> 2, 2
## $ SportMinuten   <dbl> 45, 45
## $ SportWie       <fct> Gruppe, Gruppe
## $ SportWarum     <fct> Fitness, Freizeit
## $ LebenZufrieden <dbl> 7, 8

Die Tabelle besteht zwar aus 2 Fällen, aber beide Fälle haben das selbe Alter. Die zweit-ältesten werden nicht mit angezeigt, da n intern bereits auf 2 angewachsen ist.

Wir eröhen n auf 3:

pf8 %>% 
  # zeige die ältesten 
  slice_max(Alter, n=3)%>% 
      glimpse()
## Rows: 4
## Columns: 16
## $ Standort       <fct> Münster, Rheine, Rheine, Rheine
## $ Alter          <int> 86, 86, 84, 84
## $ Geschlecht     <fct> weiblich, weiblich, weiblich, weiblich
## $ Größe          <int> 162, 160, 160, 164
## $ Gewicht        <dbl> 70, 60, 60, 70
## $ Bildung        <fct> Hauptschule, Abitur, Hauptschule, Hauptschule
## $ Beruf          <fct> Rentner*in, Postbote*in, Rentner*in, Verkäufer*in
## $ Familienstand  <fct> verwitwet, verwitwet, verwitwet, verwitwet
## $ Kinder         <int> 0, 1, 0, 0
## $ Wohnort        <fct> ländlich, städtisch, städtisch, städtisch
## $ Rauchen        <fct> nein, nein, nein, nein
## $ SportHäufig    <dbl> 2, 2, 2, NA
## $ SportMinuten   <dbl> 45, 45, 60, NA
## $ SportWie       <fct> Gruppe, Gruppe, Allein, NA
## $ SportWarum     <fct> Fitness, Freizeit, Fitness, NA
## $ LebenZufrieden <dbl> 7, 8, 8, 5

Jetzt haben wir insgesamt 4 Fälle. Es werden zuerst die ältesten angezeigt. Da es 2 Fälle sind, steigt n intern auf 2 an. Da wir n mit 3 aufgerufen haben, ist noch “Platz” für die zweit-ältesten. Da dies ebenfalls 2 Fälle sind, werden beide ausgegeben. Insgesamt sehen wir also 4 Fälle, obwohl wir n mit 3 aufgerufen haben.

Ähnlich wie head() und tail() zeigen slice_head() und slice_tail() die ersten bzw. letzten Fälle an.

# zeige die ersten 5 Fälle
pf8 %>% slice_head(n=5)
##   Standort Alter Geschlecht Größe Gewicht        Bildung            Beruf
## 1  Münster    18   weiblich   172      69         Abitur     Inspektor*in
## 2  Münster    67   weiblich   165      67 mittlere Reife       Rentner*in
## 3  Münster    60   weiblich   175      NA     Hochschule Ergotherapeut*in
## 4  Münster    61   männlich   182      90 mittlere Reife       Beamter*in
## 5  Münster    24   männlich   173      68         Abitur       Student*in
##   Familienstand Kinder   Wohnort Rauchen SportHäufig SportMinuten SportWie
## 1 Partnerschaft      0  ländlich    nein          NA           NA   Allein
## 2    geschieden      0  ländlich    nein           2           60   Gruppe
## 3 Partnerschaft      0 städtisch    nein           2           45   beides
## 4         ledig      0  ländlich    nein           4          120   Allein
## 5         ledig      0 städtisch    nein           4           60   Allein
##          SportWarum LebenZufrieden
## 1        Arbeitsweg              5
## 2        Vorbeugung              7
## 3        Vorbeugung              7
## 4           Fitness              2
## 5 Gewichtsreduktion              9
# zeige die letzten 2 Fälle
pf8 %>% slice_tail(n=2)
##   Standort Alter Geschlecht Größe Gewicht Bildung Beruf Familienstand Kinder
## 1 Internet    20   weiblich   168      58    <NA>               ledig      0
## 2 Internet    40   männlich   183      78    <NA>         verheiratet      2
##     Wohnort Rauchen SportHäufig SportMinuten SportWie SportWarum LebenZufrieden
## 1 städtisch    nein         1.0           60   Allein       <NA>              8
## 2 städtisch      ja         2.5          120   Gruppe       <NA>             10

Mit slice_sample() können zufällig Fälle aus dem Datensatz gezogen werden.

# ziehe zufällig 7 Fälle
pf8 %>% slice_sample(n=7)
##    Standort Alter Geschlecht Größe Gewicht        Bildung             Beruf
## 1    Rheine    74   männlich   175      84 mittlere Reife           Koch*in
## 2   Münster    74   weiblich   176      80    Hauptschule        Rentner*in
## 3 Ladbergen    24   weiblich   168      63         Abitur             Azubi
## 4    Rheine    19   männlich   186      88    Hauptschule            Pflege
## 5   Münster    63   weiblich   168      63     Hochschule         Lehrer*in
## 6  Internet    31   männlich   177      68           <NA>                  
## 7 Ladbergen    59   weiblich   167      63 mittlere Reife Sozialarbeiter*in
##   Familienstand Kinder   Wohnort Rauchen SportHäufig SportMinuten SportWie
## 1         ledig      0 städtisch    nein          NA           NA     <NA>
## 2   verheiratet      0  ländlich    nein           1           60   Gruppe
## 3 Partnerschaft      0 städtisch      ja           5           15   Allein
## 4 Partnerschaft      0  ländlich      ja           3           90   Gruppe
## 5     verwitwet      1 städtisch    nein           2           30   Allein
## 6 Partnerschaft      0 städtisch    nein           5           60   Allein
## 7         ledig      0 städtisch      ja           3           60   beides
##   SportWarum LebenZufrieden
## 1       <NA>              8
## 2    Fitness             NA
## 3    Fitness              6
## 4 Vorbeugung             10
## 5    Fitness              9
## 6       <NA>             10
## 7 Vorbeugung              8

Mit der Funktion group_by() können Gruppierungen vorgenommen werden.

In Kombination mit group_by() zeigen die slice()-Funktionen die jeweilige Auswahl an Fällen pro Gruppe.

pf8 %>%
  drop_na() %>% 
  # Gruppiere nach Geschlecht
  group_by(Geschlecht) %>% 
  #  zeige
  slice(1)
## # A tibble: 3 × 16
## # Groups:   Geschlecht [3]
##   Standort Alter Geschlecht Größe Gewicht Bildung   Beruf Famil…¹ Kinder Wohnort
##   <fct>    <int> <fct>      <int>   <dbl> <fct>     <fct> <fct>    <int> <fct>  
## 1 Münster     61 männlich     182      90 mittlere… Beam… ledig        0 ländli…
## 2 Münster     67 weiblich     165      67 mittlere… Rent… geschi…      0 ländli…
## 3 Rheine      32 divers       186      92 Hochschu… Sozi… verhei…      0 städti…
## # … with 6 more variables: Rauchen <fct>, SportHäufig <dbl>,
## #   SportMinuten <dbl>, SportWie <fct>, SportWarum <fct>, LebenZufrieden <dbl>,
## #   and abbreviated variable name ¹​Familienstand
pf8 %>%
  drop_na() %>% 
  # Gruppiere nach Geschlecht
  group_by(Geschlecht) %>% 
  # sortiere nach Alter
  arrange(desc(Alter)) %>% 
  #  zeige die ersten 3 Fälle pro Gruppe
  slice(1:3)
## # A tibble: 7 × 16
## # Groups:   Geschlecht [3]
##   Standort  Alter Geschlecht Größe Gewicht Bildung  Beruf Famil…¹ Kinder Wohnort
##   <fct>     <int> <fct>      <int>   <dbl> <fct>    <fct> <fct>    <int> <fct>  
## 1 Ladbergen    83 männlich     182    88   Hauptsc… Rent… verhei…      0 ländli…
## 2 Münster      78 männlich     178    71.5 Hochsch… Lehr… verhei…      0 städti…
## 3 Bahn         76 männlich     180    90   Hochsch… Arzt… verhei…      0 städti…
## 4 Münster      86 weiblich     162    70   Hauptsc… Rent… verwit…      0 ländli…
## 5 Rheine       86 weiblich     160    60   Abitur   Post… verwit…      1 städti…
## 6 Rheine       84 weiblich     160    60   Hauptsc… Rent… verwit…      0 städti…
## # … with 1 more row, 6 more variables: Rauchen <fct>, SportHäufig <dbl>,
## #   SportMinuten <dbl>, SportWie <fct>, SportWarum <fct>, LebenZufrieden <dbl>,
## #   and abbreviated variable name ¹​Familienstand

Innerhalb der Gruppierungen kann auch gefiltert werden.

pf8 %>% 
  # gruppiere nach Standort
  group_by(Geschlecht) %>% 
  # filtere "divers"
  dplyr::filter(Geschlecht != "divers") %>% 
  # filtere "Internet"
  dplyr::filter(Standort != "Internet") %>% 
  # sortiere nach "Gewicht"
  arrange(desc(Gewicht)) %>% 
  #  zeige die ersten 2 Fälle pro Gruppe
  slice(1,2)
## # A tibble: 4 × 16
## # Groups:   Geschlecht [2]
##   Standort Alter Geschlecht Größe Gewicht Bildung   Beruf Famil…¹ Kinder Wohnort
##   <fct>    <int> <fct>      <int>   <dbl> <fct>     <fct> <fct>    <int> <fct>  
## 1 Münster     22 männlich     206     130 Fachabit… Kauf… ledig        0 ländli…
## 2 Bahn        31 männlich     184     130 Fachabit… Scha… Partne…      0 städti…
## 3 Münster     40 weiblich     171     122 Hochschu… Pres… Partne…      0 städti…
## 4 Rheine      45 weiblich     168     120 mittlere… kauf… geschi…      1 ländli…
## # … with 6 more variables: Rauchen <fct>, SportHäufig <dbl>,
## #   SportMinuten <dbl>, SportWie <fct>, SportWarum <fct>, LebenZufrieden <dbl>,
## #   and abbreviated variable name ¹​Familienstand
pf8 %>% 
  group_by(Standort) %>% 
  dplyr::filter(Familienstand == "ledig" & Geschlecht == "männlich") %>% 
  arrange(desc(Alter)) %>% 
  head()
## # A tibble: 6 × 16
## # Groups:   Standort [2]
##   Standort Alter Geschlecht Größe Gewicht Bildung   Beruf Famil…¹ Kinder Wohnort
##   <fct>    <int> <fct>      <int>   <dbl> <fct>     <fct> <fct>    <int> <fct>  
## 1 Rheine      81 männlich     179      79 Hauptsch… "Han… ledig        0 ländli…
## 2 Rheine      74 männlich     175      84 mittlere… "Koc… ledig        0 städti…
## 3 Münster     72 männlich     175      86 mittlere… "Sic… ledig        0 städti…
## 4 Münster     69 männlich     179      89 mittlere… "Ren… ledig        0 städti…
## 5 Münster     61 männlich     182      90 mittlere… "Bea… ledig        0 ländli…
## 6 Rheine      59 männlich     175      70 Abitur    ""    ledig        1 städti…
## # … with 6 more variables: Rauchen <fct>, SportHäufig <dbl>,
## #   SportMinuten <dbl>, SportWie <fct>, SportWarum <fct>, LebenZufrieden <dbl>,
## #   and abbreviated variable name ¹​Familienstand

26.3 Variablen hinzufügen

Variablen können mit der Funktion bind_cols() hinzugefügt werden. Dabei muss die Länge der enthaltenen Werte mit der Länge des tibble übereinstimmen, ansonsten wiederholt R die Wertereihe so lange, bis sie mit der Länge des tibble übereinstimmt.

pf8 %>% 
  # Fügt eine Variable "test" hinzu, in der alle Werte TRUE sind.
  bind_cols(test = TRUE) %>% 
    glimpse()
## Rows: 731
## Columns: 17
## $ Standort       <fct> Münster, Münster, Münster, Münster, Münster, Münster, M…
## $ Alter          <int> 18, 67, 60, 61, 24, 21, 59, 56, 82, 52, 79, 22, 19, 18,…
## $ Geschlecht     <fct> weiblich, weiblich, weiblich, männlich, männlich, weibl…
## $ Größe          <int> 172, 165, 175, 182, 173, 177, 168, 156, 184, 166, 161, …
## $ Gewicht        <dbl> 69, 67, NA, 90, 68, 60, 80, 60, NA, 60, 66, 130, 52, 68…
## $ Bildung        <fct> Abitur, mittlere Reife, Hochschule, mittlere Reife, Abi…
## $ Beruf          <fct> Inspektor*in, Rentner*in, Ergotherapeut*in, Beamter*in,…
## $ Familienstand  <fct> Partnerschaft, geschieden, Partnerschaft, ledig, ledig,…
## $ Kinder         <int> 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0…
## $ Wohnort        <fct> ländlich, ländlich, städtisch, ländlich, städtisch, stä…
## $ Rauchen        <fct> nein, nein, nein, nein, nein, ja, nein, ja, nein, nein,…
## $ SportHäufig    <dbl> NA, 2.0, 2.0, 4.0, 4.0, 1.0, 2.0, 1.0, 1.0, 2.0, NA, 4.…
## $ SportMinuten   <dbl> NA, 60, 45, 120, 60, 60, 45, 90, NA, 45, NA, 90, 20, 12…
## $ SportWie       <fct> Allein, Gruppe, beides, Allein, Allein, Gruppe, Gruppe,…
## $ SportWarum     <fct> Arbeitsweg, Vorbeugung, Vorbeugung, Fitness, Gewichtsre…
## $ LebenZufrieden <dbl> 5, 7, 7, 2, 9, 8, 5, 8, 10, 8, 8, 8, 7, 8, 7, 8, 7, 7, …
## $ test           <lgl> TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, T…

Unsere neue Variable test sehen wir ganz unten. Alle Werte stehen auf TRUE.

26.4 Fälle hinzufügen

Neue Fälle können mit der Funktion bind_rows() hinzugefügt werden. Dies klappt nur, wenn die neuen Fälle als tibble vorliegen, das über die selben Variablen verfügt wie der Originaldatensatz. Die Reihenfolge der Spalten ist egal, da über die Spaltennamen gematcht wird.

Wichtig ist jedoch, dass innerhalb der Variablen auch der selbe Datentyp (numerisch, faktor, logisch) vorliegt, da ansonten die Datentypen auf den kleinsten gemeinsamen Nenner (character) zurückfallen. Wir machen es hier einmal falsch:

# erzeuge neuen Fall
# ohne Angabe des Datentyps
neu <- tibble("Internet", 44, "weiblich", 166, 70, NA, "Pilot", "verheiratet", 0, "ländlich","ja")
# kopiere die Spaltennamen
colnames(neu) <- colnames(pf8)

# füge zum Datensazu hinzu
# Achtung, zerschießt die Datentypen des tibble!
pf8 %>% 
   bind_rows( neu ) %>% 
    tail()
##     Standort Alter Geschlecht Größe Gewicht Bildung Beruf Familienstand Kinder
## 727 Internet    19   weiblich   158      58    <NA>               ledig      0
## 728 Internet    37   weiblich   160      59    <NA>         verheiratet      1
## 729 Internet    56   männlich   185      79    <NA>       Partnerschaft      0
## 730 Internet    20   weiblich   168      58    <NA>               ledig      0
## 731 Internet    40   männlich   183      78    <NA>         verheiratet      2
## 732 Internet    44   weiblich   166      70    <NA> Pilot   verheiratet      0
##       Wohnort Rauchen SportHäufig SportMinuten SportWie SportWarum
## 727 städtisch    nein         7.0           10   Allein       <NA>
## 728  ländlich    nein         3.0           60   Allein       <NA>
## 729  ländlich    nein         2.0           90   Gruppe       <NA>
## 730 städtisch    nein         1.0           60   Allein       <NA>
## 731 städtisch      ja         2.5          120   Gruppe       <NA>
## 732  ländlich      ja          NA           NA     <NA>       <NA>
##     LebenZufrieden
## 727              7
## 728              9
## 729              9
## 730              8
## 731             10
## 732             NA

Unsere Zeile ist ganz unten zu sehen. Die fehlenden Werte wurden mit NA aufgefüllt. Alles scheint gut gelaufen zu sein. Wie ein Blick mit glimpse() jedoch zeigt, haben wir die Datentypen unseres tibbles zerschossen, da unsere hinzugefügte Zeile nicht die korrekten Datentypen beinhaltete.

pf8 %>% 
   bind_rows( neu ) %>% 
    glimpse()
## Rows: 732
## Columns: 16
## $ Standort       <chr> "Münster", "Münster", "Münster", "Münster", "Münster", …
## $ Alter          <dbl> 18, 67, 60, 61, 24, 21, 59, 56, 82, 52, 79, 22, 19, 18,…
## $ Geschlecht     <chr> "weiblich", "weiblich", "weiblich", "männlich", "männli…
## $ Größe          <dbl> 172, 165, 175, 182, 173, 177, 168, 156, 184, 166, 161, …
## $ Gewicht        <dbl> 69, 67, NA, 90, 68, 60, 80, 60, NA, 60, 66, 130, 52, 68…
## $ Bildung        <fct> Abitur, mittlere Reife, Hochschule, mittlere Reife, Abi…
## $ Beruf          <chr> "Inspektor*in", "Rentner*in", "Ergotherapeut*in", "Beam…
## $ Familienstand  <chr> "Partnerschaft", "geschieden", "Partnerschaft", "ledig"…
## $ Kinder         <dbl> 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0…
## $ Wohnort        <chr> "ländlich", "ländlich", "städtisch", "ländlich", "städt…
## $ Rauchen        <chr> "nein", "nein", "nein", "nein", "nein", "ja", "nein", "…
## $ SportHäufig    <dbl> NA, 2.0, 2.0, 4.0, 4.0, 1.0, 2.0, 1.0, 1.0, 2.0, NA, 4.…
## $ SportMinuten   <dbl> NA, 60, 45, 120, 60, 60, 45, 90, NA, 45, NA, 90, 20, 12…
## $ SportWie       <fct> Allein, Gruppe, beides, Allein, Allein, Gruppe, Gruppe,…
## $ SportWarum     <fct> Arbeitsweg, Vorbeugung, Vorbeugung, Fitness, Gewichtsre…
## $ LebenZufrieden <dbl> 5, 7, 7, 2, 9, 8, 5, 8, 10, 8, 8, 8, 7, 8, 7, 8, 7, 7, …

Wie Sie sehen, sind unsere ehemaligen Faktoren Standort und Geschlecht auf <chr> zurückgefallen.

Ein falscher bind_rows()-Befehl kann Ihnen also das gesamte tibble “zerschießen”!

Fügen wir nun eine korrekte neue Zeile hinzu

# erzeuge korrekte neue Zeile
neu <- tibble(factor("Internet"), 44, factor("weiblich"), 166, 70, NA, factor("Pilot"), factor("verheiratet"), 0, factor("ländlich"), factor("ja"))
# Spaltennamen übernehmen
colnames(neu) <- colnames(pf8)

pf8 %>% 
   bind_rows( neu ) %>% 
    glimpse()
## Rows: 732
## Columns: 16
## $ Standort       <fct> Münster, Münster, Münster, Münster, Münster, Münster, M…
## $ Alter          <dbl> 18, 67, 60, 61, 24, 21, 59, 56, 82, 52, 79, 22, 19, 18,…
## $ Geschlecht     <fct> weiblich, weiblich, weiblich, männlich, männlich, weibl…
## $ Größe          <dbl> 172, 165, 175, 182, 173, 177, 168, 156, 184, 166, 161, …
## $ Gewicht        <dbl> 69, 67, NA, 90, 68, 60, 80, 60, NA, 60, 66, 130, 52, 68…
## $ Bildung        <fct> Abitur, mittlere Reife, Hochschule, mittlere Reife, Abi…
## $ Beruf          <fct> Inspektor*in, Rentner*in, Ergotherapeut*in, Beamter*in,…
## $ Familienstand  <fct> Partnerschaft, geschieden, Partnerschaft, ledig, ledig,…
## $ Kinder         <dbl> 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0…
## $ Wohnort        <fct> ländlich, ländlich, städtisch, ländlich, städtisch, stä…
## $ Rauchen        <fct> nein, nein, nein, nein, nein, ja, nein, ja, nein, nein,…
## $ SportHäufig    <dbl> NA, 2.0, 2.0, 4.0, 4.0, 1.0, 2.0, 1.0, 1.0, 2.0, NA, 4.…
## $ SportMinuten   <dbl> NA, 60, 45, 120, 60, 60, 45, 90, NA, 45, NA, 90, 20, 12…
## $ SportWie       <fct> Allein, Gruppe, beides, Allein, Allein, Gruppe, Gruppe,…
## $ SportWarum     <fct> Arbeitsweg, Vorbeugung, Vorbeugung, Fitness, Gewichtsre…
## $ LebenZufrieden <dbl> 5, 7, 7, 2, 9, 8, 5, 8, 10, 8, 8, 8, 7, 8, 7, 8, 7, 7, …

Die Datentypen sind erhalten geblieben.

26.5 Variablen auswählen

Mit der Funktion select() können Variablen (Spalten) des tibble ausgewählt werden.

# wähle Variablen "Alter", "Größe" und "Gewicht"
# aus Datensatz pf8
 pf8 %>% 
   select(Alter,Größe,Gewicht) %>% 
   head(.)
##    Alter Größe Gewicht
## 11    18   172      69
## 12    67   165      67
## 13    60   175      NA
## 14    61   182      90
## 15    24   173      68
## 16    21   177      60

In Kombination mit der Funktion everything() kann die Reihenfolge der Variablen im Datensatz geändert werden. Die Funktion everything() hängt alle weiteren Variablen an unsere Auswahl an.

Angenommen, wir möchten Größe und Gewicht “als erstes” sehen, und alle anderen Variablen danach, so lautet der Befehl:

# zeige erst "Größe" und "Gewicht"
# und danach alles andere.
pf8 %>% 
  select(Größe, Gewicht, everything()) %>% 
  as_tibble()
## # A tibble: 731 × 16
##   Größe Gewicht Standort Alter Geschlecht Bildung   Beruf Famil…¹ Kinder Wohnort
##   <int>   <dbl> <fct>    <int> <fct>      <fct>     <fct> <fct>    <int> <fct>  
## 1   172      69 Münster     18 weiblich   Abitur    Insp… Partne…      0 ländli…
## 2   165      67 Münster     67 weiblich   mittlere… Rent… geschi…      0 ländli…
## 3   175      NA Münster     60 weiblich   Hochschu… Ergo… Partne…      0 städti…
## 4   182      90 Münster     61 männlich   mittlere… Beam… ledig        0 ländli…
## 5   173      68 Münster     24 männlich   Abitur    Stud… ledig        0 städti…
## 6   177      60 Münster     21 weiblich   Abitur    Stud… Partne…      0 städti…
## # … with 725 more rows, 6 more variables: Rauchen <fct>, SportHäufig <dbl>,
## #   SportMinuten <dbl>, SportWie <fct>, SportWarum <fct>, LebenZufrieden <dbl>,
## #   and abbreviated variable name ¹​Familienstand

Mit der Funktion pull() werden die Spaltenwerte als Vektor wiedergegeben

# gib Werte von "Alter" als Vektor
pf8 %>% 
  pull(Alter) %>% 
   head(10)
##  [1] 18 67 60 61 24 21 59 56 82 52

26.6 Variablen erzeugen

Die Funktion mutate() erlaubt es, neue Variablen (Spalten) zu erzeugen, die durch Interaktion mit den anderen Variablen enstanden sind. So können wir im Datensatz pf8 aus den Variablen Größe und Gewicht den Body-Maß-Index errechnen, und diese Werte als neue Variable (Spalte) speichern.

# erzeuge BMI
pf8 %>% 
  mutate(BMI = Gewicht/Größe*100) %>% 
    head(.)
##    Standort Alter Geschlecht Größe Gewicht        Bildung            Beruf
## 11  Münster    18   weiblich   172      69         Abitur     Inspektor*in
## 12  Münster    67   weiblich   165      67 mittlere Reife       Rentner*in
## 13  Münster    60   weiblich   175      NA     Hochschule Ergotherapeut*in
## 14  Münster    61   männlich   182      90 mittlere Reife       Beamter*in
## 15  Münster    24   männlich   173      68         Abitur       Student*in
## 16  Münster    21   weiblich   177      60         Abitur       Student*in
##    Familienstand Kinder   Wohnort Rauchen SportHäufig SportMinuten SportWie
## 11 Partnerschaft      0  ländlich    nein          NA           NA   Allein
## 12    geschieden      0  ländlich    nein           2           60   Gruppe
## 13 Partnerschaft      0 städtisch    nein           2           45   beides
## 14         ledig      0  ländlich    nein           4          120   Allein
## 15         ledig      0 städtisch    nein           4           60   Allein
## 16 Partnerschaft      0 städtisch      ja           1           60   Gruppe
##           SportWarum LebenZufrieden      BMI
## 11        Arbeitsweg              5 40.11628
## 12        Vorbeugung              7 40.60606
## 13        Vorbeugung              7       NA
## 14           Fitness              2 49.45055
## 15 Gewichtsreduktion              9 39.30636
## 16           Fitness              8 33.89831

Mit der Schwesterfunktion transmute() wird nur die neue Variable in einem eigenen tibble zurückgegeben

# erzeuge BMI und gib nur BMI zurück
pf8 %>% 
  transmute(BMI = Gewicht/Größe*100) %>% 
    head(.)
##         BMI
## 11 40.11628
## 12 40.60606
## 13       NA
## 14 49.45055
## 15 39.30636
## 16 33.89831

26.7 statistische Berechnungen

Mit der Funktion summarise() können “zusammenfassenden Statistiken” berechnet werden. Sie fungiert als eine Art “Vermittlungsfunktion”, um Statistikfunktionen (siehe Kapitel @ref(Kapitel-StatistikMitR) in den Tidyverse-Workflow zu integrieren.

Klassische zusammenfassende Kennzahlen sind Mittelwert (über Funktion mean()), Median (über Funktion median()) und Standardabweichung (über Funktion sd()). Es funktioniert aber auch mit allen anderen Statistikfunktionen. Wir beschränken uns im Weiteren auf diese drei, alle anderen werden in Kapitel @ref(Kapitel-StatistikMitR) vorgestellt.

Berechnen wir mit mean() den Mittelwert für Alter.

# Mittelwert von "Alter"
pf8 %>% 
  summarise(Mittelwert = mean(Alter))
##   Mittelwert
## 1         NA

Wir erhalten ein NA zurück, weil in der Variable Alter fehlende Werte enthalten sind. Fast alle statistischen Funktionen erwarten von uns, dass NAs weggefilter wurden. Nutzen wir die Macht der Pipe und ändern den Befehl in

# Mittelwert von "Alter"
pf8 %>% 
  drop_na() %>% 
    summarise(Mittelwert = mean(Alter))
##   Mittelwert
## 1   38.25126

Mit der Funktion group_by() können Gruppierungen vorgenommen werden.

# Gruppiere nach Geschlecht
pf8 %>% 
  dplyr::group_by(Geschlecht) %>% 
    drop_na() %>% 
      summarise(Mittelwert = mean(Alter))
### A tibble: 3 x 2
##  Geschlecht Mittelwert
##   <fct>           <dbl>
## 1 männlich         37.3
## 2 weiblich         39.1
## 3 divers           32 

Die Liste der “zusammenfassenden Statistiken” lässt sich beliebig erweitern.

pf8 %>% 
  group_by(Geschlecht) %>% 
     drop_na() %>% 
       summarise(Mittelwert = mean(Alter),
                 Median = median(Alter),
                 Stdabw = sd(Alter))
### A tibble: 3 x 4
##  Geschlecht Mittelwert Median Stdabw
##   <fct>           <dbl>  <dbl>  <dbl>
## 1 männlich         37.3     29   17.5
## 2 weiblich         39.1     33   18.9
## 3 divers           32       32   NA  

Auch, indem Gruppierungen komplexer definiert werden.

# mit mehr Gruppierungen
pf8 %>% 
  group_by(Geschlecht, Standort) %>% 
     drop_na() %>% 
        summarise(Mittelwert = mean(Alter),
                  Median = median(Alter),
                  Stdabw = sd(Alter))
### A tibble: 9 x 5
### Groups:   Geschlecht [3]
##  Geschlecht Standort  Mittelwert Median Stdabw
##   <fct>      <fct>          <dbl>  <dbl>  <dbl>
## 1 männlich   Rheine          34.3   26     15.4
## 2 männlich   Münster         37.9   28     18.5
## 3 männlich   Bahn            39.9   36     19.8
## 4 männlich   Ladbergen       41.4   40     17.6
## 5 weiblich   Rheine          37.6   33     17.8
## 6 weiblich   Münster         38.8   27     20.0
## 7 weiblich   Bahn            41.3   37.5   19.4
## 8 weiblich   Ladbergen       43     40.5   18.5
## 9 divers     Rheine          32     32     NA   


Die Funktion count() zählt die Häufigkeit der Variablenwerte.

Dies ist nicht nur bei Faktoren hilfreich.

pf8 %>% 
  dplyr::count(Geschlecht)
##   Geschlecht   n
## 1   männlich 287
## 2   weiblich 437
## 3     divers   1
## 4       <NA>   6

In Kombination mit group_by() lassen sich Ausgaben ähnlich der Kreuztabelle erstellen.

pf8 %>% 
  drop_na() %>% 
  group_by(Familienstand, Geschlecht) %>% 
  count() %>% 
  slice_head()
## # A tibble: 13 × 3
## # Groups:   Familienstand, Geschlecht [13]
##   Familienstand Geschlecht     n
##   <fct>         <fct>      <int>
## 1 ledig         männlich      74
## 2 ledig         weiblich      82
## 3 Partnerschaft männlich      32
## 4 Partnerschaft weiblich      40
## 5 verheiratet   männlich      61
## 6 verheiratet   weiblich      78
## # … with 7 more rows

Mit der Funktion add_acount() werden die Häufigkeitswerte als eigene Variable im Datensatz gespeichert.

pf8 %>% 
  # Speichere die Levelhäufigkeit als eigene Variable
  add_count(Geschlecht, name = "AnzahlGeschlecht") %>% 
  # Zeige diese Variablen als erstes, dann den Rest
  select(Geschlecht, AnzahlGeschlecht, everything()) %>% 
  # Ausgabe als tibble ist "schöner"
  as_tibble()
## # A tibble: 731 × 17
##   Geschlecht AnzahlGe…¹ Stand…² Alter Größe Gewicht Bildung Beruf Famil…³ Kinder
##   <fct>           <int> <fct>   <int> <int>   <dbl> <fct>   <fct> <fct>    <int>
## 1 weiblich          437 Münster    18   172      69 Abitur  Insp… Partne…      0
## 2 weiblich          437 Münster    67   165      67 mittle… Rent… geschi…      0
## 3 weiblich          437 Münster    60   175      NA Hochsc… Ergo… Partne…      0
## 4 männlich          287 Münster    61   182      90 mittle… Beam… ledig        0
## 5 männlich          287 Münster    24   173      68 Abitur  Stud… ledig        0
## 6 weiblich          437 Münster    21   177      60 Abitur  Stud… Partne…      0
## # … with 725 more rows, 7 more variables: Wohnort <fct>, Rauchen <fct>,
## #   SportHäufig <dbl>, SportMinuten <dbl>, SportWie <fct>, SportWarum <fct>,
## #   LebenZufrieden <dbl>, and abbreviated variable names ¹​AnzahlGeschlecht,
## #   ²​Standort, ³​Familienstand

Die Funktion n() fliefert die Anzahl der Fälle.

pf8 %>% 
  group_by(Standort, Geschlecht) %>% 
  drop_na() %>% 
  summarise(xquer = mean(Alter),
            sd = sd(Alter),
            median = median(Alter),
            n = n())
# A tibble: 9 x 6
# Groups:   Standort [4]
  Standort  Geschlecht xquer    sd median     n
  <fct>     <fct>      <dbl> <dbl>  <dbl> <int>
1 Rheine    männlich    34.3  15.4   26      67
2 Rheine    weiblich    37.6  17.8   33      83
3 Rheine    divers      32    NA     32       1
4 Münster   männlich    37.9  18.5   28      62
5 Münster   weiblich    38.8  20.0   27      83
6 Bahn      männlich    39.9  19.8   36      29
7 Bahn      weiblich    41.3  19.4   37.5    38
8 Ladbergen männlich    41.4  17.6   40      21
9 Ladbergen weiblich    43    18.5   40.5    14


26.8 Umgang mit Faktoren

Mit dem Paket forcats stehen im Tidyverse viele hilfreiche Funktionen für den Umgang mit Faktoren zur Verfügung.

26.8.0.1 Levels umbenennen

Mit der Funktion fct_recode() können Faktorenlevels umbenannt werden.

pf8 %>% 
  mutate(Geschlecht = fct_recode(Geschlecht, 
                      m ="männlich",
                      w = "weiblich",
                      d = "divers")) %>% 
  as_tibble()
## # A tibble: 731 × 16
##   Standort Alter Geschlecht Größe Gewicht Bildung   Beruf Famil…¹ Kinder Wohnort
##   <fct>    <int> <fct>      <int>   <dbl> <fct>     <fct> <fct>    <int> <fct>  
## 1 Münster     18 w            172      69 Abitur    Insp… Partne…      0 ländli…
## 2 Münster     67 w            165      67 mittlere… Rent… geschi…      0 ländli…
## 3 Münster     60 w            175      NA Hochschu… Ergo… Partne…      0 städti…
## 4 Münster     61 m            182      90 mittlere… Beam… ledig        0 ländli…
## 5 Münster     24 m            173      68 Abitur    Stud… ledig        0 städti…
## 6 Münster     21 w            177      60 Abitur    Stud… Partne…      0 städti…
## # … with 725 more rows, 6 more variables: Rauchen <fct>, SportHäufig <dbl>,
## #   SportMinuten <dbl>, SportWie <fct>, SportWarum <fct>, LebenZufrieden <dbl>,
## #   and abbreviated variable name ¹​Familienstand

Enthalten die neuen Levelnamen Sonderzeichen (wie das Leerzeichen), müssen sie in Anführungsstrichen gesetzt werden.

pf8 %>% 
  mutate(Geschlecht = fct_recode(Geschlecht, 
                      "ein Mann" ="männlich",
                      "eine Frau" = "weiblich",
                      "ein(e) Divers" = "divers")) %>% 
  as_tibble()
## # A tibble: 731 × 16
##   Standort Alter Geschlecht Größe Gewicht Bildung   Beruf Famil…¹ Kinder Wohnort
##   <fct>    <int> <fct>      <int>   <dbl> <fct>     <fct> <fct>    <int> <fct>  
## 1 Münster     18 eine Frau    172      69 Abitur    Insp… Partne…      0 ländli…
## 2 Münster     67 eine Frau    165      67 mittlere… Rent… geschi…      0 ländli…
## 3 Münster     60 eine Frau    175      NA Hochschu… Ergo… Partne…      0 städti…
## 4 Münster     61 ein Mann     182      90 mittlere… Beam… ledig        0 ländli…
## 5 Münster     24 ein Mann     173      68 Abitur    Stud… ledig        0 städti…
## 6 Münster     21 eine Frau    177      60 Abitur    Stud… Partne…      0 städti…
## # … with 725 more rows, 6 more variables: Rauchen <fct>, SportHäufig <dbl>,
## #   SportMinuten <dbl>, SportWie <fct>, SportWarum <fct>, LebenZufrieden <dbl>,
## #   and abbreviated variable name ¹​Familienstand

26.8.1 Levelreihenfolge ändern

Bei kategorialen Daten existiert keine geordnete Reihe der Werte. Dennoch kann es hilfreich sein, kategoriale Levels in eine bestimmte Reihenfolge zu bringen. Über die Hausfunktion factor() können über den Parameter levels die Levelreihenfolgen von Hand geändert werden.

x <- factor(c("vielleicht", "ja", "nein"))
x
## [1] vielleicht ja         nein      
## Levels: ja nein vielleicht
# ändere Levelreihenfolge
factor(x, levels=c("nein", "vielleicht", "ja"))
## [1] vielleicht ja         nein      
## Levels: nein vielleicht ja

Für häufige Anwendungsfälle bietet forcats Funktionen, die uns diese Arbeit abnehmen.

Schauen wir uns im Datensatz pf8 die Anlässe für Sport an. Das Skalenniveau ist nominal. Wenn wir die Daten plotten (zu ggplot siehe Kapitel @ref(Kapitel-ggplot)), werden die Daten (die Diagrammsäulen) in der Reihenfolge der Levels angezeigt, und nicht in der Reihenfolge der Häufigkeiten.

pf8 %>% 
  select(SportWarum) %>% 
  drop_na() %>% 
  # dies ist der Plotbefehl, den Sie jetzt noch nicht verstehen.
  # Lesen Sie das Kapitel zu "ggplot".
  ggplot(aes(x=SportWarum)) + geom_bar()

Soll die Reihenfolgde der Levels so verändert werden, dass die mit der höchsten Ausprägung zuerst angezeigt werden, kann die Funktion fct_infreq() verwendet werden.

pf8 %>% 
  drop_na() %>% 
  # Sortiere nach Häufigkeiten
  mutate(SportWarum = fct_infreq(SportWarum)) %>% 
  # plotten
  ggplot(aes(x=SportWarum)) + geom_bar()

Mit der Funktion fct_rev() wird die Levelreihenfolge umgekehrt.

pf8 %>% 
  drop_na() %>% 
  # Sortiere nach Häufigkeiten
  mutate(SportWarum = fct_infreq(SportWarum)) %>% 
  # kehre Levelreihenfolge um
  mutate(SportWarum = fct_rev(SportWarum)) %>% 
  # plotten
  ggplot(aes(x=SportWarum)) + geom_bar()

Die Levelreihenfolge kann auch auf Grundlage einer anderen Variable erfolgen.

Erstellen wir uns hierfür ein Subset des pf8-Datensatzes, indem wir für jede Sport-Kategorie die Mittelwerte von Alter und Gewicht ermitteln.

pf8sub <- pf8 %>% 
            group_by(SportWarum) %>% 
            summarise(
              Alter = mean(Alter, na.rm=T),
              Gewicht = mean(Gewicht, na.rm=T),
              n = n()
            )
pf8sub
## # A tibble: 9 × 4
##   SportWarum        Alter Gewicht     n
##   <fct>             <dbl>   <dbl> <int>
## 1 0                  19      65       1
## 2 Vorbeugung         42.9    78.1   131
## 3 Gewichtsreduktion  31.9    81.7    56
## 4 Fitness            37.4    73.2   191
## 5 Therapie           52.4    80.8    14
## 6 Arbeitsweg         34.6    82.1    19
## # … with 3 more rows

Wenn wir die Daten plotten, folgen die Datenpunkte auch hier der Levelreihenfolge.

pf8sub %>% 
  # plotten
  ggplot(aes(x=Alter, y=SportWarum)) + geom_point()

Soll auch hier die Reihenfolge nach Mittelwerten erfolgen, kann die Funktion fct_reorder() verwendet werden.

pf8sub %>% 
  # überschreibe Variable "SportWarum"
  # ordne die Levels von "SportWarum" nach "Alter"
  mutate(SportWarum = fct_reorder(SportWarum, Alter)) %>% 
  # plotten  
  ggplot(aes(x=Alter, y=SportWarum)) + geom_point()

Beachten Sie, dass NA weiterhin ganz oben angezeigt werden.

Mit der Funktion fct_relevel() können einzelne Levels “nach vorne” geholt werden. In diesem Beispiel möchten wir, dass der Grund Freizeit als erstes angezeigt wird

pf8sub %>% 
  # überschreibe Variable "SportWarum"
  # ordne die Levels von "SportWarum" nach "Alter"
  mutate(SportWarum = fct_reorder(SportWarum, Alter)) %>% 
  # hole Level "Freizeit" nach vorne
  mutate(SportWarum = fct_relevel(SportWarum, "Freizeit")) %>% 
  # plotten  
  ggplot(aes(x=Alter, y=SportWarum)) + geom_point()

26.8.2 Levels zusammenfassen

Schauen wir uns die Berufe im Datenatz pf8 an.

pf8 %>% 
  dplyr::select(Beruf) %>% 
  dplyr::count(Beruf) %>% 
  arrange(n) %>% 
  as_tibble()
## # A tibble: 104 × 2
##   Beruf                    n
##   <fct>                <int>
## 1 " Produktionsleiter"     1
## 2 "Angestellte"            1
## 3 "Bäcker*in"              1
## 4 "Bauzeichner*in"         1
## 5 "Berater*in"             1
## 6 "Betriebsprüfer*in"      1
## # … with 98 more rows

Wie Sie sehen, haben wir sehr viele Levels, die nur einmal oder zweimal vorkommen.


Mit der Funktion fct_lump_min() können wir niedrigausgeprägte Levels zusammenfassen.

pf8 %>% 
  drop_na() %>% 
  # fasse alle Levels mit Ausprägung kleiner 4 zusammen
  mutate(Beruf = fct_lump_min(Beruf, 4)) %>% 
  dplyr::select(Beruf) %>% 
  dplyr::count(Beruf) %>% 
  arrange(desc(n)) %>% 
  as_tibble()
## # A tibble: 22 × 2
##   Beruf             n
##   <fct>         <int>
## 1 Other           101
## 2 Student*in       82
## 3 kaufmann/frau    29
## 4 Handwerker*in    19
## 5 Angestellte*r    18
## 6 Azubi            17
## # … with 16 more rows

Alle Levels mit Ausprägungen kleiner 4 wurden in der neuen Level Other zusammengefasst.

Mit der Funktion fct_lump_n() bleiben die höchsten n Levels erhalten, während der Rest unter Other zusammengefasst wird.

pf8 %>% 
  drop_na() %>% 
  # behalte die 3 höchstausgeprägtesten Levels
  # und fasse den Rest zusammen
  mutate(Beruf = fct_lump_n(Beruf, 3)) %>% 
  dplyr::select(Beruf) %>% 
  dplyr::count(Beruf) %>% 
  arrange(desc(n)) %>% 
  as_tibble()
## # A tibble: 4 × 2
##   Beruf             n
##   <fct>         <int>
## 1 Other           268
## 2 Student*in       82
## 3 kaufmann/frau    29
## 4 Handwerker*in    19


Mit der Funktion fct_collapse() können die Levels “von Hand” zusammengefasst werden. Schauen wir uns den Familienstand im Datensatz pf8 an.

  levels(pf8$Familienstand)
## [1] "ledig"         "Partnerschaft" "verheiratet"   "geschieden"   
## [5] "verwitwet"     "getrennt"

Fassen wir nun alle “verpartnerten” und alle “Singles” zu zwei Levels zusammen.

pf8 %>% 
  # fasse Singles und Partner in eigenen Levels zusammen
  mutate(Partnerschaft = fct_collapse(Familienstand,
                                      "Partnerschaft" = c("Partnerschaft", "verheiratet"),
                                      "Single" = c("ledig", "geschieden", "verwitwet", "getrennt"))) %>% 
  dplyr::select(Partnerschaft, Familienstand, Alter) %>% 
  as_tibble()
## # A tibble: 731 × 3
##   Partnerschaft Familienstand Alter
##   <fct>         <fct>         <int>
## 1 Partnerschaft Partnerschaft    18
## 2 Single        geschieden       67
## 3 Partnerschaft Partnerschaft    60
## 4 Single        ledig            61
## 5 Single        ledig            24
## 6 Partnerschaft Partnerschaft    21
## # … with 725 more rows

26.9 Daten visualisieren

Zum Visualisieren von Daten sind neben Tabellen vor allem Diagramme geeignet. Wie Sie im Tidyverse Diagramme erstellen behandeln wir im Kapitel ggplot, siehe Kapitel 33.