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

2 visualizzazioni (ultimi 30 giorni)
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.

Risposta accettata

Stephen23
Stephen23 il 15 Mar 2024
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 Commenti
Voss
Voss il 18 Mar 2024
Modificato: Voss il 18 Mar 2024
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 il 20 Mar 2024
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)?

Accedi per commentare.

Più risposte (2)

Voss
Voss il 16 Mar 2024
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 il 15 Mar 2024
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.

Categorie

Scopri di più su Matrices and Arrays in Help Center e File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by