31  Daten manipulieren

31.1 Einer Kreuztabelle Prozentwerte hinzufügen

Ich möchte eine Kreuztabelle ausgeben, die sowohl absolute Häufigkeiten als auch Prozentwerte enthält.

Ich erstelle folgende Kreuztabelle:

A <- rep(c("A1", "A2", "A3"), 10)
B <- sample(1:5, size=30, replace=TRUE)
C <- sample(c("ja", "nein"), size=30, replace=TRUE)
df <- data.frame(rbind(table(B, A),
                 table(C, A)))
df
##      A1 A2 A3
## 1     0  4  1
## 2     1  1  4
## 3     2  1  1
## 4     2  3  0
## 5     5  1  4
## ja    5  3  6
## nein  5  7  4

Die einzelnen Werte sollen nun mit den jeweiligen Prozentwerten ergänzt werden. Dies kann mit den Funktionen transmute() und across() erfolgen.

df %>% 
            # über jede Spalte
  transmute(across(everything(),
                     # x ausgeben und " (x%)" anhängen
                   ~ paste0(.x, " (", round(.x / sum(df), 2) * 100, "%)")
                  )
           )
##          A1      A2      A3
## 1    0 (0%)  4 (7%)  1 (2%)
## 2    1 (2%)  1 (2%)  4 (7%)
## 3    2 (3%)  1 (2%)  1 (2%)
## 4    2 (3%)  3 (5%)  0 (0%)
## 5    5 (8%)  1 (2%)  4 (7%)
## ja   5 (8%)  3 (5%) 6 (10%)
## nein 5 (8%) 7 (12%)  4 (7%)

31.2 Zeilen und Spalten tauschen

Ich möchte bei meinem Datensatz Zeilen und Spalten vertauschen.

Dies kann mit der Funktion apply() gemacht werden. Angenommen das Datenframe datensatz sieht wie folgt aus …

# lade Testdatensatz datensatz
datensatz <-read.table(url("http://www.produnis.de/R/DieDaten.csv"), sep=";", header=TRUE) 
# zeige "datensaz" an 
datensatz
##     Name   Geschlecht Lieblingsfarbe Einkommen
## 1   Hans    maennlich          gruen      1233
## 2   Caro     weiblich           blau       800
## 3   Lars intersexuell           gelb      2400
## 4   Ines     weiblich        schwarz      4000
## 5 Samira     weiblich           gelb       899
## 6  Peter    maennlich          gruen      1100
## 7  Sarah     weiblich           blau      1900

…so tauschen wir Zeilen und Spalten mittels

# vertausche Spalten und Zeilen 
apply(datensatz, MARGIN=1, FUN=function(x) {x})
##                [,1]        [,2]       [,3]           [,4]       [,5]      
## Name           "Hans"      "Caro"     "Lars"         "Ines"     "Samira"  
## Geschlecht     "maennlich" "weiblich" "intersexuell" "weiblich" "weiblich"
## Lieblingsfarbe "gruen"     "blau"     "gelb"         "schwarz"  "gelb"    
## Einkommen      "1233"      " 800"     "2400"         "4000"     " 899"    
##                [,6]        [,7]      
## Name           "Peter"     "Sarah"   
## Geschlecht     "maennlich" "weiblich"
## Lieblingsfarbe "gruen"     "blau"    
## Einkommen      "1100"      "1900"

Da die Funktion apply() eine Typkonversion in die Klasse matrix vornimmt, (und somit alle Datentypen auf den kleinsten gemeinsamen Nenner character zurückfallen, siehe die Anführungszeichen im Output) muss bei Bedarf zurück in die Klasse data.frame konvertiert werden.

# vertausche Spalten und Zeilen 
as.data.frame(apply(datensatz, MARGIN=1, FUN=function(x) {x}))
##                       V1       V2           V3       V4       V5        V6
## Name                Hans     Caro         Lars     Ines   Samira     Peter
## Geschlecht     maennlich weiblich intersexuell weiblich weiblich maennlich
## Lieblingsfarbe     gruen     blau         gelb  schwarz     gelb     gruen
## Einkommen           1233      800         2400     4000      899      1100
##                      V7
## Name              Sarah
## Geschlecht     weiblich
## Lieblingsfarbe     blau
## Einkommen          1900

31.3 Klassen für Variablen bilden (klassieren)

Ich möchte die Werte einer Variable in Kategorien bzw. Klassen einteilen.

Angenommen, meine Variable enthält Werte zwischen 0 und 500, und ich möchte diese Werte in die Gruppen “0-70”, “71-200”, “201-400”, “>400”, klassieren, wie gehe ich dann vor?

31.3.1 R base

Im klassischen R erstellen wir zunächst zufällige Zahlen zwischen 0 und 500.

# erzeuge 200 Zufallszahlen von 0 bis 500
dummy <- sample(0:500, 200)
# bzw. direkt als Dataframe
dummy <- data.frame(x = sample(0:500, 200))

Nun erzeugen wir die neue Variable xKAT, in welcher die Klassierung angegeben werden soll.

# wir bilden Kategorien
#      "0-70"
#      "71-200"
#      "201-400"
#      "> 400"
# und speichern das in die neue Variable xKAT
dummy$xKAT[dummy$x <71] <- "0-70"
dummy$xKAT[dummy$x <201 & dummy$x > 70] <- "71-200"
dummy$xKAT[dummy$x <401 & dummy$x > 200] <- "201-400"
dummy$xKAT[dummy$x >400] <- "größer 400"

Anschließend wandeln wir die neue Variable in einen ordinalen Faktor mit korrekter Levelreihenfolge.

dummy$xKAT <- factor(dummy$xKAT, levels=c("0-70",
                                    "71-200",
                                    "201-400",
                                    "größer 400"),
                       ordered=TRUE)
head(dummy$xKAT)
## [1] 201-400    größer 400 71-200     größer 400 71-200     0-70      
## Levels: 0-70 < 71-200 < 201-400 < größer 400

31.3.2 Tidyverse

Zunächst laden wir das tidyverse-Paket und erstellen uns zufällige Zahlen zwischen 0 und 500.

# lade tidyverse
library(tidyverse)
# erzeuge 200 Zufallszahlen von 0 bis 500
dummy <- sample(0:500, 200)
# bzw. direkt als Tibble
dummy <- tibble(x = sample(0:500, 200))

Nun erzeugen wir die neue Variable xKAT, in welcher die Klassierung angegeben werden soll. Hierfür nutzen wir innerhalb von mutate() die ifelse()-Funktion. Diese folgte der Logik “WELCHE - WAS -ANSONSTEN”. In einem ersten beispielhaften Schritt wählen wir all “x < 71” aus, speichern für diese Fälle den character-Wert “0-70”, und bei allen anderen Fällen ein “NA”.

dummy %>%
              # ifelse(WELCHE, WAS, ANSONSTEN)
    mutate(xKAT = ifelse(x < 71 , "0-70", NA))
## # A tibble: 200 × 2
##       x xKAT 
##   <int> <chr>
## 1   211 <NA> 
## 2   241 <NA> 
## 3   449 <NA> 
## 4   131 <NA> 
## 5   476 <NA> 
## 6   459 <NA> 
## # … with 194 more rows

Es lassen sich mehrere ifelse()-Ausdrücke kombinieren, indem diese vor den NA-Ausdruck geschrieben werden.

# Das lässt sich erweitern, indem der ", NA"-Ausdruck nach hinten wandert
dummy %>%
  mutate(xKAT = ifelse(x < 71 , "0-70",
                ifelse(x < 201 & x >70 , "71-200",
                       NA)))
## # A tibble: 200 × 2
##       x xKAT  
##   <int> <chr> 
## 1   211 <NA>  
## 2   241 <NA>  
## 3   449 <NA>  
## 4   131 71-200
## 5   476 <NA>  
## 6   459 <NA>  
## # … with 194 more rows

Der vollständige Befehl zur Klassierung lautet demnach:

# wir bilden Kategorien
#      "0-70"
#      "71-200"
#      "201-400"
#      "> 400"
# und speichern das in die neue Variable xKAT
dummy %>%
  mutate(xKAT = ifelse(x < 71 , "0-70",
                ifelse(x < 201 & x >70 ,  "71-200",
                ifelse(x < 401 & x >200 , "201-400",
                ifelse(x > 400 , "> 400",
                              NA)))))
## # A tibble: 200 × 2
##       x xKAT   
##   <int> <chr>  
## 1   211 201-400
## 2   241 201-400
## 3   449 > 400  
## 4   131 71-200 
## 5   476 > 400  
## 6   459 > 400  
## # … with 194 more rows

Anschließend wandeln wir die neue Variable in einen ordinalen Faktor mit korrekter Levelreihenfolge.

# die neue Variable als ordinalen Factor mit korrekter
# Levelreihenfolge speichern
dummy <- dummy %>%
  mutate(xKAT = ifelse(x < 71 , "0-70",
                ifelse(x < 201 & x >70 ,  "71-200",
                ifelse(x < 401 & x >200 , "201-400",
                ifelse(x > 400 , "größer 400",
                                NA)))),
         xKAT = factor(xKAT, levels=c("0-70",
                                      "71-200",
                                      "201-400",
                                      "größer 400"),
                       ordered=TRUE)
         )
head(dummy$xKAT)
## [1] 201-400    201-400    größer 400 71-200     größer 400 größer 400
## Levels: 0-70 < 71-200 < 201-400 < größer 400