简体   繁体   中英

R: "if else if" vs "or" with three cases

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
}

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.

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...

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM