Discover MakerZone

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

Learn more

Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

Apply Today

Thread Subject:
Rearranging an array by collecting values

Subject: Rearranging an array by collecting values

From: stumacher Saare

Date: 25 Feb, 2009 04:05:05

Message: 1 of 15

I have a relatively simple problem, but I just can't figure out a decent way to solve it.

I have an array that looks like such:

sn = [ 1 10
           1 27
           2 25
           2 26
           3 342
           3 343
           4 359
           4 368
           5 124
           5 142
           5 143
           5 144
           5 160 ]

which I want to rearrange to look like:

sn = [ 1 10 27 0 0 0
          2 25 26 0 0 0
          3 342 343 0 0 0
          4 459 368 0 0 0
          5 124 142 143 144 160 ]

Is there are more efficient way to do other than using a few 'for' and 'if' loops? Any help will be much appreciated.

Subject: Rearranging an array by collecting values

From: Darren Rowland

Date: 25 Feb, 2009 05:38:01

Message: 2 of 15

"stumacher Saare" <ssaare@mech.uwa.edu.au> wrote in message <go2g1h$jtl$1@fred.mathworks.com>...
> I have a relatively simple problem, but I just can't figure out a decent way to solve it.
>
> I have an array that looks like such:
>
> sn = [ 1 10
> 1 27
> 2 25
> 2 26
> 3 342
> 3 343
> 4 359
> 4 368
> 5 124
> 5 142
> 5 143
> 5 144
> 5 160 ]
>
> which I want to rearrange to look like:
>
> sn = [ 1 10 27 0 0 0
> 2 25 26 0 0 0
> 3 342 343 0 0 0
> 4 459 368 0 0 0
> 5 124 142 143 144 160 ]
>
> Is there are more efficient way to do other than using a few 'for' and 'if' loops? Any help will be much appreciated.

Try posting some code that you have already written and you are much more likely to receive some help with your homework.

Subject: Rearranging an array by collecting values

From: Matt Fig

Date: 25 Feb, 2009 05:58:01

Message: 3 of 15

That array is taylor-made for accumarray.




&mt~kaa?`ng-`llon~dX~`unn~~m~jgf``&d`t~nxoss~hLDb`9ddnbgshk

Subject: Rearranging an array by collecting values

From: Roger Stafford

Date: 25 Feb, 2009 08:08:03

Message: 4 of 15

"stumacher Saare" <ssaare@mech.uwa.edu.au> wrote in message <go2g1h$jtl$1@fred.mathworks.com>...
> I have a relatively simple problem, but I just can't figure out a decent way to solve it.
>
> I have an array that looks like such:
>
> sn = [ 1 10
> 1 27
> 2 25
> 2 26
> 3 342
> 3 343
> 4 359
> 4 368
> 5 124
> 5 142
> 5 143
> 5 144
> 5 160 ]
>
> which I want to rearrange to look like:
>
> sn = [ 1 10 27 0 0 0
> 2 25 26 0 0 0
> 3 342 343 0 0 0
> 4 459 368 0 0 0
> 5 124 142 143 144 160 ]
>
> Is there are more efficient way to do other than using a few 'for' and 'if' loops? Any help will be much appreciated.

  To utilize Matt's suggestion, you will need some column numbers. Here is one way to get them:

 p = diff(sn(:,1))~=0;
 q = find(p);
 p(q) = -diff([0;q]);
 p = cumsum([2;p+1]);

p will be the needed column numbers for entry into 'accumarray'.

Roger Stafford

Subject: Rearranging an array by collecting values

From: Siyi

Date: 25 Feb, 2009 10:15:52

Message: 5 of 15

On Feb 24, 8:05=A0pm, "stumacher Saare" <ssa...@mech.uwa.edu.au> wrote:
> I have a relatively simple problem, but I just can't figure out a decent =
way to solve it.
>
> I have an array that looks like such:
>
> sn =3D [ =A01 =A010
> =A0 =A0 =A0 =A0 =A0 =A01 =A027
> =A0 =A0 =A0 =A0 =A0 =A02 =A025
> =A0 =A0 =A0 =A0 =A0 =A02 =A026
> =A0 =A0 =A0 =A0 =A0 =A03 342
> =A0 =A0 =A0 =A0 =A0 =A03 343
> =A0 =A0 =A0 =A0 =A0 =A04 359
> =A0 =A0 =A0 =A0 =A0 =A04 368
> =A0 =A0 =A0 =A0 =A0 =A05 124
> =A0 =A0 =A0 =A0 =A0 =A05 142
> =A0 =A0 =A0 =A0 =A0 =A05 143
> =A0 =A0 =A0 =A0 =A0 =A05 144
> =A0 =A0 =A0 =A0 =A0 =A05 160 ]
>
> which I want to rearrange to look like:
>
> sn =3D [ 1 =A0 =A010 =A0 27 =A0 0 =A0 =A00 =A0 =A0 0
> =A0 =A0 =A0 =A0 =A0 2 =A0 25 =A026 =A0 =A00 =A0 =A0 0 =A0 =A0 0
> =A0 =A0 =A0 =A0 =A0 3 342 343 =A0 =A00 =A0 =A00 =A0 =A0 0
> =A0 =A0 =A0 =A0 =A0 4 459 368 =A0 =A00 =A0 =A00 =A0 =A0 0
> =A0 =A0 =A0 =A0 =A0 5 124 142 143 144 160 ]
>
> Is there are more efficient way to do other than using a few 'for' and 'i=
f' loops? Any help will be much appreciated.

p =3D sn(:,1);
q =3D cumsum(ones(length(p),1))-cumsum([0;diff(p)~=3D0])-p+2

sn1 =3D zeros(5,6);
sn1(:,1) =3D 1:5;
sn1(sub2ind(size(sn1),p,q)) =3D sn(:,2)

Subject: Rearranging an array by collecting values

From: Siyi

Date: 25 Feb, 2009 10:19:44

Message: 6 of 15

On Feb 24, 8:05=A0pm, "stumacher Saare" <ssa...@mech.uwa.edu.au> wrote:
> I have a relatively simple problem, but I just can't figure out a decent =
way to solve it.
>
> I have an array that looks like such:
>
> sn =3D [ =A01 =A010
> =A0 =A0 =A0 =A0 =A0 =A01 =A027
> =A0 =A0 =A0 =A0 =A0 =A02 =A025
> =A0 =A0 =A0 =A0 =A0 =A02 =A026
> =A0 =A0 =A0 =A0 =A0 =A03 342
> =A0 =A0 =A0 =A0 =A0 =A03 343
> =A0 =A0 =A0 =A0 =A0 =A04 359
> =A0 =A0 =A0 =A0 =A0 =A04 368
> =A0 =A0 =A0 =A0 =A0 =A05 124
> =A0 =A0 =A0 =A0 =A0 =A05 142
> =A0 =A0 =A0 =A0 =A0 =A05 143
> =A0 =A0 =A0 =A0 =A0 =A05 144
> =A0 =A0 =A0 =A0 =A0 =A05 160 ]
>
> which I want to rearrange to look like:
>
> sn =3D [ 1 =A0 =A010 =A0 27 =A0 0 =A0 =A00 =A0 =A0 0
> =A0 =A0 =A0 =A0 =A0 2 =A0 25 =A026 =A0 =A00 =A0 =A0 0 =A0 =A0 0
> =A0 =A0 =A0 =A0 =A0 3 342 343 =A0 =A00 =A0 =A00 =A0 =A0 0
> =A0 =A0 =A0 =A0 =A0 4 459 368 =A0 =A00 =A0 =A00 =A0 =A0 0
> =A0 =A0 =A0 =A0 =A0 5 124 142 143 144 160 ]
>
> Is there are more efficient way to do other than using a few 'for' and 'i=
f' loops? Any help will be much appreciated.


p =3D sn(:,1);
q =3D cumsum(ones(length(p),1))-2*p+3
sn1 =3D zeros(5,6);
sn1(:,1) =3D 1:5;
sn1(sub2ind(size(sn1),p,q)) =3D sn(:,2)

Subject: Rearranging an array by collecting values

From: Matt Fig

Date: 26 Feb, 2009 00:34:01

Message: 7 of 15

Siyi <Mr.Siyi.Deng@gmail.com> wrote in message <83043c12-ac0f-49dd-


How would you generalize your solution to work with, say:

sn(:,1) = sort(round(rand(2000,1)*10+1));
sn(:,2) = round(rand(2000,1)*600+1);

Where the the number and values of the indeces is unknown?
I wonder if it is really faster than for loops and indexing (No IF statements are necessary).

Subject: Rearranging an array by collecting values

From: Amandeep

Date: 26 Aug, 2011 04:37:10

Message: 8 of 15

"Roger Stafford" wrote in message <go2u93$1tg$1@fred.mathworks.com>...
> "stumacher Saare" <ssaare@mech.uwa.edu.au> wrote in message <go2g1h$jtl$1@fred.mathworks.com>...
> > I have a relatively simple problem, but I just can't figure out a decent way to solve it.
> >
> > I have an array that looks like such:
> >
> > sn = [ 1 10
> > 1 27
> > 2 25
> > 2 26
> > 3 342
> > 3 343
> > 4 359
> > 4 368
> > 5 124
> > 5 142
> > 5 143
> > 5 144
> > 5 160 ]
> >
> > which I want to rearrange to look like:
> >
> > sn = [ 1 10 27 0 0 0
> > 2 25 26 0 0 0
> > 3 342 343 0 0 0
> > 4 459 368 0 0 0
> > 5 124 142 143 144 160 ]
> >
> > Is there are more efficient way to do other than using a few 'for' and 'if' loops? Any help will be much appreciated.
>
> To utilize Matt's suggestion, you will need some column numbers. Here is one way to get them:
>
> p = diff(sn(:,1))~=0;
> q = find(p);
> p(q) = -diff([0;q]);
> p = cumsum([2;p+1]);
>
> p will be the needed column numbers for entry into 'accumarray'.
>
> Roger Stafford

Hi,
I have a very similar problem:

I'm trying to rearrange the following:

[1 16;
2 55;
2 61;
2 66;
2 68; .
......
10 57];

to look like:

[1 16 0 0 0;
2 55 61 66 68;
......
10 57 0 0 0];

and I used p in accumarray to get the following:

[0;
16;
0;
55;
61;
66;
68;
.....
0;
57]

(Thanks by the way for getting me to this point!)
 and I was wondering what the next step is to get the matrix looking the way I want?

Thanks

Subject: Rearranging an array by collecting values

From: Bruno Luong

Date: 26 Aug, 2011 06:16:11

Message: 9 of 15

One way:

A=[ 1 16;
    2 55;
    2 61;
    2 66;
    2 68;
    10 57];

[A1, trash, J] = unique(A(:,1));
C = accumarray(J,A(:,2),[],@(x){x});
row = arrayfun(@(k) k+zeros(1,length(C{k})),1:length(C),'unif',false);
col = cellfun(@(x) 1:length(x),C,'unif',false);
IJ = [row{:}; col{:}].';
B = accumarray(IJ, cat(1,C{:}));
[A1 B]

% Bruno

Subject: Rearranging an array by collecting values

From: Amandeep

Date: 26 Aug, 2011 06:28:10

Message: 10 of 15

"Bruno Luong" <b.luong@fogale.findmycountry> wrote in message <j37dnb$dpo$1@newscl01ah.mathworks.com>...
> One way:
>
> A=[ 1 16;
> 2 55;
> 2 61;
> 2 66;
> 2 68;
> 10 57];
>
> [A1, trash, J] = unique(A(:,1));
> C = accumarray(J,A(:,2),[],@(x){x});
> row = arrayfun(@(k) k+zeros(1,length(C{k})),1:length(C),'unif',false);
> col = cellfun(@(x) 1:length(x),C,'unif',false);
> IJ = [row{:}; col{:}].';
> B = accumarray(IJ, cat(1,C{:}));
> [A1 B]
>
> % Bruno

Hi Bruno,

Thankyou very much, I spent a couple of hours trying to figure this out but you have helped a lot.

Thanks,

Amandeep

Subject: Rearranging an array by collecting values

From: Bruno Luong

Date: 26 Aug, 2011 06:53:10

Message: 11 of 15

Another way (the first column of A must have elements grouped consecutively):

A=[ 1 16;
    2 55;
    2 61;
    2 66;
    2 68;
    10 57
    10 23];

b = diff([-Inf; A(:,1); Inf]) ~= 0;
b = find(b);
l = diff(b);
m = length(l);
n = max(l);
b(end) = [];

row = zeros(size(A,1),1);
row(b) = 1;
row = cumsum(row);

col = ones(size(row));
col(b(2:end)) = 1-l(1:end-1);
col = cumsum(col);

B = zeros(m,n);
B((col-1)*m+row) = A(:,2);

[A(b,1) B]

% Bruno

Subject: Rearranging an array by collecting values

From: Bruno Luong

Date: 26 Aug, 2011 08:58:11

Message: 12 of 15

Using three FEX tools:

A=[ 1 16;
    2 55;
    2 61;
    2 66;
    2 68;
    10 57
    10 23];

% http://www.mathworks.com/matlabcentral/fileexchange/6436
% http://www.mathworks.com/matlabcentral/fileexchange/29854
% http://www.mathworks.com/matlabcentral/fileexchange/2425

[lgt a] = SplitVec(A,1, 'length', 'firstelem');
row = rude(lgt,1:length(lgt));
col = mcolon(ones(size(lgt)),lgt);
[a(:,1) accumarray([row(:) col(:)], A(:,2))]

% Bruno

Subject: Rearranging an array by collecting values

From: Bruno Luong

Date: 26 Aug, 2011 09:41:10

Message: 13 of 15

Sorry for the typo: correction of the third link

>
> % http://www.mathworks.com/matlabcentral/fileexchange/6436
> % http://www.mathworks.com/matlabcentral/fileexchange/29854
> % http://www.mathworks.com/matlabcentral/fileexchange/24255
>

Bruno

Subject: Rearranging an array by collecting values

From: Bruno Luong

Date: 26 Aug, 2011 11:02:11

Message: 14 of 15

Most compact using only Matlab built-in functions:

m = max(diff(find([1; diff(A(:,1)); 1])));
[A1, trash, J] = unique(A(:,1));
C = accumarray(J,A(:,2),[],@(x){[x' zeros(1,m-length(x))]});
[A1 cat(1,C{:})]

% Bruno

Subject: Rearranging an array by collecting values

From: Bruno Luong

Date: 26 Aug, 2011 12:04:26

Message: 15 of 15

Don't you have enough? Here is another one

b = [true; diff(A(:,1))~=0];
l = diff(find([b; true]));
B = bsxfun(@le,ndgrid(1:max(l),1:length(l)),l.');
C = zeros(size(B));
C(B) = A(:,2);
[A(b,1) C']

Bruno

Tags for this Thread

No tags are associated with this thread.

What are tags?

A tag is like a keyword or category label associated with each thread. Tags make it easier for you to find threads of interest.

Anyone can tag a thread. Tags are public and visible to everyone.

Contact us