Home > OS >  R: "if else if" vs "or" with three cases
R: "if else if" vs "or" with three cases

Time:10-24

Im running through some old code to clean it up and saw an old if else if statement that brought up a question in my mind; this is a super simple logic question but for my own edification and to make sure I'm thinking about this logically I wanted to see if a change from the 'old way' to the 'new way', in essence for this case at least, would be the same. My question is: are these two ways of doing this essentially the same?

 #old way
df_test = tibble::as_tibble(data.frame(column1 = NA))

if(NROW(df_test$column1) == 0) {
  df_test = TRUE
} else if (all(is.na(df_test$column1))) {
  df_test = TRUE
} else {
  df_test = FALSE
}

#new way
df_test = tibble::as_tibble(data.frame(column1 = NA))

if(NROW(df_test$column1) == 0 | all(is.na(df_test$column1))) {
  df_test = TRUE
} else {
  df_test = FALSE
}

CodePudding user response:

My question is: are these two ways of doing this essentially the same?

Yes, they are.

To see this, note that in the first code block, TRUE is returned if either NROW(df_test$column1) == 0 or if all(is.na(df_test$column1)) == TRUE.

Thus, the first if .... else if can be replaced by

if(NROW(df_test$column1) == 0 | all(is.na(df_test$column1))) 

and then the 2nd code block immediately follows.

CodePudding user response:

Yet another way of doing this:

df_test = tibble::as_tibble(data.frame(column1 = NA))

df_test <- ifelse(NROW(df_test$column1) == 0 | all(is.na(df_test$column1)), TRUE, FALSE)
df_test 

I believe that this is cleaner...

CodePudding user response:

No, they are not the same

The reason they're not the same is because the | operator always evaluates the operands on both sides. However, in the if(x) else if(y) block, the second if is not evaluated if the first if is true. The difference is particularly important if the expressions being tested involve side-effects, eg if you are modifying files.

Another difference is that | is vectorised, ie it returns a vector of true/false values if its operands are vectors. This is usually not what you want in the context of if blocks, and R will throw a warning if a vector of length >1 is returned.

Simplified example:

foo <- function()
{
    print("in foo")
    TRUE
}

bar <- function()
{
    print("in bar")
    TRUE
}

# case 1
if(foo()) x <- 1 else if(bar()) x <- 1

# case 2
if(foo() | bar()) x <- 1

The first case will print out "in foo" only. The second case will print "in foo" followed by "in bar".

If you want to collapse the if block, use ||, not |. This will only evaluate the right-side operand if the left side is false, and also only returns a scalar value, not a vector. This is consistent with how if behaves.

  • Related