smars smars - 28 days ago 15
R Question

R: "Error in matrix[i, 1] : incorrect number of dimensions"

With DV and FF as vectors of length 47:

analyse <- function(DV,FF)
{
correct <- rep(0,47)
matrix <- array(rep(0,47*3), dim=c(47,3))

for(i in 1:47)
{
if(DV[i] > 50) {if(FF[i] > 50) {correct[i] <- i}
}
else
{
if(FF[i] < 0){correct[i] <- i}}
}

for(i in 1:47)
{
if((correct[i] == 0) == FALSE)
{
matrix[i,1] <- DV[i]
matrix[i,2] <- FF[i]
matrix[i,3] <- matrix[i,1] - matrix[i,2]
}
}

for(i in 47:1)
{
if(matrix[i,1]==0) {matrix<-matrix[-i]
}
}
return(matrix)
}


I do not understand why I am getting this error:


Error in matrix[i, 1] : incorrect number of dimensions


Thanks in advance

[edit] sample data:

DV <- c(56.2, 59.2, 50.9, 46.9, 50.7, 47.3, 53.6, 57.8, 42.7, 45.0, 47.3, 44.1, 51.5, 50.0, 50.3, 50.4, 51.7, 47.8, 46.8, 40.0, 45.5, 57.4, 51.6, 36.1, 34.8, 41.2, 59.1, 62.5, 55.0, 53.8, 52.4, 44.5, 42.2, 50.1, 61.3, 49.6, 38.2, 51.1, 44.7, 40.8, 46.1, 53.5, 54.7, 50.3, 48.8, 53.7, 52.0)

DF <- c(49.95662, 51.93295, 53.02263, 50.00784, 48.55493, 49.93520, 48.70022, 50.98856, 52.51411, 47.02938, 47.86480, 48.70022, 47.53790, 50.22578, 49.68094, 49.78991, 49.82623, 50.29842, 48.88184, 48.51861, 46.04866, 48.04641, 52.36882, 50.26210, 44.63208, 44.15988, 46.48454, 52.98631, 54.22128, 51.49707, 51.06120, 50.55268, 47.68319, 46.84776, 49.71726, 53.78541, 49.53565, 45.39485, 50.08049, 47.75583, 46.33925, 48.26435, 50.95223, 51.38811, 49.78991, 49.24506, 51.02488)

[edit] result:

Scope of the function it to obtain a matrix which contains:
- every couple of DV[i] and FF[i] which are not both higher (or lower) than 50.
- their difference as third column.

example:

DV[1] = 55
FF[1] = 45

DV > 50 and FF < 50, so I report them in the matrix:

DV[1] -> matrix [1,1]
FF[1] -> matrix[1,2]

Third column being their difference:

matrix[1,3] <- matrix[1,1] - matrix[1,2].

With DV[2] = 55 and FF[2] = 55, analyse() does nothing because they're both higher than 50.

Answer

You can replace the final for loop with a vectorized solution:

analyse <- function(DV,FF)
{
  correct <- rep(0,47)
  matrix <- array(rep(0,47*3),dim=c(47,3))

  for(i in 1:47)
  {
    if( DV[i] > 50 ) { 
      if( FF[i] > 50) {
        correct[i] <- i 
      } 
    }

    else {
      if( FF[i] < 0) {
        correct[i] <- i}
    }
  }

  for(i in 1:47)
  {
    if( (correct[i] == 0) == FALSE)
    {
      matrix[i,1] <- DV[i]
      matrix[i,2] <- FF[i]
      matrix[i,3] <- matrix[i,1] - matrix[i,2]
    }
  }

  matrix <- matrix[ matrix[,1] != 0, ]

  return(matrix)
}

analyse(DV, FF)
#      [,1]     [,2]     [,3]
# [1,] 59.2 51.93295  7.26705
# [2,] 50.9 53.02263 -2.12263
# [3,] 57.8 50.98856  6.81144
# [4,] 51.6 52.36882 -0.76882
# [5,] 62.5 52.98631  9.51369
# [6,] 55.0 54.22128  0.77872
# [7,] 53.8 51.49707  2.30293
# [8,] 52.4 51.06120  1.33880
# [9,] 54.7 50.95223  3.74777
# [10,] 50.3 51.38811 -1.08811
# [11,] 52.0 51.02488  0.97512

But as you mentioned, this is inefficient. There is no need for loops. The below function provides identical output.

analyse2 <- function(DV, FF) {
  indx <- (DV > 50 & FF > 50) | FF < 0
  dif <- DV[indx] - FF[indx]
  matrix(c(DV[indx], FF[indx], dif), ncol=3)
}
analyse2(DV, FF)
#      [,1]     [,2]     [,3]
# [1,] 59.2 51.93295  7.26705
# [2,] 50.9 53.02263 -2.12263
# [3,] 57.8 50.98856  6.81144
# [4,] 51.6 52.36882 -0.76882
# [5,] 62.5 52.98631  9.51369
# [6,] 55.0 54.22128  0.77872
# [7,] 53.8 51.49707  2.30293
# [8,] 52.4 51.06120  1.33880
# [9,] 54.7 50.95223  3.74777
# [10,] 50.3 51.38811 -1.08811
# [11,] 52.0 51.02488  0.97512

all.equal(analyse(DV, FF), analyse2(DV, FF))
[1] TRUE

edit

Based on your description, you want the values less than 50 to be reported to the matrix, not the values greater than 50 as you made in your original function. This is an edited function with an exclamation point added to the second line.

analyse2 <- function(DV, FF) {
  indx <- (!DV > 50 & FF > 50) | FF < 0
  dif <- DV[indx] - FF[indx]
  matrix(c(DV[indx], FF[indx], dif), ncol=3)
}

analyse2(DV, FF)
#      [,1]     [,2]      [,3]
# [1,] 46.9 50.00784  -3.10784
# [2,] 42.7 52.51411  -9.81411
# [3,] 50.0 50.22578  -0.22578
# [4,] 47.8 50.29842  -2.49842
# [5,] 36.1 50.26210 -14.16210
# [6,] 44.5 50.55268  -6.05268
# [7,] 49.6 53.78541  -4.18541
# [8,] 44.7 50.08049  -5.38049

edit 2

With either both greater or lesser than 50.

analyse3 <- function(DV, FF) {
  indx <- !( (DV > 50 & FF > 50) | (DV < 50 & FF < 50) )
  dif <- DV[indx] - FF[indx]
  matrix(c(DV[indx], FF[indx], dif), ncol=3)
}
Comments