JontroPothon
JontroPothon

Reputation: 534

Ifelse is returning wrong results

Here is my code:

library(lubridate)
library(tidyverse)

day <- c("20", "01")
my <- ifelse(is.na(day), NA, "042020")
value <- c(34, 23)
X <- ifelse(is.na(day), NA, paste(day, my, sep = ""))
Y <- ifelse(is.na(dmy), NA, rep("30042020"))
Z <- c("01082020", "01072020")
data <- data.frame(X, Y, Z, value)
data$X <- lubridate::dmy(X)
data$Y <- lubridate::dmy(Y)
data$Z <- lubridate::dmy(Z)
data

And this is my data:

           X          Y          Z value
1 2020-04-20 2020-04-30 2020-08-01    34
2 2020-04-01 2020-04-30 2020-07-01    23

I have three time variables. I want to create a new variable using two conditions:

I am expecting a new variable called adjValue where the first row should be A and the second row should be B.

This is what I wrote,

data %>% mutate(adjValue = ifelse(Z > Y & Y > X & !is.na(Z) & !is.na(X), "A", ifelse(
  X == ymd(20200401) &  (Z > Y) & !is.na(Z), "B", value)))

           X          Y          Z value adjValue
1 2020-04-20 2020-04-30 2020-08-01    34        A
2 2020-04-01 2020-04-30 2020-07-01    23        A

As one can see, the adjValue second row is showing A instead of my expected B. What did I do wrong here?

Upvotes: 0

Views: 59

Answers (2)

Count Orlok
Count Orlok

Reputation: 1007

The problem with your code is that the second case (the one which you want to annotate as B) is a subset of your first case (the one falling under A). Take the second row for example, which you want to yield B. It's true that Z > Y, that Y > X, and that Z and X are not NA. As such, the first ifelse will return A. The second ifelse is only evaluated if the condition is false.

To make your code work, you simply need to check the conditions for B before those for A.

data %>% mutate(adjValue = ifelse(X == ymd(20200401) & (Z > Y) & !is.na(Z), "B", 
                ifelse(Z > Y & Y > X & !is.na(Z) & !is.na(X), "A", value)))

Upvotes: 1

Duck
Duck

Reputation: 39595

You can try this solution:

library(lubridate)
library(tidyverse)
#Your input
day <- c("20", "01")
my <- ifelse(is.na(day), NA, "042020")
value <- c(34, 23)
X <- ifelse(is.na(day), NA, paste(day, my, sep = ""))
Y <- ifelse(is.na(dmy), NA, rep("30042020"))
Z <- c("01082020", "01072020")
data <- data.frame(X, Y, Z, value)
data$X <- lubridate::dmy(X)
data$Y <- lubridate::dmy(Y)
data$Z <- lubridate::dmy(Z)
data
#Conditions
cond1 <- (data$Z > data$Y) & (data$Y>data$X) & !is.na(data$Z) & !is.na(data$X)
cond2 <- format(data$X,'%d-%m')=='01-04' & (data$Z>data$Y) & !is.na(data$Z)
#Assign valus
data$adjvalue<-NA
data$adjvalue[cond1]<-'A'
data$adjvalue[cond2]<-'B'

           X          Y          Z value adjvalue
1 2020-04-20 2020-04-30 2020-08-01    34        A
2 2020-04-01 2020-04-30 2020-07-01    23        B

Upvotes: 1

Related Questions