Bedingte Ausdrücke If und Ifelse
Bedingte Ausdrücke sind eines der grundlegenden Merkmale der Programmierung. Sie werden für die so genannte Ablaufsteuerung verwendet. Der häufigste bedingte Ausdruck ist die if-else-Anweisung. In R können wir eine ganze Reihe von Datenanalysen ohne bedingte Ausdrücke durchführen. Sie kommen jedoch gelegentlich vor, und Sie werden sie brauchen, wenn Sie anfangen, Ihre eigenen Funktionen und Pakete zu schreiben.
Wenn-Bedingung mit if
Hier ist ein sehr einfaches Beispiel, das die allgemeine Struktur einer if-else-Anweisung zeigt. Die Grundidee ist, den Kehrwert von a auszugeben, wenn a nicht 0 ist:
a <- 0
if(a!=0){
print(1/a)
} else{
print("No reciprocal for 0.")
}
#> [1] "No reciprocal for 0."
Betrachten wir ein weiteres Beispiel anhand des Datenrahmens für Morde in den USA:
library(dslabs)
data(murders)
murder_rate <- murders$total / murders$population*100000
Hier ist ein sehr einfaches Beispiel, das uns sagt, welche Staaten, wenn überhaupt, eine Mordrate von weniger als 0,5 pro 100.000 haben. Die if-Anweisung schützt uns vor dem Fall, dass kein Staat die Bedingung erfüllt.
ind <- which.min(murder_rate)
if(murder_rate[ind] < 0.5){
print(murders$state[ind])
} else{
print("No state has murder rate that low")
}
#> [1] "Vermont"
Wenn wir es noch einmal mit einem Satz von 0,25 versuchen, erhalten wir eine andere Antwort:
if(murder_rate[ind] < 0.25){
print(murders$state[ind])
} else{
print("No state has a murder rate that low.")
}
#> [1] "No state has a murder rate that low."
Ifelse Bedingung
Eine verwandte Funktion, die sehr nützlich ist, ist ifelse. Diese Funktion hat drei Argumente: ein logisches und zwei mögliche Antworten. Wenn die Logik TRUE ist, wird der Wert im zweiten Argument zurückgegeben und wenn FALSE, wird der Wert im dritten Argument zurückgegeben. Hier ist ein Beispiel:
a <- 0
ifelse(a > 0, 1/a, NA)
#> [1] NA
Die Funktion ist besonders nützlich, weil sie mit Vektoren arbeitet. Sie prüft jeden Eintrag des logischen Vektors und gibt Elemente aus dem im zweiten Argument angegebenen Vektor zurück, wenn der Eintrag TRUE ist, oder Elemente aus dem im dritten Argument angegebenen Vektor, wenn der Eintrag FALSE ist.
a <- c(0, 1, 2, -4, 5)
result <- ifelse(a > 0, 1/a, NA)
Hilfreiche Anwendung: alle fehlenden Werte mit Null ersetzen
Das folgende Beispiel zeigt, wie diese Funktion leicht verwendet werden kann, um alle fehlenden Werte in einem Vektor durch Nullen zu ersetzen:
data(na_example)
no_nas <- ifelse(is.na(na_example), 0, na_example)
sum(is.na(no_nas))
#> [1] 0
Funktionen in R Studio
Mit zunehmender Erfahrung werden Sie feststellen, dass Sie die gleichen Operationen immer wieder durchführen müssen. Ein einfaches Beispiel ist die Berechnung von Durchschnittswerten. Wir können den Durchschnitt eines Vektors x mit den Funktionen Summe und Länge berechnen: Summe(x)/Länge(x). Da wir dies wiederholt tun, ist es viel effizienter, eine Funktion zu schreiben, die diese Operation ausführt. Diese spezielle Operation ist so häufig, dass bereits jemand die Mittelwertfunktion geschrieben hat und sie in der Basis von R enthalten ist. Sie werden jedoch auf Situationen stoßen, in denen die Funktion noch nicht vorhanden ist. Eine einfache Version einer Funktion, die den Mittelwert berechnet, kann wie folgt definiert werden:
avg <- function(x){
s <- sum(x)
n <- length(x)
s/n
}
Nun ist avg eine Funktion, die den Mittelwert berechnet:
x <- 1:100
identical(mean(x), avg(x))
#> [1] TRUE
Beachten Sie, dass Variablen, die innerhalb einer Funktion definiert sind, nicht im Arbeitsbereich gespeichert werden. Wenn wir also s und n verwenden, wenn wir avg aufrufen, werden die Werte nur während des Aufrufs erstellt und geändert. Hier ist ein anschauliches Beispiel:
s <- 3
avg(1:10)
#> [1] 5.5
s
#> [1] 3
Die von Ihnen definierten Funktionen können mehrere Argumente und auch Standardwerte haben. Wir können zum Beispiel eine Funktion definieren, die entweder den arithmetischen oder den geometrischen Mittelwert in Abhängigkeit von einer benutzerdefinierten Variable wie folgt errechnet:
avg <- function(x, arithmetic = TRUE){
n <- length(x)
ifelse(arithmetic, sum(x)/n, prod(x)^(1/n))
}
For-loops | for Schleifen
Angenommen wir erstellen eine Funktion, dass die Summe jeder Zahl aufsummiert:
compute_s_n <- function(n){
x <- 1:n
sum(x)
}
Das vielleicht einfachste Beispiel für eine for-Schleife ist dieses nutzlose Stück Code:
for(i in 1:5){
print(i)
}
#> [1] 1
#> [1] 2
#> [1] 3
#> [1] 4
#> [1] 5
# a for-loop for our summation
m <- 25
s_n <- vector(length = m) # create an empty vector
for(n in 1:m){
s_n[n] <- compute_s_n(n)
}
# creating a plot for our summation function
n <- 1:m
plot(n, s_n)
# a table of values comparing our function to the summation formula
head(data.frame(s_n = s_n, formula = n*(n+1)/2))
Überlagerung unserer Funktion mit der Summenformel
plot(n, s_n)
lines(n, n*(n+1)/2)
R Studio gibt uns bessere Möglichkeiten zur Hand, als for Schleifen.
Aber das Konzept ist immer noch wichtig, daher ist es gut, dass wir for-Schleifen behandelt haben. Funktionen, die typischerweise anstelle von for-Schleifen in R verwendet werden sind apply, sapply, tapply und mapply. Weitere Funktionen, die wir nicht im Detail betrachten sind: split, cut, quantile, reduce, identical, unique.
Hier gibt es mehr Informationen dazu.
Übung
# Assign the state abbreviation when the state name is longer than 8 characters
new_names <- ifelse(nchar(murders$state)>8, murders$abb, murders$state)
# Create function called `sum_n`
sum_n <- function(n){
x <- 1:n
sum(x)
}
# Use the function to determine the sum of integers from 1 to 5000
sum_n(5000)
Create a function altman_plot
that takes two arguments x
and y
and plots y-x
(on the y-axis) against x+y
(on the x-axis).
Note: don’t use parentheses around the arguments in the plot
function because you will confuse R.
# Create `altman_plot`
altman_plot <- function(x, y){
plot(x+y, y-x)
}
# Here is an example of a function that adds numbers from 1 to n
example_func <- function(n){
x <- 1:n
sum(x)
}
# Here is the sum of the first 100 numbers
example_func(100)
# Write a function compute_s_n with argument n that for any given n computes the sum of 1 + 2^2 + ...+ n^2
compute_s_n <- function(n){
x <- 1:n
sum(x^2)
}
# Report the value of the sum when n=10
compute_s_n(10)
dd
# Define a function and store it in `compute_s_n`
compute_s_n <- function(n){
x <- 1:n
sum(x^2)
}
# Create a vector for storing results
s_n <- vector("numeric", 25)
# write a for-loop to store the results in s_n
for(i in 1:25){
s_n[i] <- compute_s_n(i)
}
Definieren Sie einen leeren numerischen Vektor s_n der Größe 25 mit s_n <- vector(„numeric“, 25).
Berechnen Sie die Summe, wenn n gleich jeder ganzen Zahl von 1 bis 25 ist, indem Sie die Funktion verwenden, die wir in der vorherigen Übung definiert haben: compute_s_n
Speichern Sie die Ergebnisse in s_n
# Define a function and store it in `compute_s_n`
compute_s_n <- function(n){
x <- 1:n
sum(x^2)
}
# Create a vector for storing results
s_n <- vector("numeric", 25)
# write a for-loop to store the results in s_n
for(i in 1:25){
s_n[i] <- compute_s_n(i)
}
- Define
n <- 1:25
. Note that with this we can usefor(i in n)
- Use a for loop to save the sums into a vector
s_n <- vector("numeric", 25)
- Plot
s_n
(on the y-axis) againstn
(on the x-axis).
# Define the function
compute_s_n <- function(n){
x <- 1:n
sum(x^2)
}
# Define the vector of n
n <- 1:25
# Define the vector to store data
s_n <- vector("numeric", 25)
for(i in n){
s_n[i] <- compute_s_n(i)
}
# Create the plot
plot(n, s_n)
Weitere Übung
Aufgabe 1: Schreiben Sie eine ifelse()-Anweisung, die 1 zurückgibt, wenn das Geschlecht weiblich ist, und 2, wenn das Geschlecht männlich ist. Wie lautet die Summe des resultierenden Vektors?
library(dslabs)
data(heights)
str(heights)
coded_sex <- ifelse(heights$sex == "Female", 1, 2)
sum(coded_sex)
Aufgabe 2: Schreiben Sie eine ifelse()-Anweisung, die die Höhenspalte nimmt und die Höhe zurückgibt, wenn sie größer als 72 Zoll ist, und ansonsten 0 zurückgibt. Was ist der Mittelwert des resultierenden Vektors?
library(dplyr)
new_height <- mutate(heights, t_height = ifelse(heights$height > 72, heights$height, 0))
new_height <- filter(new_height, height>72)
mean(new_height$height)