Vectorize nested for loops with indices and subscripts

1 visualizzazione (ultimi 30 giorni)
How can I vectorize these nested loops?
A=[1 2 0 2;2 1 3 0;0 3 1 3;2 0 3 1];
matArray=unifrnd(-1,1,[4,4,10]);
m=size(matArray,3);
n=size(unique(A),1)-1;
out=zeros(m,n);
for i = 1 : m
mat=matArray(:,:,i);
for j = 1 : n
out(i,j) = sum(mat(A(:)==j));
end
end
Imo, the main challenge seems to be that if I vectorize i, then I don't seem how to combine indices and subscripts for mat(A(:)==j) to work. I guess one option could be to arrange m copies of A in the same shape as matArray but I am not sure whether that is the best approach.

Risposta accettata

Stephen23
Stephen23 il 24 Apr 2024
Modificato: Stephen23 il 24 Apr 2024
A = [1,2,0,2;2,1,3,0;0,3,1,3;2,0,3,1]
A = 4x4
1 2 0 2 2 1 3 0 0 3 1 3 2 0 3 1
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
matArray = unifrnd(-1,1,[4,4,10])
matArray =
matArray(:,:,1) = 0.9181 -0.9570 0.0497 0.6524 0.4205 -0.6451 -0.5588 -0.5780 0.7118 0.7484 -0.8464 -0.0865 -0.4525 0.2185 0.5790 -0.3427 matArray(:,:,2) = 0.1309 0.5653 -0.5524 -0.1512 0.7527 0.5233 -0.3332 0.9836 0.7834 -0.9420 -0.2268 0.6117 -0.1715 -0.1176 -0.9772 0.9388 matArray(:,:,3) = 0.4596 -0.3614 -0.4097 -0.7903 -0.7122 -0.1399 -0.4565 0.4347 -0.8415 0.8953 0.1029 0.0455 -0.5326 0.2804 -0.8066 0.6261 matArray(:,:,4) = 0.4077 -0.0333 0.4346 -0.9412 0.6351 -0.3117 -0.5348 0.5761 -0.2888 -0.7777 0.9341 0.3771 0.4621 -0.6025 0.6449 0.8022 matArray(:,:,5) = 0.7395 0.6730 0.7379 0.4053 0.1464 -0.0509 0.6831 -0.8796 -0.3895 0.1702 -0.5938 -0.2962 0.4174 0.3532 0.9227 -0.5501 matArray(:,:,6) = 0.2197 0.1687 0.7668 0.8683 -0.4941 0.6725 0.6514 -0.9704 0.3028 -0.1318 0.7828 0.4340 0.2623 0.0420 -0.5201 -0.4108 matArray(:,:,7) = -0.2713 0.9768 0.1635 -0.5738 0.3383 -0.8399 -0.0359 -0.6835 -0.7208 -0.3161 -0.9481 -0.8822 0.0418 0.6457 -0.7966 -0.5913 matArray(:,:,8) = -0.6910 -0.4674 -0.7370 -0.6626 -0.1444 -0.8325 -0.6488 0.3413 0.9821 0.0235 -0.9698 -0.6879 -0.4565 -0.1777 0.1102 0.1591 matArray(:,:,9) = 0.9320 -0.7865 -0.2062 -0.8246 0.6398 0.6122 -0.8366 -0.6873 0.2411 -0.1408 0.5993 -0.9460 -0.4430 0.4233 -0.7198 0.3413 matArray(:,:,10) = -0.7914 -0.1586 0.8757 -0.4813 0.2051 -0.4098 -0.8188 -0.3925 -0.2224 0.6264 0.3945 0.6536 -0.8382 -0.3902 -0.8194 0.9986
Method one:
[X,Y] = meshgrid(1:size(matArray,3),A(:));
Z = Y>0;
B = accumarray([X(Z),Y(Z)],matArray(Z))
B = 10x3
-0.9162 -0.3365 0.6820 1.3662 0.9953 -1.6407 1.0488 -2.3965 -0.3223 1.8324 0.1227 -0.2904 -0.4553 1.6421 1.4797 1.2642 0.8051 0.4335 -2.6506 0.7832 -2.0309 -2.3342 -1.7309 -1.2030 2.4848 -1.4144 -2.6432 0.1919 -1.2730 -0.3581
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
Method two:
[X,Y] = meshgrid(1:size(matArray,3),1+A(:));
B = accumarray([X(:),Y(:)],matArray(:));
B = B(:,2:end)
B = 10x3
-0.9162 -0.3365 0.6820 1.3662 0.9953 -1.6407 1.0488 -2.3965 -0.3223 1.8324 0.1227 -0.2904 -0.4553 1.6421 1.4797 1.2642 0.8051 0.4335 -2.6506 0.7832 -2.0309 -2.3342 -1.7309 -1.2030 2.4848 -1.4144 -2.6432 0.1919 -1.2730 -0.3581
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
Method three:
F = @(n)reshape(sum(matArray.*(n==A),1:2),[],1);
C = arrayfun(F,1:max(A(:)),'uni',0);
B = [C{:}]
B = 10x3
-0.9162 -0.3365 0.6820 1.3662 0.9953 -1.6407 1.0488 -2.3965 -0.3223 1.8324 0.1227 -0.2904 -0.4553 1.6421 1.4797 1.2642 0.8051 0.4335 -2.6506 0.7832 -2.0309 -2.3342 -1.7309 -1.2030 2.4848 -1.4144 -2.6432 0.1919 -1.2730 -0.3581
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
Compared against your approach:
m=size(matArray,3);
n=size(unique(A),1)-1;
out=zeros(m,n);
for i = 1:m
mat = matArray(:,:,i);
for j = 1:n
vec = mat(A(:)==j);
tmp = sum(vec);
out(i,j) = tmp;
end
end
out
out = 10x3
-0.9162 -0.3365 0.6820 1.3662 0.9953 -1.6407 1.0488 -2.3965 -0.3223 1.8324 0.1227 -0.2904 -0.4553 1.6421 1.4797 1.2642 0.8051 0.4335 -2.6506 0.7832 -2.0309 -2.3342 -1.7309 -1.2030 2.4848 -1.4144 -2.6432 0.1919 -1.2730 -0.3581
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>

Più risposte (1)

Brahmadev
Brahmadev il 24 Apr 2024
Hi @OK,
I think we can modify the loop as follows:
for j = 1:n
mask2 = A == j; % Logical indexing for each unique value in A
out2(:, j) = squeeze(sum(sum(space .* mask2, 1), 2)); % Assuming space to be similar to matArray
end
Hope this helps!

Categorie

Scopri di più su Loops and Conditional Statements in Help Center e File Exchange

Prodotti


Release

R2023a

Community Treasure Hunt

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

Start Hunting!

Translated by