Vectorize nested for loops with indices and subscripts

1 Ansicht (letzte 30 Tage)
OK
OK am 24 Apr. 2024
Bearbeitet: Stephen23 am 24 Apr. 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.

Akzeptierte Antwort

Stephen23
Stephen23 am 24 Apr. 2024
Bearbeitet: Stephen23 am 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>

Weitere Antworten (1)

Brahmadev
Brahmadev am 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!

Kategorien

Mehr zu Loops and Conditional Statements finden Sie in Help Center und File Exchange

Produkte


Version

R2023a

Community Treasure Hunt

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

Start Hunting!

Translated by