select elements of matrix from indices defined in an array
2 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
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 comentarios
Jan
el 12 de Ag. de 2017
Editada: Jan
el 12 de Ag. de 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.
Respuesta aceptada
Jan
el 12 de Ag. de 2017
Editada: Jan
el 12 de Ag. de 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.
Más respuestas (0)
Ver también
Categorías
Más información sobre Loops and Conditional Statements en Help Center y File Exchange.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!