Det är omöjligt att arbeta med analys av data utan att använda villkor för att skapa eller modifiera variabler. De mest använda funktionerna för villkor är ifelse()
(från base R), if_else()
(från dplyr) och case_when()
(från dplyr).
I detta kapitel kommer vi demonstrera funktionerna med hjälp av data som vi själva genererar direkt i R med funktionen tibble()
:
my_data <- tibble(Var1 = c(NA, 5, 9, 5, 3, 4, 10, 20, 30),
Var2 = c(1, NA, 3, 6, 1, 12, 0, 12, 3),
Var3 = c("Ja", "Nej", NA, "Ja", "Ja", "Ja", "Ja", "Nej", NA),
Var4 = rnorm(9), # genererar 9 slumpvärden med normalfördelning
Var5 = letters[1:9]) # första 9 bokstäverna i alfabetet
my_data
Var1 Var2 Var3 Var4 Var5
NA 1 Ja -0.234 a
5 NA Nej 0.794 b
9 3 NA 0.834 c
5 6 Ja -1.40 d
3 1 Ja -0.818 e
4 12 Ja 0.688 f
10 0 Ja 0.218 g
20 12 Nej -2.14 h
30 3 NA -0.449 i
ifelse()
Med ifelse()
från base definieras ett villkor med följande syntax:
ifelse(VILLKORET, OM_SANT, OM_FALSKT)
- I första position (
VILLKORET
) specificeras villkoret. - I andra position (
OM_SANT
) specificeras vad funktionen skall returnera om villkoret är sant. - I tredje position (
OM_FALSKT
) specificeras vad funktionen skall returnera om villkoret är falskt.
Vi använder nu denna funktion för att skapa en ny variabel kallad ny_variabel
. Denna variabeln får värdet 0 om Var är mindre än 5 och i annat fall 1:
BLOCKERAD KOD, BILD ELLER TEXT
Du måste logga in för att komma åt allt material.
Var1 Var2 Var3 Var4 Var5 ny_variabel
NA 1 Ja 0.276 a NA
5 NA Nej 1.15 b 1
9 3 NA 0.162 c 1
5 6 Ja -0.517 d 1
3 1 Ja 1.36 e 0
4 12 Ja -0.454 f 0
10 0 Ja -0.445 g 1
20 12 Nej 0.394 h 1
30 3 NA -0.642 i 1
Det fungerade med undantag för att första observationen fick NA
(missing) på ny_variabel
. Förklaringen till detta är enkel: den observationen saknar information om Var1
och då kan inte villkoret utvärderas. Vi kan däremot specificera i villkoret hur NA
ska hanteras. I nästa exempel utökar vi villkoret så att även missing (NA) får värdet 0. Detta gör vi genom att använda funktionen is.na()
och operanden |
som betyder "eller".
BLOCKERAD KOD, BILD ELLER TEXT
Du måste logga in för att komma åt allt material.
Var1 Var2 Var3 Var4 Var5 ny_variabel
1 NA 1 Ja 0.276 a 0
2 5 NA Nej 1.15 b 1
3 9 3 NA 0.162 c 1
4 5 6 Ja -0.517 d 1
5 3 1 Ja 1.36 e 0
6 4 12 Ja -0.454 f 0
7 10 0 Ja -0.445 g 1
8 20 12 Nej 0.394 h 1
9 30 3 NA -0.642 i 1
ifelse()
kan bli krånglig om flera villkor behöver utvärderas sekventiellt, vilket är mycket vanligt. För att göra detta med ifelse()
måste det tredje argumentet ersättas med en ny ifelse()
. Ett exempel på detta följer:
BLOCKERAD KOD, BILD ELLER TEXT
Du måste logga in för att komma åt allt material.
Var1 Var2 Var3 Var4 Var5 ny_variabel
1 NA 1 Ja 0.276 a NA
2 5 NA Nej 1.15 b Mindre än 7
3 9 3 NA 0.162 c Mindre än 10
4 5 6 Ja -0.517 d Mindre än 7
5 3 1 Ja 1.36 e Mindre än 4
6 4 12 Ja -0.454 f Mindre än 7
7 10 0 Ja -0.445 g Övriga
8 20 12 Nej 0.394 h Övriga
9 30 3 NA -0.642 i Övriga
Notera att det sista argumentet (ovan specificerat som "Övriga"
) är värdet som skall retuernas om inget av villkoren stämmer. Notera också att allra sist måste samtliga parenteser stängas.
if_else()
I dplyr finns funktionen if_else()
som liknar ifelse()
. Skillnaderna mellan dessa funktioner demonstreras nedan.
if_else() är mer strikt än ifelse()
Observera följande kommando och resultat med ifelse()
:
BLOCKERAD KOD, BILD ELLER TEXT
Du måste logga in för att komma åt allt material.
Var1 Var2 Var3 Var4 Var5 ny_variabel
1 NA 1 Ja 0.276 a NA
2 5 NA Nej 1.15 b 0
3 9 3 NA 0.162 c 0
4 5 6 Ja -0.517 d 0
5 3 1 Ja 1.36 e Mindre än 4
6 4 12 Ja -0.454 f 0
7 10 0 Ja -0.445 g 0
8 20 12 Nej 0.394 h 0
9 30 3 NA -0.642 i 0
Det verkar som att koden fungerade. Nu upprepas identisk kod med undantag för att ifelse() ersätts med if_else():
BLOCKERAD KOD, BILD ELLER TEXT
Du måste logga in för att komma åt allt material.
Error in `mutate()`:
! Problem while computing `ny_variabel = if_else(Var1 < 4, "Mindre än 4", 0)`.
Caused by error in `if_else()`:
! `false` must be a character vector, not a double vector.
Detta resulterade däremot i error. Förklaringen till detta är att villkoret returnerar en textsträng ("Mindre än 4") om det är sant och ett numeriskt värde (0) om det är falskt. Detta ogillas av if_else() för att värdena som kan returneras skall vara av samma typ.
if_else() konverterar inte datumvariabler till numeriska värden
Se följande exempel med resultat med ifelse():
BLOCKERAD KOD, BILD ELLER TEXT
Du måste logga in för att komma åt allt material.
[1] "Numeric"
Samma kod upprepas med ifelse()
ersätts med if_else()
:
# Skapar 3 datum med funktionerna c() och ymd()
my_dates <- ymd(c('2021-10-01', '2022-10-02', '2021-10-03'))
# Utvärderar ett villkor och sparar som nytt objekt
my_dates_2 <- if_else(my_dates == '2022-10-02', my_dates + 1, my_dates)
# Visa vilken klass vektorn har
class(my_dates_2)
[1] "Date"
if_else() har ett extra argument för missing
Vi upprepar första exemplet, men nu med if_else() och specificerar ett värde på missing:
BLOCKERAD KOD, BILD ELLER TEXT
Du måste logga in för att komma åt allt material.
Var1 Var2 Var3 Var4 Var5 ny_variabel
1 NA 1 Ja 0.276 a Saknas
2 5 NA Nej 1.15 b 4 eller mer
3 9 3 NA 0.162 c 4 eller mer
4 5 6 Ja -0.517 d 4 eller mer
5 3 1 Ja 1.36 e Mindre än 4
6 4 12 Ja -0.454 f 4 eller mer
7 10 0 Ja -0.445 g 4 eller mer
8 20 12 Nej 0.394 h 4 eller mer
9 30 3 NA -0.642 i 4 eller mer
if_else() är snabbare än ifelse()
Sist men inte minst är if_else()
snabbare än ifelse()
.
case_when()
Istället för att skapa nestade ifelse()
eller if_else()
satser kan case_when()
användas. Denna funktionen gör det möjligt att med effektiv syntax specificera en rad sekventiella villkor. Villkoren testas ett i taget. Notera att med case_when()
används ~
. Till vänster om ~
anges villkoret, och till höger om ~
anges värdet som funktionen skall returnera om villkoret stämmer. Notera att vi kan specificera missing med funktionen is.na()
.
BLOCKERAD KOD, BILD ELLER TEXT
Du måste logga in för att komma åt allt material.
Var1 Var2 Var3 Var4 Var5 ny_variabel
1 NA 1 Ja 0.276 a Saknas
2 5 NA Nej 1.15 b Större än 3
3 9 3 NA 0.162 c Större än 3
4 5 6 Ja -0.517 d Större än 3
5 3 1 Ja 1.36 e Lika med 3
6 4 12 Ja -0.454 f Större än 3
7 10 0 Ja -0.445 g Större än 3
8 20 12 Nej 0.394 h Större än 3
9 30 3 NA -0.642 i Större än 3