Vectorization: incompatible sizes of arrays

O is a matrix with n_p x n_o rows; P is a matrix with n_p rows. Both matrices have three columns.The second column in O should be filled with the average of two values in the second column of P: the first value at the row ip and the second value at randomly selected row.
counter = 0;
for ip = 1:n_p
for io = 1:n_o
counter = counter + 1;
O(counter,2) = (P(ip,2) + P(randi(n_p),2))/2;
end
end
I attempted to vectorize the code as:
ip = 1:n_p;
io = 1:n_o;
O(ip(:)+io(:),2) = (P(ip(:),2)+P(randi(n_p),2))/2;
I am receiving the following message: „Arrays have incompatible sizes for this operation“. Thank you for any suggestions.

 Accepted Answer

n_p = 3;
n_o = 3;
P = rand(n_p,2);
R = randi(n_p,n_p*n_o,1)
R = 9×1
3 2 2 2 3 1 3 2 1
IP = (cell2mat(arrayfun(@(i)vertcat(repmat(i,1,n_o)),1:n_p,'UniformOutput',0))).'
IP = 9×1
1 1 1 2 2 2 3 3 3
O(:,2) = (P(IP,2)+P(R,2))/2
O = 9×2
0 0.8950 0 0.5663 0 0.5663 0 0.2625 0 0.5912 0 0.5663 0 0.9199 0 0.5912 0 0.8950

3 Comments

Thank you. I like this solution and I learned something new.
IP = (cell2mat(arrayfun(@(i)vertcat(repmat(i,1,n_o)),1:n_p,'UniformOutput',0))).'
can be simplified to
IP = replem((1:n_p)',n_o)
Or:
IP = reshape(repmat(1:n_p,n_o,1),n_p*n_o,1)
But yours is shorter :-)

Sign in to comment.

More Answers (2)

Simpler one liner
O(:,2) = P(randi(end,n_o,end),2) + repelem(P(:,2),n_o) / 2;
O(:,2) = reshape(reshape(P(randi(end,n_o,end),2),n_o,[]) + reshape(P(:,2),1,[]), [],1) / 2;

2 Comments

I just checked and it seems to work equally. I like your approach very much, never thought this could be done in a single line. Thank you!
Good.
It is not easy to check the correctness due to randomness.

Sign in to comment.

Categories

Products

Release

R2022b

Asked:

on 18 Sep 2022

Commented:

on 19 Sep 2022

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!