Elle Jun
Elle Jun

Reputation: 13

How to write multiple if statement R

I am manipulating raster data in R with the rgdal and raster packages. I want to get rid of all infinite, no values, negative values and replace them with zero:

NoNA <- function (x) { 
    x[is.infinite(x) | is.na(x) | is.nan(x) | is.null(x) | is.na(x < 0)] <- 0
}
ndii_noNA <- calc(ndii, NoNA)

Then the ndii_noNA have only a value of 0. I tried if else statement but it raises an error in

.calcTest(x[1:5], fun, na.rm, forcefun, forceapply).

Is there any way to solve this?

Upvotes: 1

Views: 176

Answers (2)

Taylor White
Taylor White

Reputation: 674

Edit: ifelse() is cleaner but the @cgmil's answer is indeed faster.

    x = rep(c(Inf, -Inf, NULL, NaN, NA, 1), 250e3)

    no_na = function(x){

      ifelse(
        is.infinite(x) | is.na(x) | is.nan(x) | is.null(x) | is.na(x < 0), 0, x
      )

    }


NoNA <- function(x) {
  x[which(is.infinite(x) | is.na(x) | is.nan(x) | is.null(x) | is.na(x < 0))] <- 0
  return(x)
}

microbenchmark(
  no_na(x), NoNA(x),
  times = 50
)

# Unit: milliseconds
# expr      min       lq     mean   median       uq      max neval
# no_na(x) 380.9375 399.7520 416.7729 424.5490 429.6005 451.0534    50
# NoNA(x) 242.8555 249.0034 255.8857 251.3694 254.8176 285.1451    50

Upvotes: 0

cgmil
cgmil

Reputation: 440

You are very close, but have made two errors:

  1. You need to use which() in the index of x, rather than just the truth statement. Otherwise, you will index either x[TRUE] or x[FALSE], which is not what you want. which() will return the indices of all "bad" elements in your vector.
  2. When you make the assignment with <-, the local copy of x will be changed, not the one that was passed. If you want to change x in place, you need to use <<-. That said, you would be wise to stick to R's functional paradigm, in which you would make the change to the local copy, then return it with return(x), rather than change in place.

Here is the function you want:

# The "change in place" method (may be considered bad style)
NoNA <- function(x) {
  x[which(is.infinite(x) | is.na(x) | is.nan(x) | is.null(x) | is.na(x < 0))] <<- 0
}
# The functional way (recommended)
NoNA <- function(x) {
  x[which(is.infinite(x) | is.na(x) | is.nan(x) | is.null(x) | is.na(x < 0))] <- 0
  return(x)
}

Upvotes: 1

Related Questions