rearranging a matrix in an efficient way
2 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
Hello, I would like to know what is the best way to extract rows from a matrix but in a specific order. I’ll explain: My program is generating HUGE matrices that always have their number of rows divisible by 3. The number of columns is always 3. I need to extract rows from these matrices in the following way: Let’s say I have a matrix 9x3:
1.1 1.2 1.3
2.1 2.2 2.3
3.1 3.2 3.3
4.1 4.2 4.3
5.1 5.2 5.3
6.1 6.2 6.3
7.1 7.2 7.3
8.1 8.2 8.3
9.1 9.2 9.3
I would like to end up with:
1.1 1.2 1.3
4.1 4.2 4.3
7.1 7.2 7.3
2.1 2.2 2.3
5.1 5.2 5.3
8.1 8.2 8.3
3.1 3.2 3.3
6.1 6.2 6.3
9.1 9.2 9.3
So basically it is taking these rows:
1:N/3:end
2:N/3:end
3:N/3:end
etc…….
Doing it with a ‘for’ loop is trivial but very time consuming. Is there an automatic way to do this? Thank you.
0 comentarios
Respuesta aceptada
Andrei Bobrov
el 23 de Jun. de 2012
one way
out = data(reshape(1:size(data,1),3,[])',:); %%%EDIT
second way
out = reshape(permute(reshape(data,3,[],3),[3 2 1]),3,[])';
ADD after Yair's answer
out = A(reshape(1:size(A,1),size(A,1)/3,[])',:);
ADD 2
[~,ii] = sort(rem(0:size(data,1)-1,size(data,1)/3)+1);
out = data(ii,:);
Más respuestas (4)
the cyclist
el 23 de Jun. de 2012
I fear that I am misunderstanding the ordering when the number of rows is larger, but is this right?
out = data([1:3:end 2:3:end 3:3:end],:)
0 comentarios
Jamie Rodgers
el 23 de Jun. de 2012
MY Strategy: Generate required indices, and use arrayfun!
(i) Generate 2 matrices corresponding respectively to the row indices and column indices you want to see in the arranged data.
Columns index is easy as these don’t change, so its just numbers 1:3 in each row:
col_idx= repmat([1,2,3],size(unsorted,1),1);
We can rearrange rows according to your rules with repmat and using a combination of linear and row column indexing as follows:
row_idx=([1:3:size(unsorted,1);2:3:size(unsorted,1);3:3:size(unsorted,1)]');
row_idx=repmat(row_idx(:),1,size(unsorted,2));
(ii) Create a function handle to index into the original dataset
read_data=@(x,y)unsorted(x,y);
(iii) apply this using arrayfun:
sorted_data=arrayfun(read_data,row_idx,col_idx);
SHORTER ALTERNATIVE
harder to follow but does the same thing in exactly the same way
row_idx=([1:3:size(unsorted,1);2:3:size(unsorted,1);3:3:size(unsorted,1)]');
sorted =arrayfun(@(x,y)unsorted(x,y),repmat(row_idx(:),1,3),repmat([1:size(unsorted,2)],size(unsorted,1),1));
OR Just feed your data into the results into this function~
function [sorted] = sort_by_3s(unsorted) ;
row_idx=([1:3:size(unsorted,1);2:3:size(unsorted,1);3:3:size(unsorted,1)]') ;
sorted =arrayfun(@(x,y)unsorted(x,y),repmat(row_idx(:),1,3),repmat([1:size(unsorted,2)],size(unsorted,1),1));
2 comentarios
Jamie Rodgers
el 23 de Jun. de 2012
Just saw your second comment about wanting the transpose:
This is easy with my solution: Instead of generating a matrix of indices the same shape as unsorted (mx3), just generate the transpose shapes (3xm)... ofr any other shape you like for that matter... and apply the function in exactly the same way. Because the arrayfun operates elementwise, the output will be the same shape as the inputs, no matter what shape the unsorted matrix is.
As long as no value in the input matrices exceeds the matrix dimensions of the unsorted matrix, it will give you a result. You just have to make sure you are asking for the right rxc combinations in whatever matrix you input.
Walter Roberson
el 23 de Jun. de 2012
Jamie, thank you for trying to format your code. Unfortunately the { and } character pair are not actually formatting characters and we don't know why they appear on the "Code" button. Two leading spaces is what is actually used for code formatting. I have adjusted your answer.
Ver también
Categorías
Más información sobre Resizing and Reshaping Matrices 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!