Vectorize nested for loops with indices and subscripts

1 vue (au cours des 30 derniers jours)
OK
OK le 24 Avr 2024
Modifié(e) : Stephen23 le 24 Avr 2024
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.

Réponse acceptée

Stephen23
Stephen23 le 24 Avr 2024
Modifié(e) : Stephen23 le 24 Avr 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>

Plus de réponses (1)

Brahmadev
Brahmadev le 24 Avr 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!

Catégories

En savoir plus sur Loops and Conditional Statements dans Help Center et File Exchange

Produits


Version

R2023a

Community Treasure Hunt

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

Start Hunting!

Translated by