27  Schritt 3: Umgang mit Datensätzen

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

27.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

27.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 Familienstand Kinder
##   <fct>    <int> <fct>      <int>   <dbl> <fct>       <fct> <fct>          <int>
## 1 Münster     61 männlich     182      90 mittlere R… Beam… ledig              0
## 2 Münster     67 weiblich     165      67 mittlere R… Rent… geschieden         0
## 3 Rheine      32 divers       186      92 Hochschule  Sozi… verheiratet        0
## # ℹ 7 more variables: Wohnort <fct>, Rauchen <fct>, SportHäufig <dbl>,
## #   SportMinuten <dbl>, SportWie <fct>, SportWarum <fct>, LebenZufrieden <dbl>
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 Familienstand Kinder
##   <fct>     <int> <fct>      <int>   <dbl> <fct>      <fct> <fct>          <int>
## 1 Ladbergen    83 männlich     182    88   Hauptschu… Rent… verheiratet        0
## 2 Münster      78 männlich     178    71.5 Hochschule Lehr… verheiratet        0
## 3 Bahn         76 männlich     180    90   Hochschule Arzt… verheiratet        0
## 4 Münster      86 weiblich     162    70   Hauptschu… Rent… verwitwet          0
## 5 Rheine       86 weiblich     160    60   Abitur     Post… verwitwet          1
## 6 Rheine       84 weiblich     160    60   Hauptschu… Rent… verwitwet          0
## # ℹ 1 more row
## # ℹ 7 more variables: Wohnort <fct>, Rauchen <fct>, SportHäufig <dbl>,
## #   SportMinuten <dbl>, SportWie <fct>, SportWarum <fct>, LebenZufrieden <dbl>

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 Familienstand Kinder
##   <fct>    <int> <fct>      <int>   <dbl> <fct>       <fct> <fct>          <int>
## 1 Münster     22 männlich     206     130 Fachabitur  Kauf… ledig              0
## 2 Bahn        31 männlich     184     130 Fachabitur  Scha… Partnerschaft      0
## 3 Münster     40 weiblich     171     122 Hochschule  Pres… Partnerschaft      0
## 4 Rheine      45 weiblich     168     120 mittlere R… kauf… geschieden         1
## # ℹ 7 more variables: Wohnort <fct>, Rauchen <fct>, SportHäufig <dbl>,
## #   SportMinuten <dbl>, SportWie <fct>, SportWarum <fct>, LebenZufrieden <dbl>
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 Familienstand Kinder
##   <fct>    <int> <fct>      <int>   <dbl> <fct>       <fct> <fct>          <int>
## 1 Rheine      81 männlich     179      79 Hauptschule "Han… ledig              0
## 2 Rheine      74 männlich     175      84 mittlere R… "Koc… ledig              0
## 3 Münster     72 männlich     175      86 mittlere R… "Sic… ledig              0
## 4 Münster     69 männlich     179      89 mittlere R… "Ren… ledig              0
## 5 Münster     61 männlich     182      90 mittlere R… "Bea… ledig              0
## 6 Rheine      59 männlich     175      70 Abitur      ""    ledig              1
## # ℹ 7 more variables: Wohnort <fct>, Rauchen <fct>, SportHäufig <dbl>,
## #   SportMinuten <dbl>, SportWie <fct>, SportWarum <fct>, LebenZufrieden <dbl>

27.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.

27.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.

27.5 Datensätze verbinden

Um Datenframes oder Tibbles miteinander zu verbinden, stehen neben bind_rows() und bind_cols() die join-Funktionen zur Verfügung. Sie kommen dann zur Anwendung, wenn die Zusammenführung anhand von “Übereinstimmungen” erfolgen soll.

Stellen wir uns die beiden Datenframes X und Y vor.

zwei Datenframes X und Y

Lassen Sie uns nun zwei konkrete Testdatensätze für X und Y erzeugen.

Das Tibble patient soll Daten über 10 Testpatienten enthalten.

patient <- tribble(
  ~Patient, ~Alter, ~Geschlecht, ~Diagnose,
    "AB25",     51,         "w",   "00119",
    "JA26",     61,         "w",   "00030",
    "BG81",     44,         "m",   "00011",
    "ZT42",     50,         "m",   "00199",
    "AL63",     80,         "w",   "00223",
    "XV96",     88,         "w",   "00016",
    "QR49",     66,         "w",   "00027",
    "FE31",     77,         "w",   "00027",
    "PP23",     64,         "m",   "00098",
    "WU53",     86,         "w",   "00016"
  )

In nanda sollen 10 NANDA-Pflegediagnosen enthalten sein.

nanda <- tribble(
    ~Code,                                ~Diagnosetitel, ~Evidenzlevel,
  "00110", "Selbstversorgungsdefizit Toilettenbenutzung",           2.1,
  "00108",       "Selbstversorgungsdefizit Körperpflege",           2.1,
  "00027",             "Defizitäres Flüssigkeitsvolumen",           2.1,
  "00011",                                 "Obstipation",           3.1,
  "00030",               "Beeinträchtigter Gasaustausch",           3.3,
  "00223",                       "Ineffektive Beziehung",           2.1,
  "00016",            "Beeinträchtigte Harnausscheidung",           3.1,
  "00119",         "Chronisch geringes Selbstwertgefühl",           3.2,
  "00199",              "Ineffektive Aktivitätenplanung",           2.1,
  "00095",                               "Schlafstörung",           3.3
  )

Schauen wir uns die beiden Tibbles noch einmal an:

head(patient)
## # A tibble: 6 × 4
##   Patient Alter Geschlecht Diagnose
##   <chr>   <dbl> <chr>      <chr>   
## 1 AB25       51 w          00119   
## 2 JA26       61 w          00030   
## 3 BG81       44 m          00011   
## 4 ZT42       50 m          00199   
## 5 AL63       80 w          00223   
## 6 XV96       88 w          00016
head(nanda)
## # A tibble: 6 × 3
##   Code  Diagnosetitel                               Evidenzlevel
##   <chr> <chr>                                              <dbl>
## 1 00110 Selbstversorgungsdefizit Toilettenbenutzung          2.1
## 2 00108 Selbstversorgungsdefizit Körperpflege                2.1
## 3 00027 Defizitäres Flüssigkeitsvolumen                      2.1
## 4 00011 Obstipation                                          3.1
## 5 00030 Beeinträchtigter Gasaustausch                        3.3
## 6 00223 Ineffektive Beziehung                                2.1

Es ist erkennbar, dass patient$Diagnose und nanda$Code Daten über das selbe Item beinhalten (in vielen Projekten wird eine eindeutige ID vergeben, über die später referenziert werden kann). Diese Spalten können wir also nutzen, um beim Verschmelzen die jeweiligen Datenreihen der beiden Tibbles einander zuordnen zu können. Dies haben wir schon bei der merge()-Funktion so gemacht, siehe Abschnitt 8.4.3. Im Tidyverse muss diese Information mittels join_by( X$Spalte == Y$Spalte) an die join-Funktionen übergeben werden. In userem Beispiel würde die Übereinstimmung wie folgt festgelegt: join_by(Diagnose==Code).

Die eigentliche Zusammenführung kann dann auf verschiedene Arten erfolgen:

  • inner_join()
  • left_join()
  • right_join()
  • full_join()

27.5.1 inner_join()

Die Funktion inner_join() verschmilzt nur solche Datenreihen aus X und Y, die in den Übereinstimmungsspalten gleiche Werte haben.

inner-join() übernimmt nur übereinstimmende Zeilen

Welcher Datensatz für X oder Y steht entscheidet die Reihenfolge innerhalb des Funktionsaufrufs. Im folgenden Beispiel setzen wir patient als X und nanda als Y.

# behalte nur solche, die matchen
inner_join(patient, nanda, join_by(Diagnose == Code))
## # A tibble: 9 × 6
##   Patient Alter Geschlecht Diagnose Diagnosetitel                   Evidenzlevel
##   <chr>   <dbl> <chr>      <chr>    <chr>                                  <dbl>
## 1 AB25       51 w          00119    Chronisch geringes Selbstwertg…          3.2
## 2 JA26       61 w          00030    Beeinträchtigter Gasaustausch            3.3
## 3 BG81       44 m          00011    Obstipation                              3.1
## 4 ZT42       50 m          00199    Ineffektive Aktivitätenplanung           2.1
## 5 AL63       80 w          00223    Ineffektive Beziehung                    2.1
## 6 XV96       88 w          00016    Beeinträchtigte Harnausscheidu…          3.1
## 7 QR49       66 w          00027    Defizitäres Flüssigkeitsvolumen          2.1
## 8 FE31       77 w          00027    Defizitäres Flüssigkeitsvolumen          2.1
## 9 WU53       86 w          00016    Beeinträchtigte Harnausscheidu…          3.1

Das so erzeugte Tibble enthält nur 9 Patientendaten, da der Diagnosecode von Patient PP23 (00098) nicht in der nanda-Liste enthalten ist. Weil aber nur vollständige Matches beibehalten werden, fehlt Patient PP23 in der Ausgabe.

Das Merkmal von inner_join() ist also, dass nur vollständige Datenreihen erhalten bleiben.

27.5.2 left_join()

Die Funktion left_join() behält alle Datenreihen von X, und fügt nur solche Y hinzu, die über die Übereinstimmungsspalte matchen.

left_join() behält alle X und ergänz passende Y

Auch in diesem Beispiel setzen wir patient als X und nanda als Y.

# behalte alle patienten (x), und packe nur
# matchende y (NANDA) hinzu
left_join(patient, nanda, join_by(Diagnose == Code))
## # A tibble: 10 × 6
##    Patient Alter Geschlecht Diagnose Diagnosetitel                  Evidenzlevel
##    <chr>   <dbl> <chr>      <chr>    <chr>                                 <dbl>
##  1 AB25       51 w          00119    Chronisch geringes Selbstwert…          3.2
##  2 JA26       61 w          00030    Beeinträchtigter Gasaustausch           3.3
##  3 BG81       44 m          00011    Obstipation                             3.1
##  4 ZT42       50 m          00199    Ineffektive Aktivitätenplanung          2.1
##  5 AL63       80 w          00223    Ineffektive Beziehung                   2.1
##  6 XV96       88 w          00016    Beeinträchtigte Harnausscheid…          3.1
##  7 QR49       66 w          00027    Defizitäres Flüssigkeitsvolum…          2.1
##  8 FE31       77 w          00027    Defizitäres Flüssigkeitsvolum…          2.1
##  9 PP23       64 m          00098    <NA>                                   NA  
## 10 WU53       86 w          00016    Beeinträchtigte Harnausscheid…          3.1

Alle Patienten (X) sind erhalten geblieben. Da der Diagnosecode von Patient PP23 (00098) nicht in der nanda-Liste (Y) enthalten ist, wurden NAs ergänzt.

27.5.3 right_join()

Die Funktion right_join() ist das spiegelverkehrte Pendant. Sie behält alle Datenreihen von Y, und fügt nur solche X hinzu, die über die Übereinstimmungsspalte matchen.

right_join() behält alle Y und ergänz passende X
# behalte alle NANDA (y) und packe nur
# matchende Patienten (x) hinzu
# erzeugt doppelte Y, wenn x mehrfach y enthält
right_join(patient, nanda, join_by(Diagnose == Code))
## # A tibble: 12 × 6
##    Patient Alter Geschlecht Diagnose Diagnosetitel                  Evidenzlevel
##    <chr>   <dbl> <chr>      <chr>    <chr>                                 <dbl>
##  1 AB25       51 w          00119    Chronisch geringes Selbstwert…          3.2
##  2 JA26       61 w          00030    Beeinträchtigter Gasaustausch           3.3
##  3 BG81       44 m          00011    Obstipation                             3.1
##  4 ZT42       50 m          00199    Ineffektive Aktivitätenplanung          2.1
##  5 AL63       80 w          00223    Ineffektive Beziehung                   2.1
##  6 XV96       88 w          00016    Beeinträchtigte Harnausscheid…          3.1
##  7 QR49       66 w          00027    Defizitäres Flüssigkeitsvolum…          2.1
##  8 FE31       77 w          00027    Defizitäres Flüssigkeitsvolum…          2.1
##  9 WU53       86 w          00016    Beeinträchtigte Harnausscheid…          3.1
## 10 <NA>       NA <NA>       00110    Selbstversorgungsdefizit Toil…          2.1
## 11 <NA>       NA <NA>       00108    Selbstversorgungsdefizit Körp…          2.1
## 12 <NA>       NA <NA>       00095    Schlafstörung                           3.3

Das neue Tibble ist 12 Reihen lang, da zwei Pflegediagnosen (Y) jeweils 2mal im Datensatz patient (X) vorkommen.

Das Ergebnis von right_join() lässt sich prinzipiell auch erreichen, indem innerhalb von left_join() einfach die Werte umgedreht werden. Die Reihenfolge der Spalten und Zeilen im erzeugten Tibble ist dann aber anders, obwohl insgesamt die selben Daten enthalten sind.

# geht auch mit left_join(),
# indem man einfach X und Y vertauscht
# join_by() muss ebenfalls vertauscht werden
left_join(nanda, patient, join_by(Code == Diagnose))
## # A tibble: 12 × 6
##    Code  Diagnosetitel                     Evidenzlevel Patient Alter Geschlecht
##    <chr> <chr>                                    <dbl> <chr>   <dbl> <chr>     
##  1 00110 Selbstversorgungsdefizit Toilett…          2.1 <NA>       NA <NA>      
##  2 00108 Selbstversorgungsdefizit Körperp…          2.1 <NA>       NA <NA>      
##  3 00027 Defizitäres Flüssigkeitsvolumen            2.1 QR49       66 w         
##  4 00027 Defizitäres Flüssigkeitsvolumen            2.1 FE31       77 w         
##  5 00011 Obstipation                                3.1 BG81       44 m         
##  6 00030 Beeinträchtigter Gasaustausch              3.3 JA26       61 w         
##  7 00223 Ineffektive Beziehung                      2.1 AL63       80 w         
##  8 00016 Beeinträchtigte Harnausscheidung           3.1 XV96       88 w         
##  9 00016 Beeinträchtigte Harnausscheidung           3.1 WU53       86 w         
## 10 00119 Chronisch geringes Selbstwertgef…          3.2 AB25       51 w         
## 11 00199 Ineffektive Aktivitätenplanung             2.1 ZT42       50 m         
## 12 00095 Schlafstörung                              3.3 <NA>       NA <NA>

Das neue Tibble ist 12 Reihen lang, da zwei Pflegediagnosen (X) jeweils 2mal im Datensatz patient (Y) vorkommen.

Dieses Verhalten kann über den Parameter multiple bestimmt werden. So lässt sich einstellen, ob aus Y alle (all), nur der erste (first) oder letzte (last), oder irgendein (any) passender Eintrag übernommen werden soll.

# wenn mehrfaches Vorkommen in Y, nimm den letzten
left_join(nanda, patient, join_by(Code == Diagnose),
           multiple="last")
## # A tibble: 10 × 6
##    Code  Diagnosetitel                     Evidenzlevel Patient Alter Geschlecht
##    <chr> <chr>                                    <dbl> <chr>   <dbl> <chr>     
##  1 00110 Selbstversorgungsdefizit Toilett…          2.1 <NA>       NA <NA>      
##  2 00108 Selbstversorgungsdefizit Körperp…          2.1 <NA>       NA <NA>      
##  3 00027 Defizitäres Flüssigkeitsvolumen            2.1 FE31       77 w         
##  4 00011 Obstipation                                3.1 BG81       44 m         
##  5 00030 Beeinträchtigter Gasaustausch              3.3 JA26       61 w         
##  6 00223 Ineffektive Beziehung                      2.1 AL63       80 w         
##  7 00016 Beeinträchtigte Harnausscheidung           3.1 WU53       86 w         
##  8 00119 Chronisch geringes Selbstwertgef…          3.2 AB25       51 w         
##  9 00199 Ineffektive Aktivitätenplanung             2.1 ZT42       50 m         
## 10 00095 Schlafstörung                              3.3 <NA>       NA <NA>

Ausgangspunkt für den Parameter multiple ist immer Datensatz X. Im letzten Beispiel wurde nanda als X angegeben. Da jeder Diagnosecode in nanda genau einmal vorkommt, ist das neue Tibble 10 Reihen lang. Sollte in Y (patient) die Diagnose mehrfach vorkommen, wird (im Beispiel oben) die letzte vorkommende Datenreihen aus Y verwendet.

Kehren wir zum ursprünglichen right_join()-Aufruf zurück und übergeben den Parameter

right_join(patient, nanda, join_by(Diagnose == Code),
           multiple="last")
## # A tibble: 12 × 6
##    Patient Alter Geschlecht Diagnose Diagnosetitel                  Evidenzlevel
##    <chr>   <dbl> <chr>      <chr>    <chr>                                 <dbl>
##  1 AB25       51 w          00119    Chronisch geringes Selbstwert…          3.2
##  2 JA26       61 w          00030    Beeinträchtigter Gasaustausch           3.3
##  3 BG81       44 m          00011    Obstipation                             3.1
##  4 ZT42       50 m          00199    Ineffektive Aktivitätenplanung          2.1
##  5 AL63       80 w          00223    Ineffektive Beziehung                   2.1
##  6 XV96       88 w          00016    Beeinträchtigte Harnausscheid…          3.1
##  7 QR49       66 w          00027    Defizitäres Flüssigkeitsvolum…          2.1
##  8 FE31       77 w          00027    Defizitäres Flüssigkeitsvolum…          2.1
##  9 WU53       86 w          00016    Beeinträchtigte Harnausscheid…          3.1
## 10 <NA>       NA <NA>       00110    Selbstversorgungsdefizit Toil…          2.1
## 11 <NA>       NA <NA>       00108    Selbstversorgungsdefizit Körp…          2.1
## 12 <NA>       NA <NA>       00095    Schlafstörung                           3.3

so ist das Tibble wieder 12 Reihen lang, denn Ausgangspunkt für multiple ist immer Datensatz X (auch bei right_join()). Im Funktionsaufruf oben steht patient als X. Daher schaut die Funktion für jede Reihe in X, ob ein oder mehrere passende Einträge in Y vorhanden sind. Da in Y (nanda) aber jede Diagnose nur einmal definiert wird, kommen keine multiplen Zeilen vor. Der Parameter multiple findet daher keine Anwendung.

Nun will right_join() aber alle Y beibehalten und mit allen passenden X (patient) verschmelzen. Da bei zwei Diagnosen in Y jeweils zwei Patienten aus X matchen, ist die Ausgabe 12 Zeilen lang.

27.5.4 full_join()

Beim full_join() werden alle Daten von X und Y beibehalten.

full_join() behält alle X und Y
# behält alle x und alle y
full_join(patient, nanda, join_by(Diagnose == Code))
## # A tibble: 13 × 6
##    Patient Alter Geschlecht Diagnose Diagnosetitel                  Evidenzlevel
##    <chr>   <dbl> <chr>      <chr>    <chr>                                 <dbl>
##  1 AB25       51 w          00119    Chronisch geringes Selbstwert…          3.2
##  2 JA26       61 w          00030    Beeinträchtigter Gasaustausch           3.3
##  3 BG81       44 m          00011    Obstipation                             3.1
##  4 ZT42       50 m          00199    Ineffektive Aktivitätenplanung          2.1
##  5 AL63       80 w          00223    Ineffektive Beziehung                   2.1
##  6 XV96       88 w          00016    Beeinträchtigte Harnausscheid…          3.1
##  7 QR49       66 w          00027    Defizitäres Flüssigkeitsvolum…          2.1
##  8 FE31       77 w          00027    Defizitäres Flüssigkeitsvolum…          2.1
##  9 PP23       64 m          00098    <NA>                                   NA  
## 10 WU53       86 w          00016    Beeinträchtigte Harnausscheid…          3.1
## 11 <NA>       NA <NA>       00110    Selbstversorgungsdefizit Toil…          2.1
## 12 <NA>       NA <NA>       00108    Selbstversorgungsdefizit Körp…          2.1
## 13 <NA>       NA <NA>       00095    Schlafstörung                           3.3

27.6 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 Familienstand Kinder
##   <int>   <dbl> <fct>    <int> <fct>      <fct>       <fct> <fct>          <int>
## 1   172      69 Münster     18 weiblich   Abitur      Insp… Partnerschaft      0
## 2   165      67 Münster     67 weiblich   mittlere R… Rent… geschieden         0
## 3   175      NA Münster     60 weiblich   Hochschule  Ergo… Partnerschaft      0
## 4   182      90 Münster     61 männlich   mittlere R… Beam… ledig              0
## 5   173      68 Münster     24 männlich   Abitur      Stud… ledig              0
## 6   177      60 Münster     21 weiblich   Abitur      Stud… Partnerschaft      0
## # ℹ 725 more rows
## # ℹ 7 more variables: Wohnort <fct>, Rauchen <fct>, SportHäufig <dbl>,
## #   SportMinuten <dbl>, SportWie <fct>, SportWarum <fct>, LebenZufrieden <dbl>

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

27.7 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

27.8 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
##  7 verheiratet   divers         1
##  8 geschieden    männlich       5
##  9 geschieden    weiblich       7
## 10 verwitwet     männlich       4
## 11 verwitwet     weiblich       9
## 12 getrennt      männlich       3
## 13 getrennt      weiblich       2

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 AnzahlGeschlecht Standort Alter Größe Gewicht Bildung        Beruf 
##   <fct>                 <int> <fct>    <int> <int>   <dbl> <fct>          <fct> 
## 1 weiblich                437 Münster     18   172      69 Abitur         Inspe…
## 2 weiblich                437 Münster     67   165      67 mittlere Reife Rentn…
## 3 weiblich                437 Münster     60   175      NA Hochschule     Ergot…
## 4 männlich                287 Münster     61   182      90 mittlere Reife Beamt…
## 5 männlich                287 Münster     24   173      68 Abitur         Stude…
## 6 weiblich                437 Münster     21   177      60 Abitur         Stude…
## # ℹ 725 more rows
## # ℹ 9 more variables: Familienstand <fct>, Kinder <int>, Wohnort <fct>,
## #   Rauchen <fct>, SportHäufig <dbl>, SportMinuten <dbl>, SportWie <fct>,
## #   SportWarum <fct>, LebenZufrieden <dbl>

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


27.9 Umgang mit Faktoren

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

27.9.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 Familienstand Kinder
##   <fct>    <int> <fct>      <int>   <dbl> <fct>       <fct> <fct>          <int>
## 1 Münster     18 w            172      69 Abitur      Insp… Partnerschaft      0
## 2 Münster     67 w            165      67 mittlere R… Rent… geschieden         0
## 3 Münster     60 w            175      NA Hochschule  Ergo… Partnerschaft      0
## 4 Münster     61 m            182      90 mittlere R… Beam… ledig              0
## 5 Münster     24 m            173      68 Abitur      Stud… ledig              0
## 6 Münster     21 w            177      60 Abitur      Stud… Partnerschaft      0
## # ℹ 725 more rows
## # ℹ 7 more variables: Wohnort <fct>, Rauchen <fct>, SportHäufig <dbl>,
## #   SportMinuten <dbl>, SportWie <fct>, SportWarum <fct>, LebenZufrieden <dbl>

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 Familienstand Kinder
##   <fct>    <int> <fct>      <int>   <dbl> <fct>       <fct> <fct>          <int>
## 1 Münster     18 eine Frau    172      69 Abitur      Insp… Partnerschaft      0
## 2 Münster     67 eine Frau    165      67 mittlere R… Rent… geschieden         0
## 3 Münster     60 eine Frau    175      NA Hochschule  Ergo… Partnerschaft      0
## 4 Münster     61 ein Mann     182      90 mittlere R… Beam… ledig              0
## 5 Münster     24 ein Mann     173      68 Abitur      Stud… ledig              0
## 6 Münster     21 eine Frau    177      60 Abitur      Stud… Partnerschaft      0
## # ℹ 725 more rows
## # ℹ 7 more variables: Wohnort <fct>, Rauchen <fct>, SportHäufig <dbl>,
## #   SportMinuten <dbl>, SportWie <fct>, SportWarum <fct>, LebenZufrieden <dbl>

27.9.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
## 7 Beruflich          43.9    80.6    14
## 8 Freizeit           36.7    74.0    28
## 9 <NA>               34.1    73.9   277

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()

27.9.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
## # ℹ 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
## # ℹ 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
## # ℹ 725 more rows

27.10 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 34.