logischer_vektor = c(TRUE, FALSE, FALSE, TRUE, TRUE)
! logischer_vektor [1] FALSE  TRUE  TRUE FALSE FALSEIn R stehen die logischen Operationen als binäre Operatoren zur Verfügung, bzw. als Funktionen mit genau zwei Parametern. Diese logischen Operatoren sind vektorisiert. Es ist deshalb unnötig, logische Ausdrücke durch die Boole’sche Arithmetik zu ersetzen. Lediglich die Reihenfolge der Ausführung dieser Operatoren folgt der gleichen Regel wie die Arithmetik.
Daraus folgt, dass immer zuerst das logische Und und erst danach das logische Oder ausgewertet wird. Dieser Regel folgt auch R.
Die Tabelle 11.1 stellt die logischen Operationen und die verschiedenen Schreibweisen gegenüber.
| Operation | neutrales Element | Mathematisch | R | arithmetische Operation | 
|---|---|---|---|---|
| Nicht | - | \lnot | ! | 1 - a | 
| Und | WAHR | \land | & | a \cdot b | 
| Oder | FALSCH | \lor | | | a + b | 
| Exklusiv-Oder/Antivalenz | - | \oplus | xor() | (a - b)^2 | 
Es gibt neben den beiden Operatoren & und | auch die gedoppelte Varianten && und ||. Diese Varianten arbeiten auf den Binärwerten von Ganzzahlen und werden normalerweise nicht im Zusammenhang mit logischen Ausdrücken verwendet.
Das Logisches Nicht wird in R durch den Nicht-Operator (!) ausgedrückt. Dieser Operator wird auf jeden Wert eines Vektors einzeln angewandt.
Beispiel 11.1 (Logisches Nicht)
logischer_vektor = c(TRUE, FALSE, FALSE, TRUE, TRUE)
! logischer_vektor [1] FALSE  TRUE  TRUE FALSE FALSER wandelt numerische Werte automatisch in Wahrheitswerte um, wenn sie mit logischen Operationen verwendet werden. Dabei gilt:
FALSE entspricht 0TRUE entspricht ungleich 0Beispiel 11.2
! c(1, 2, 0, 4, 0) [1] FALSE FALSE  TRUE FALSE  TRUEWenn Sie in R zwei Vektoren mit dem Und- (&), dem Oder-Operator (|) oder der Antivalenz (xor()) verknüpfen, dann werden die Werte immer paarweise miteinander verglichen. Ein einzelner Vektor kann nicht an die Funktion des jeweiligen Operators übergeben werden.
Beispiel paarweise Verknüpfung
vektor_a = c(TRUE, FALSE, FALSE, TRUE, TRUE)
vektor_b = c(TRUE,  TRUE, FALSE, FALSE, TRUE)
vektor_a & vektor_b [1]  TRUE FALSE FALSE FALSE  TRUEreduce()Um logische Vektoren in R zu aggregieren, muss der Vektor reduziert (engl. reduce) werden. Das Reduzieren ist eine besondere Aggregation über eine Reihe von Werten, bei der jeder Wert gemeinsam mit dem Ergebnis der Vorgängerwerte an eine Funktion übergeben wird.
Beispiel 11.3 (Aggregation logischer Vektoren)
beispielWerte = c(TRUE, TRUE, FALSE, TRUE)
beispielWerte |> reduce(`&`)   [1] FALSEbeispielWerte |> reduce(`|`)   [1] TRUEbeispielWerte |> reduce(`xor`) [1] TRUEBeim Reduzieren muss beachtet werden, dass eine Funktion und nicht den Operator übergeben wird. Deshalb muss der jeweilige logische Operator in Backticks (`) gesetzt und so als Funktionsbezeichner markiert werden.
Neben den logischen Operationen sind Vergleiche ein wichtiges Konzept, das wir in logischen Ausdrücken regelmässig anwenden.
Es gibt genau sechs (6) Vergleichsoperatoren:
==)!=)>)>=)<)<=)Vergleiche erfordern, dass beide Werte vom gleichen Datentyp sind.
Die Vergleiche funktionieren für alle fundamentalen Datentypen.
Bei Zeichenketten wertet R die alphabetische Reihenfolge der Symbole vom Beginn einer Zeichenkette aus, um grösser oder kleiner Vergleiche durchzuführen.
Häufig müssen Sie überprüfen, ob ein Wert in einer Liste vorkommt. Grundsätzlich können Sie das mit komplizierten logischen Verknüpfungen in der Art von Beispiel 11.4 schreiben.
Beispiel 11.4 (Existstenzprüfung ohne %in%)  
meinWert = 3
wertVektor = c(8, 2, 3)
meinWert == wertVektor[1] | meinWert == wertVektor[2] | meinWert == wertVektor[3][1] TRUEEinfacher ist aber ein sogenannter Existenztest. Dabei wird überprüft, ob ein Wert in einem Vektor vorkommt. Ein solcher Test lässt sich wie in Beispiel 11.5 schreiben:
Beispiel 11.5 (Existstenzprüfung mit %in%)  
meinWert = 3
wertVektor = c(8, 2, 3)
meinWert %in% wertVektor[1] TRUEEntsprechend der Definition des Existenzvergleichs \in funktioniert R’s %in%-Operator auch für Vektoren als linker Operand.
R kennt die beiden Schlüsselworte if und else, um die Ausführung Operationsblöcken an Bedingungen zu knüpfen. Das Schlüsselwort if erwartet einen logischen Ausdruck, der genau einen Wahrheitswert zurückgibt. Logische Ausdrücke mit Vektoren sind damit nicht möglich.
Soll sowohl die Bedingung als auch die Alternative behandelt werden, dann muss das Schlüsselwort else in der gleichen Zeile stehen, wie das Ende des Blocks für die Bedingung.
Beispiel 11.6 (Ungültige Vektorbedingung mit if)  
werte = c(-1, 2, 0, 1)
if (werte > 1) {
    werte = werte - 1
} else {
    werte = 0
}Error in if (werte > 1) {: Bedingung hat Länge > 1Bedingte Operationen sind in R nur selten notwendig. Die einzige relevandte Anwendung ist Datentypkontrolle für Parameter bevor die eigentliche Operation durchgeführt wird.
Beispiel 11.7 (Datentypprüfung mit if)  
if (!is.list(werte)) {
    stop("Variable enthält keine Liste")
}Error in eval(expr, envir, enclos): Variable enthält keine ListeHäufiger als Bedingungen kommen in R vektorisierte Unterscheidungen vor. Dafür stehen zwei Funktionen zur Verfügung:
ifelse()case_when()Die Funktion ifelse() hat drei Parameter und immer einen Vektor als Ergebnis. Die Parameter sind:
TRUE) ergibt.FALSE) ergibt.Die Ergebnisse der beiden Operationen stehen im Ergebnisvektor an den Positionen, an denen der logische Ausdruck Wahr oder Falsch ergab.
Beispiel 11.8 (Vektorisierte Unterscheidung mit ifelse())  
ifelse(werte > 1, werte * 2, 0)[1] 0 4 0 0Die Funktion case_when() erlaubt es, mehrere miteinander verbundene vektorisierte Unterscheidungen in einer Operation durchzuführen. Dazu werden logische Ausdrücke mit Ergebnisoperationen bzw. -Werten verknüpft. Eine Ergebnisoperation wird dann ausgeführt, wenn der zugehörige logische Ausdruck Wahr (TRUE) ergibt. Die logischen Ausdrücke werden in der angegebenen Reihenfolge geprüft, wobei die Operation abbricht, sobald ein logischer Ausdruck Wahr ergibt.
Beispiel 11.9 (case_when() über einen Vektor)  
case_when(
    werte > 0 ~ "positiv",
    werte == 0 ~ "null",
    werte < 0 ~ "negativ" 
)[1] "negativ" "positiv" "null"    "positiv"Für den Fall, dass für einen Wert kein logischer Ausdruck Wahr ergibt, kann ein Rückfallergebnis angegeben werden. Dieses Rückfallergebnis muss mit .default = eingeleitet werden.
Beispiel 11.10 (case_when() mit Rückfallergebnis)  
case_when(
    werte > 0 ~ "positiv",
    werte < 0 ~ "negativ",
    .default = "null"
)[1] "negativ" "positiv" "null"    "positiv"Das Filtern von Werten in Vektoren und Stichproben ist ein zentrales Element von R. Dafür stehen viele Funktionen bereit. Es ist auch möglich über die Index-Operatoren zu filtern.
In der Praxis wird meistens die Funktion filter() zum Auswählen von Datensätzen verwendet. Diese Funktion ermöglicht es, einen Datenrahmen mittels eines logischen Ausdrucks einzuschränken. Die Funktion filter() hat zwei Parameter:
Das Ergebnis ist ein Datenrahmen, der nur Datensätze enthält, für die der logische Ausdruck Wahr (TRUE) ergibt.
Beispiel 11.11 (Filtern)
A B C 1 Name Sprache Einwohner:innen 2 Basel deutsch 173863 3 Genf französisch 203856 4 Lugano italienisch 62315 5 Zug deutsch 30934 6 Zürich deutsch 421878 Für diese Stichprobe möchten wir wissen, wie viele Einwohner in Städten mit mehr als 100000 Einwohnenden leben?
Diese Frage beantworten wir mit der folgenden Logik:
- Alle Städte mit mehr als 100000 Einwohner:innen filtern.
- Die Einwohner:innen der gefilterten Städte zusammenzählen.
Der logische Ausdruck zum Filtern ist
`Einwohner:innen` > 100000, weil dieser Ausdruck nur für die Datensätze Wahr wird, wenn im VektorEinwohner:innender Wert grösser als100000ist. Nach dem Filtern im ersten Schritt liegt nur noch die folgende Stichprobe vor:
A B C 1 Name Sprache Einwohner:innen 2 Basel deutsch 173863 3 Genf französisch 203856 6 Zürich deutsch 421878 Für diese Teilstichprobe muss im zweiten Schritt nur noch die Summe über den Vektor
Einwohner:innengebildet werden.Daraus ergibt sich die folgende Funktionskette:
1read_delim("daten/einwohnende.psv", delim = "|", trim_ws = T, show_col_types = F) |> 2 filter(`Einwohner:innen` > 100000) |> summarise( Gesamteinwohnende = sum(`Einwohner:innen`) )
- 1
read_delim()muss verwendet werden, weil ein besonderes Trennzeichen benutzt wird.- 2
- Filter operation.
# A tibble: 1 × 1 Gesamteinwohnende <dbl> 1 799597
NA-Werte filternDie Funktion drop_na() ist eine spezielle Filterfunktion, deren Ergebnis nur Datensätze enthält, in denen bei keinem Vektor den Wert NA vorkommt. Die Funktion hat keinen Effekt, wenn ein Datenrahmen nur gültige Werte enthält (Beispiel 11.12).
Beispiel 11.12 (drop_na() ohne Effekt)  
Die tidyverse Bibliothek umfasst die tidyselect-Funktionen. Dabei handelt es sich um eine Reihe von Hilfsfunktionen, die die Vektorenauswahl nachvollziehbarer macht. Auf der tidyselect-Homepage finden sich ausführliche Code-Beispiele.
In R können Vektoren mit der Funktion select() selektiert werden. Dieser Funktion werden Regeln übergeben, nach denen die Vektoren auswählt werden sollen. Die einfachste Regel ist die direkte Eingabe der Vektorennamen. Ein typischer Anwendungsfall ist die Datenbereinigung, damit die Funktion drop_na() nicht zu viele Datensätze löscht. Diese Situation kommt vor, wenn ein Datenrahmen viele fehlende Werte enthält, die ungleichmässig in den Vektoren vorkommen. Die Analyse muss deshalb auf die gewünschten Vektoren beschränkt werden.
Für die folgenden Beispiele verwenden wir die Daten der Befragung zum digitalen Umfeld, die mit der read_csv()-Funktion eingelesen wird.
stichprobe = read_csv("daten/befragung_digitales_umfeld/deviceuse.csv") Rows: 76 Columns: 4
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (4): q00_demo_gen, q00_demo_studyload, q01_mob_typ, q12_fav_apps
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.Wir wollen die Vektoren q00_demo_gen (Gender), q00_demo_studyload (Studienmodell) und q01_mob_typ (Mobile OS des Smartphones) auswählen.
Beispiel 11.13 (Direktes selektieren)
stichprobe |>
    select(q00_demo_gen, q00_demo_studyload, q01_mob_typ) |>
    head()# A tibble: 6 × 3
  q00_demo_gen q00_demo_studyload q01_mob_typ       
  <chr>        <chr>              <chr>             
1 Weiblich     Vollzeit           iPhone            
2 Weiblich     Vollzeit           iPhone            
3 Weiblich     Teilzeit           iPhone            
4 Weiblich     Teilzeit           iPhone            
5 Männlich     <NA>               Android Smartphone
6 Weiblich     Vollzeit           iPhone            Durch diesen Aufruf von select() wird der Datenrahmen auf die drei ausgewählten Vektoren reduziert.
Vektoren direkt zu benennen ist eine einfache direkte Methode. Wenn man sehr viele Vektoren auswählen möchte, dann ist es manchmal einfacher, nur die Vektoren anzugeben, die nicht in der Ergebnisstichprobe enthalten sein sollen. Mit select() erreichen wir das, indem wir ein - den ungewollten Vektoren voranstellen.
Das folgende Beispiel selektiert alle Vektoren ausser q00_demo_gen aus der Stichprobe.
Beispiel 11.14 (Selektieren durch Ausschliessen)
stichprobe |>
    select(-q00_demo_gen) |>
    head()Wenn mehrere Vektoren ausgeschlossen werden sollen, dann müssen diese zu einem Vektor zusammengefasst werden.
Beispiel 11.15 (Selektieren durch mehrfaches Ausschliessen)
stichprobe |>
    select(- c(q00_demo_gen, q00_demo_studyload)) |>
    head()Diese Vektorenauswahl wählt alle Vektoren ausser das Geschlecht und das Studienmodell.
Drei leistungsfähige Hilfsfunktionen für select() sind:
starts_with(),ends_with() sowiecontains()Diesen Funktionen akzeptieren einen Teilnamen, über den mehrere Vektoren ausgewählt werden, in denen der angegebene Teil im Vektornamen vorkommt.
Diese Funktionen lassen sich mittels der iris-Stichprobe veranschaulichen.
Beispiel 11.16 (Selektieren mit starts_with())  
iris |>
    select(starts_with("Sepal")) |>  # wählt die Vektoren Sepal.Width und Sepal.Length aus
    head()  Sepal.Length Sepal.Width
1          5.1         3.5
2          4.9         3.0
3          4.7         3.2
4          4.6         3.1
5          5.0         3.6
6          5.4         3.9Beispiel 11.17 (Selektieren mit ends_with())  
iris |>
    select(ends_with("Length")) |> # wählt die Vektoren Petal.Length und Sepal.Length aus
    head()  Sepal.Length Petal.Length
1          5.1          1.4
2          4.9          1.4
3          4.7          1.3
4          4.6          1.5
5          5.0          1.4
6          5.4          1.7Eine weitere Möglichkeit schneller viele Vektoren auszuwählen ist der :-Operator. Damit können wir alle Vektoren zwischen zwei Vektoren inklusive der benannten Vektoren auswählen.
Der folgende Aufruf veranschaulicht dies:
Beispiel 11.18 (Vektorenbereich selektieren)
stichprobe |>
    select(q00_demo_gen:q01_mob_typ) |>
    head()# A tibble: 6 × 3
  q00_demo_gen q00_demo_studyload q01_mob_typ       
  <chr>        <chr>              <chr>             
1 Weiblich     Vollzeit           iPhone            
2 Weiblich     Vollzeit           iPhone            
3 Weiblich     Teilzeit           iPhone            
4 Weiblich     Teilzeit           iPhone            
5 Männlich     <NA>               Android Smartphone
6 Weiblich     Vollzeit           iPhone            Diese Vektorenauswahl wählt die Vektoren q00_demo_gen, q00_demo_studyload und q01_mob_typ für das Ergebnis aus.
Die Reihenfolge von Vektoren kann durch andere Transformationen geändert werden. Deshalb sollte das Selektieren mit Vektorbereichen vermieden werden.
R erlaubt kein Sortieren über logische Ausdrücke. Es ist nur möglich, Werte nach vorgegebenen grösser-kleiner Beziehungen zu sortieren. Deshalb muss für komplexe Sortierungen ein numerischer Hilfsvektor erzeugt werden, der anschliessend sortiert werden kann.
Die Werte eines Vektors werden mit sort() sortiert.
Beispiel 11.19 (Vektorsortierung für zufällige Ganzzahlen)
set.seed(10)
runif(10, min = 1, max = 10) |> trunc() |> sort() [1] 1 3 3 3 3 4 4 5 6 7Die sort()-Funktion kann nur einzelne Vektoren sortieren. Das ist unpraktisch, wenn Daten in einem Datenrahmen vorliegen. In diesem Fall lassen sich die Datensätze mithilfe der Funktion arrange() sortieren. Der Funktion werden die Vektoren übergeben, über die eine neue Reihenfolge festgelegt werden soll. Standardmässig sortiert arrange() aufsteigend. Mit der Hilfsfunktion desc() (engl. descending = absteigen) werden Datensätze entsprechend der Werte im Sortiervektor absteigend sortiert.
Beispiel 11.20 (Absteigende Datenrahmensortierung mit arrange())  
mtcars |>
    as_tibble(rownames = "model") |> 
    select(model, hp, disp, mpg, am) |> 
    arrange(desc(hp)) |> 
    head()# A tibble: 6 × 5
  model                  hp  disp   mpg    am
  <chr>               <dbl> <dbl> <dbl> <dbl>
1 Maserati Bora         335   301  15       1
2 Ford Pantera L        264   351  15.8     1
3 Duster 360            245   360  14.3     0
4 Camaro Z28            245   350  13.3     0
5 Chrysler Imperial     230   440  14.7     0
6 Lincoln Continental   215   460  10.4     0