rearranging a matrix in an efficient way

조회 수: 1 (최근 30일)
Yair
Yair 2012년 6월 23일
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.

채택된 답변

Andrei Bobrov
Andrei Bobrov 2012년 6월 23일
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
Yair
Yair 2012년 6월 23일
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?

댓글을 달려면 로그인하십시오.

추가 답변 (4개)

the cyclist
the cyclist 2012년 6월 23일
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 2012년 6월 23일
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 2012년 6월 23일
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 2012년 6월 23일
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
Jamie Rodgers
Jamie Rodgers 2012년 6월 23일
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 2012년 6월 23일
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.

댓글을 달려면 로그인하십시오.

카테고리

Help CenterFile Exchange에서 Resizing and Reshaping Matrices에 대해 자세히 알아보기

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by