Home > OS >  ifelse command always returns 0 if condition contains `years` function from package lubridate
ifelse command always returns 0 if condition contains `years` function from package lubridate

Time:06-25

I have an ifelse condition where I want to return a years value from package lubridate.

However, it does return 0 inside the ifelse and I have no idea why.

library(lubridate)

years(1)

[1] "1y 0m 0d 0H 0M 0S" # correct

years(2)

[1] "2y 0m 0d 0H 0M 0S" # correct

ifelse(1 == 1, years(1), years(2))

[1] 0 # wrong

Can anyone explain why the ifelse returns 0?

CodePudding user response:

Here is why it happens. This is from the bottom of source code of ifelse, which will run in your example.

ans <- test
len <- length(ans)
ypos <- which(test)
npos <- which(!test)
if (length(ypos) > 0L) 
  ans[ypos] <- rep(yes, length.out = len)[ypos]
if (length(npos) > 0L) 
  ans[npos] <- rep(no, length.out = len)[npos]
ans

The function is modifying the ans vector by element, not the entire vector itself. So therefore the attributes from yes and no are being dropped.

ans <- TRUE
ans[1] <- years(1)

ans
# [1] 0

Below is from the the help file. The "mode of the answer will be coerced from logical" starting with the yes values first.

mode(years(1))
# [1] "numeric"

Value

A vector of the same length and attributes (including dimensions and "class") as test and data values from the values of yes or no. The mode of the answer will be coerced from logical to accommodate first any values taken from yes and then any values taken from no.

CodePudding user response:

Due to the way it constructs its output, ifelse strips the attributes from a vector. This is not unique to lubridate::year. It also happens with, for example, dates and date-times

ifelse(1 == 1, as.Date("2022-06-24"), as.Date("2022-06-25"))
#> [1] 19167

Using dplyr::if_else avoids this problem:

dplyr::if_else(1 == 1, years(1), years(2))
#> [1] "1y 0m 0d 0H 0M 0S"

And obviously the low-tech fix is to do:

years(ifelse(1 == 1, 1, 2))
#> [1] "1y 0m 0d 0H 0M 0S"
  • Related