select elements of matrix from indices defined in an array
2 visualizzazioni (ultimi 30 giorni)
Mostra commenti meno recenti
Say I have a 4x3 matrix of non-zero elements (A):
A = (0.1299 0.3371 0.5285
0.5688 0.1622 0.1656
0.4694 0.7943 0.6020
0.0119 0.3112 0.2630)
and two 1x3 arrays B and C such as:
B = (1 2 4)
C = (2 3 4)
I would like to build a matrix D that selects rows 1 to 5 from column 1, 2 to 3 from column 2 and row 4 from column 3...
D = (0.1299 0 0
0.5688 0.1622 0
0 0.7943 0.6020
0 0 0)
I am using a for loop to do it which is quite inefficient.. Any suggestions? Thanks!
2 Commenti
Jan
il 12 Ago 2017
Modificato: Jan
il 12 Ago 2017
You mean: "Rows 1 to 2 from column 1."
In the example you have chosen the 3. row of column 3, not the 4th one.
It is a good strategy to post the data in valid Matlab syntax to allow for an easy using to test the suggested solutions: It is not much work to replace the parenthesis by square brackets for valid Matlab matrices. But if you do this, it has to be done once only.
Please check your question before posting. It is not efficient, if the readers guess the details.
If you post your code, we could see the problem of the loop method.
Risposta accettata
Jan
il 12 Ago 2017
Modificato: Jan
il 12 Ago 2017
Nope, a loop is efficient here:
A = [0.1299 0.3371 0.5285; ...
0.5688 0.1622 0.1656; ...
0.4694 0.7943 0.6020; ...
0.0119 0.3112 0.2630];
B = [1 2 4];
C = [2 3 4];
D = zeros(size(A));
for k = 1:numel(B)
D(B(k):C(k), k) = A(B(k):C(k), k);
end
A vectorized version:
[s1, s2] = size(A);
sp = [s1 + 1, s2];
M = zeros(sp);
M(sub2ind(sp, B, 1:s2)) = 1;
M(sub2ind(sp, C + 1, 1:s2)) = -1;
M = cumsum(M(1:s1, :), 1);
D = A .* M;
Some timings (R2016b, Win7/64, Core2Duo):
A = rand(1000, 1000);
BB = randi(1000, 1, 1000);
CC = randi(1000, 1, 1000);
B = min(BB, CC);
C = max(BB, CC);
tic; for q = 1:100; D = fcn(A, B, C); end, toc
Elapsed time is 1.052819 seconds. % Loop
Elapsed time is 2.604761 seconds. % Vectorized
The creation of the index matrix M and the multiplication A .* M is expensive, but the copy of memory blocks in the loop method is cheap.
Note: The indexing in D(B(k):C(k), k) is very efficient, because Matlab does not create the vector B(k):C(k) explicitly. This saves temporary memory and reduce the number of out-of-range checks, because only the first and the last element are checked. In opposite to this, the [ ] operator does create the temporary index vectors:
for k = 1:numel(B)
D([B(k):C(k)], k) = A([B(k):C(k)], k);
end
% Elapsed time is 1.634790 seconds.
or
for k = 1:numel(B)
v = B(k):C(k);
D(v, k) = A(v, k);
end
% Elapsed time is 1.458995 seconds.
Avoid the use of unnecessary square brackets.
Più risposte (0)
Vedere anche
Categorie
Scopri di più su Loops and Conditional Statements 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!