Home > OS >  How to use an if condition to select only the values different from NA in a matrix?
How to use an if condition to select only the values different from NA in a matrix?

Time:12-21

I am trying to apply a function on the elements of an array that are different from NA. I tried to use an if statement with the !is.na function but I get an error message saying that the "argument is of length zero". Would someone have an idea on how to fix that error or an alternative way to only select the non NA values of the matrix?

F <- function(x, a, b, c, d) { 
  f <- a*(tanh(b*(x - c)) - d)
  return(f)
}

nlon <- 3241 ; nlat <- 1680
p1 <- 3221 ; p2 <- 1103
pr_new <- matrix(0, nlat, nlon) # for the example 
lim <- 10 

for (n in 1:nlon) {
  a <- -0.5; b <- 1; c <- 0; d <- 1 #Parameters of F
  if (n < p1) { #left side of the step
    for (m in nlat - lim:nlat) {
      if (!is.na(c(pr_new[m, n]))) { #no calculation on the NA values
        pr_new[m, n] <- F(n, a, b, c, d)
      }
    }
  } else { #right side of the step
    if (is.na(c(pr_new[p2, n]))) { #if we are on the upper step
      for (m in p2 - 1:p2 - 1 - lim) {
        if (!is.na(c(pr_new[m, n]))) { #no calculation on the NA values
          pr_new[m, n] <- F(m, a, b, c, d)
        }
      }
    } else { #if we are on the lower step
      for (m in p2:p2 - lim) {
        if (!is.na(c(pr_new[m, n]))) { #no calculation on the NA values
          pr_new[m, n] <- F(m, a, b, c, d)
        }
      }
    }
  }
}

CodePudding user response:

You can find out which value to which a loop-index was set after an error by simply typing the loop-index name at the console:

Error in if (!is.na(c(pr_new[m, n]))) { : argument is of length zero
> m
[1] 0             # R uses 1 based indexing so 0 indexed value is not there
> n
[1] 1
> str( p2:p2-lim)  # demonstrating error
 num 1093

The comment was correct from @zephryl , but it only identified one of the three times that a similar error was made.

 for (m in nlat-lim:nlat){ ...
 for (m in p2-1:p2-1-lim){ ...
 for (m in p2:p2-lim){ ...

In each of these an expression using both colons and minnus signs has been incorrectly contsructed because the ":" has a higher operator precedence than a binary minus sign. You can find the operator precedence rules at the ?Syntax help page.

If you correct those three errors you get code that runs without error.

for (n in 1:nlon){
    a= -0.5; b=1; c=0; d=1 #Parameters of F
    if (n<p1){ #left side of the step
        for (m in (nlat-lim):nlat ){  # fix #1
            if (!is.na(c(pr_new[m,n]))){ #no calculation on the NA values
                pr_new[m,n]=F(n,a,b,c,d)
            }
        }
    }
    else{ #right side of the step
        if (is.na(c(pr_new[p2,n]))) { #if we are on the upper step
            for (m in (p2-1):(p2-1-lim) ){  # fix #2
                if (!is.na(c(pr_new[m,n]))){ #no calculation on the NA values
                    pr_new[m,n]=F(m,a,b,c,d)
                }
            }
        }
        else { #if we are on the lower step
            for (m in p2:(p2-lim) ){   # fix # 3
                if (!is.na(c(pr_new[m,n]))){ #no calculation on the NA values
                    pr_new[m,n]=F(m,a,b,c,d)
                }
            }
        }
    }
}

Regarding the tangential "answer" from a new user of low rep, I did test the theory that it might return a similar answer. I did try chatGPT on some questions and noticed that it not only returned incorrect ansers, but it was alo unable to learn from its mistakes when there were reported to it. When the title and body of the question were given to ChatGPT it gave an almost identical answer to the now-deleted one.

The which function can be used to return a vector of indices from an array or matrix but it is most useful when it is used with the arr.ind parameter is set to its non-default value: ..., arr.in = TRUE. And na.omit can be used to remove cases from matrices. It will however, remove, entire lines of values for any row that contains a single NA.

  • Related