Search code examples
rdataframeiterationoperatorslogical-operators

Why logical operations in dataframe iteration doesn't return the right values?


I'm trying to perform a logic test on two dataframes. If zero is included in the delimited interval between dataframe elements, the label 'Not Significant' must be included, otherwise, if zero is not included, the label 'Significant' must be included.

The code below works fine, except for the case where a[i,] and b[n,] are negative, where it should include the label 'Significant', it returns 'Not Significant' (line 4). How to solve the problem?

CODE:

a<-c(-1,1,-1,-2,1,0,0,-1)
b<-c(1,1,1,-1,1,1,0,0)
a<-as.data.frame(a)
b<-as.data.frame(b)

ab<-matrix(data=NA)

for (i in 1:nrow(a))
    {
      for (n in 1:nrow(b))
      {
        if (a[i,] <= 0 && b[n,] >= 0) {ab[i]<-c('Not Significant')}
        else {ab[i] <-c('Significant')}
      }
        
    }
c<-cbind(a,b,ab)
c

OUTPUT:

a b ab
-1 1 Not Significant
1 1 Significant
-1 1 Not Significant
-2 -1 Not Significant (Should be Significant)
1 1 Significant
0 1 Not Significant
0 0 Not Significant
-1 0 NotSignificant

Solution

  • There is no need to use a nested loop if we want to compare corresponding elements of a and b columns (as they have the same number of rows). Also, a loop is not needed as these are vectorized operations

    ab <- ifelse(a$a <=0 & b$b >= 0, "Not Significant", "Significant")
    data.frame(a, b, ab)
    

    -output

       a  b              ab
    1 -1  1 Not Significant
    2  1  1     Significant
    3 -1  1 Not Significant
    4 -2 -1     Significant
    5  1  1     Significant
    6  0  1 Not Significant
    7  0  0 Not Significant
    8 -1  0 Not Significant
    

    In the OP's nested loop

     if (a[i,] <= 0 && b[n,] >= 0) {ab[i]<-c('Not Significant')
    

    the ab[i] gets overrided each time it loops over the b[n,] for the same value of a[i,] and thus it returns the output of the last assignment

    Use a print statement to that it becomes more clear

    for (i in 1:nrow(a))
        {
          for (n in 1:nrow(b))
          {
            if (a[i,] <= 0 && b[n,] >= 0) {
               
               ab[i]<-c('Not Significant')
               print(paste("a[i,], b[n,]", "i=", i, "n=", n, a[i,], b[n,], "ab[i]", ab[i]))
               
               
               }
            else {ab[i] <-c('Significant')}
          }
            
        }
    

    -print output for 4th row in 'a'

    ...
    [1] "a[i,], b[n,] i= 4 n= 1 -2 1 ab[i] Not Significant"
    [1] "a[i,], b[n,] i= 4 n= 2 -2 1 ab[i] Not Significant"
    [1] "a[i,], b[n,] i= 4 n= 3 -2 1 ab[i] Not Significant"
    [1] "a[i,], b[n,] i= 4 n= 5 -2 1 ab[i] Not Significant"
    [1] "a[i,], b[n,] i= 4 n= 6 -2 1 ab[i] Not Significant"
    [1] "a[i,], b[n,] i= 4 n= 7 -2 0 ab[i] Not Significant"
    ...
    

    Here, the 4th element for n is not printed as it is in the else loop and thus even it though it is Significant, in the next iteration i.e. 5, it becomes overrided with "Not Significant"