0

I have an array of matrices which are all different lengths. I want to compare the distance of each item in matrix 1 to the items in matrix 2 and so on. The for loops I've written below work well except when it reaches a matrix which is length 2. The loop continues to xx = 3 and then calls an error ("Index in position 1 exceeds array bounds. Index must not exceed 2.") because there is no current_mat(3,:). Why is it doing this only for matrices of length 2? I'm relatively new to matlab, so apologies if this is a simple question. Here are some toy data that give the same error I am seeing with a larger dataset.

matrix_1 = ones(16,3)
matrix_2 = ones(14,3)
matrix_3 = ones(2,3)
matrix_4 = ones(10,3)
my_array = {matrix_1; matrix_2; matrix_3; matrix_4}

for ii = 1:length(my_array)-1;
    current_mat = my_array{ii};
    compare_mat = my_array{ii+1};
    for xx = 1:length(current_mat);
        xx_info = current_mat(xx,:);
    end
end
Susanna
  • 3
  • 1
  • I would recommend that you never, ever use `length`. It is useless. `numel` is faster for vectors, or be explicit about which size you want with matrices: `size(…, dim)`. – Cris Luengo Jan 13 '22 at 06:20

2 Answers2

1

The issue is that when given a matrix input length returns the longest dimension of the matrix, not the number of rows. In the case of your matrix_3 this is 3 although it appears that you expect 2. So xx goes from 1 to 3 and in line 11 you attempt to access a row that doesn't exist when xx=3. Better would be to explicitly loop across the m dimension. You can do this with size which returns the number of rows and columns in the matrix:

matrix_1 = ones(16,3)
matrix_2 = ones(14,3)
matrix_3 = ones(2,3)
matrix_4 = ones(10,3)
my_array = {matrix_1; matrix_2; matrix_3; matrix_4}

for ii = 1:length(my_array)-1;
    current_mat = my_array{ii};
    compare_mat = my_array{ii+1};
    [m,n] = size(current_mat); % <-- use size here, not length
    for xx = 1:m;
        xx_info = current_mat(xx,:);
    end
end 

or, if you wish to look at the columns:

matrix_1 = ones(16,3)
matrix_2 = ones(14,3)
matrix_3 = ones(2,3)
matrix_4 = ones(10,3)
my_array = {matrix_1; matrix_2; matrix_3; matrix_4}

for ii = 1:length(my_array)-1;
    current_mat = my_array{ii};
    compare_mat = my_array{ii+1};
    [m,n] = size(current_mat); % <-- use size here, not length
    for xx = 1:n;
        xx_info = current_mat(:,xx);
    end
end 
dmedine
  • 1,430
  • 8
  • 25
  • i realize that OP's internal FOR loop doesn't really do a comparison, but if you compare across rows, it will still give an error, won't it?. Shouldn't OP be comparing across columns which will be consistent in this case? – whoknowsmerida Jan 13 '22 at 03:09
  • 1
    I wouldn't presume to read into that. I don't know what the OP wishes to compare. I updated the answer to show both ways. – dmedine Jan 13 '22 at 03:15
  • This explains the problem nicely, but fixes it with awkward syntax. OP needs to replace `length(current_mat)` with `size(current_mat,1)`. There is no need to extract two values if one only needs one of them. – Cris Luengo Jan 13 '22 at 06:18
0

This code should work for you. You didn't specifically specify the length of columns (or rows) as the determinant,

matrix_1 = ones(16,3);
matrix_2 = ones(14,3);
matrix_3 = ones(2,3);
matrix_4 = ones(10,3);
my_array = {matrix_1; matrix_2; matrix_3; matrix_4};

for ii = 1:length(my_array)-1
    current_mat = my_array{ii};
    compare_mat = my_array{ii+1};
    for xx = 1:size(current_mat,2)  % length of columns
        xx_info = current_mat(:,xx);  % Can compare across columns, since no of columns are consistent across multiple matrices
    end
end
whoknowsmerida
  • 134
  • 2
  • 10
  • It is not correct to say the OP used 'length of rows as opposed to ... columns'. As I pointed out `length` returns the length of the longest dimension, not number of rows/columns. – dmedine Jan 13 '22 at 03:18
  • ok. fair enough. I'll delete my answer since you've covered both. Thought i'd let you know before i delete it. – whoknowsmerida Jan 13 '22 at 03:36