Vectorize nested for loops with indices and subscripts

조회 수: 1 (최근 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 CenterFile Exchange에서 Loops 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