rearranging a matrix in an efficient way

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

Risposta accettata

Andrei Bobrov
Andrei Bobrov il 23 Giu 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,:);
  1 Commento
Yair
Yair il 23 Giu 2012
Exactly ! great.
Now, what if I actually need the final answer to be a transpose of the outcome of your code?
Is there a quicker way than using the transpose sign? I'm asking this because I see that you used a transpose symbol along the way of your answer. Maybe somewhere there the final answer I need is lurking?

Accedi per commentare.

Più risposte (4)

the cyclist
the cyclist il 23 Giu 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],:)

Yair
Yair il 23 Giu 2012
Hmmm...at first sight it seems that what both of you wrote is correct but there are some problems it seems. I made a random matrix to check your answers.
A=rand(15,3);
Someone gave me the following answer:
NN = size( A , 1 ) / 3 ;
q1 = reshape( A( : , 1 ) , NN , [ ] ).' ; q1 = q1( : ) ;
q2 = reshape( A( : , 2 ) , NN , [ ] ).' ; q2 = q2( : ) ;
q3 = reshape( A( : , 3 ) , NN , [ ] ).' ; q3 = q3( : ) ;
q = [ q1 q2 q3 ];
which gives me the correct answer. Then I ran your answers and subtracted it from this answer. They didn't give 0 although subtracting 'the cyclinst's' answer from Andrei's gave 0. So I'm not sure why your answers (which seem correct at first sight) give a different result than the one I have above. ??? What is even stranger is that if I change the first line: A=rand(15,3); to A=rand(9,3);
Then your answers and the one above give the same result??? I appreciate your continuing help.

Yair
Yair il 23 Giu 2012
O.k. I think I understand the differences now. What you guys gave me is not exactly what I asked in my first post. if you generate the matrix:
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
10.1 10.2 10.3
11.1 11.2 11.3
12.1 12.2 12.3
you will notice that your answers do not produce:
1:N/3:end
2:N/3:end
3:N/3:end
etc…….
'The cyclist', if I change your code to:
out = A([1:N/3:end 2:N/3:end 3:N/3:end],:);
Then that is what I need but only for a 9x3 matrix. When the matrix gets larger, your code is not automated to deal with the larger matrices.
Actually, what I need as a final answer is the above but transposed. If I could achieve that without using the transpose symbol after the above rearranged matrix is generated then that would be perfect. I hope I'm clear as to what I'm asking here. Thank you for you help.

Jamie Rodgers
Jamie Rodgers il 23 Giu 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 Commenti
Jamie Rodgers
Jamie Rodgers il 23 Giu 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
Walter Roberson il 23 Giu 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.

Accedi per commentare.

Categorie

Scopri di più su Resizing and Reshaping Matrices 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