rearranging a matrix in an efficient way
2 Ansichten (letzte 30 Tage)
Ältere Kommentare anzeigen
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 Kommentare
Akzeptierte Antwort
Andrei Bobrov
am 23 Jun. 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,:);
Weitere Antworten (4)
the cyclist
am 23 Jun. 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 Kommentare
Jamie Rodgers
am 23 Jun. 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 Kommentare
Jamie Rodgers
am 23 Jun. 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
am 23 Jun. 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.
Siehe auch
Kategorien
Mehr zu Resizing and Reshaping Matrices finden Sie in Help Center und File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!