Matrixwise subtraction yields vector - how to reshape to original logical matrix?

조회 수: 2 (최근 30일)
Hi,
I am working with a large dataset for which I need to do multiple substractions between vectors, then summing across logically indexed values. Currently, I index the vector subtraction in a for loop, but it takes forever as I have to run that loop ~ 1.5M, several times, so I would like to move to matrixwise calculations.
Below is a short version of the crux of my question. If I have a matrix A and a matrix B, and I index the values I am interested in using a logical matrix (cmpMatrix), then I subtract B from A and want to get the mean per column. However, the logical indexing always reshapes into a vector, not a matrix:
A = rand(3);
B = rand(3);
cmpMatrix = A>=0.5 %in my situation, there are always unequal numbers of 0s and 1s per column
cmpMatrix =
3×3 logical array
1 0 1
0 1 1
1 0 0
%Issue: ans for the following line is a vector.
A(cmpMatrix)
ans =
0.9612
0.7870
0.9437
0.9813
0.5702
I'd like to take the mean of all the values that are indexed per column, so I'd need to be able to backtrack where the values in the vector came from. Ideally, I'd be able to do something like:
mean(A(cmpMatrix) - B(cmpMatrix),2)
And receive a 1 x 3 vector where B was subtracted from A at each logical 1, and then the mean was taken across the matrix columns, so as to get a mean per column.
How do I achieve that?
Thank you for your help.

채택된 답변

Stephen23
Stephen23 2024년 3월 15일
A = rand(3);
B = rand(3);
X = A>=0.5;
[~,C] = find(X);
M = accumarray(C,A(X)-B(X),[],@mean).'
M = 1×3
0.6699 0.0500 0.5998
  댓글 수: 7
Voss
Voss 2024년 3월 18일
편집: Voss 2024년 3월 18일
They're equal up to round-off error:
A = rand(104,8193);
B = rand(104,8193);
max(abs(Stephen(A,B)-Voss(A,B)),[],'all')
ans = 1.6653e-16
function M = Stephen(A,B)
X = A>=0.5;
[~,C] = find(X);
M = accumarray(C,A(X)-B(X),[],@mean).';
end
function M = Dyuman(A,B)
[m,n] = size(A);
Y = repmat(1:n,m,1); % modification for non-square A
X = A>=0.5;
M = accumarray(Y(X),A(X)-B(X),[],@mean).';
end
function result = Walter1(A,B)
cmpMatrix = A>=0.5;
result = arrayfun(@(IDX) mean(A(cmpMatrix(:,IDX),IDX)-B(cmpMatrix(:,IDX),IDX)), 1:size(A,2));
end
function result = Walter2(A,B)
cmpMatrix = A>=0.5;
result = cellfun(@mean, mat2cell(A(cmpMatrix) - B(cmpMatrix), sum(cmpMatrix,1), 1)).'; % removing temp variable, and transposing for consistency with other methods
end
function result = Voss(A,B)
A_temp = A;
B_temp = B;
idx = A >= 0.5;
A_temp(~idx) = NaN;
B_temp(~idx) = NaN;
result = mean(A_temp-B_temp,1,'omitnan');
end
Dyuman Joshi
Dyuman Joshi 2024년 3월 20일
I know and understand that they are round-off error; my point is why does it only occur in a single method and not in others, when all the methods use the same function (essentially the same operation)?

댓글을 달려면 로그인하십시오.

추가 답변 (2개)

Voss
Voss 2024년 3월 16일
A_temp = A;
B_temp = B;
idx = A >= 0.5;
A_temp(~idx) = NaN;
B_temp(~idx) = NaN;
result = mean(A_temp-B_temp,1,'omitnan');

Walter Roberson
Walter Roberson 2024년 3월 15일
One way:
result = arrayfun(@(IDX) mean(A(cmpMatrix(:,IDX),IDX)-B(cmpMatrix(:,IDX),IDX)), 1:size(A,2))
Chances are that this will be slower than looping.
Another way:
temp = A(cmpMatrix) - B(cmpMatrix);
result = cellfun(@mean, mat2cell(temp, sum(cmpMatrix,1), 1));
It would not surprise me if this is slower than looping.

카테고리

Help CenterFile Exchange에서 Matrices and Arrays에 대해 자세히 알아보기

Community Treasure Hunt

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

Start Hunting!

Translated by