Vectorize nested for loops with indices and subscripts

2 ビュー (過去 30 日間)
OK
OK 2024 年 4 月 24 日
編集済み: Stephen23 2024 年 4 月 24 日
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.

採用された回答

Stephen23
Stephen23 2024 年 4 月 24 日
編集済み: Stephen23 2024 年 4 月 24 日
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>

その他の回答 (1 件)

Brahmadev
Brahmadev 2024 年 4 月 24 日
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!

カテゴリ

Help Center および File ExchangeLoops and Conditional Statements についてさらに検索

製品


リリース

R2023a

Community Treasure Hunt

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

Start Hunting!

Translated by