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:
matrix manipulation

Subject: matrix manipulation

From: Yuri Geshelin

Date: 10 Apr, 2008 17:35:03

Message: 1 of 17

Hi,

I have array a (3 x 2):

>> a

a =

     1 4
     2 5
     3 6

How can I obtain b from a such that b = [1:4 2:5 3:6] ?

No loops pls.

Thanks

Yuri

Subject: matrix manipulation

From: John D'Errico

Date: 10 Apr, 2008 17:43:01

Message: 2 of 17

"Yuri Geshelin" <geshelin@hotmail.com> wrote in message
<ftlj46$1f1$1@fred.mathworks.com>...
> Hi,
>
> I have array a (3 x 2):

Admit it. You have a homework assignment.


> >> a
>
> a =
>
> 1 4
> 2 5
> 3 6
>
> How can I obtain b from a such that b = [1:4 2:5 3:6] ?
>
> No loops pls.

Learn to use tools like reshape and permute.
Read the help.

Learn what A(:) does. try it out for a matrix A.

John

Subject: matrix manipulation

From: us

Date: 10 Apr, 2008 18:03:01

Message: 3 of 17

"Yuri Geshelin":
<SNIP indexing evergreen...

one of the solutions

     a=[
          1 4
          -5 -2
          30 32
     ];
     ix=arrayfun(@(x,y) x:y,a(:,1),a(:,2),'uni',false);
     ix=cat(2,ix{:})
% ix = 1 2 3 4 -5 -4 -3 -2 30 31 32

us

Subject: matrix manipulation

From: Yuri Geshelin

Date: 10 Apr, 2008 18:06:02

Message: 4 of 17

"John D'Errico" <woodchips@rochester.rr.com> wrote in
message <ftljj5$9n$1@fred.mathworks.com>...

> Admit it. You have a homework assignment.

I wish I had one, but I have no time for a matlab course.

Here is what I have come up with.

q = a';
w = q(:)';

Now w is [1 4 2 5 3 6], which is very close to what I need.
If I could only insert 3 colons...

I read help for reshape and permute, but have no idea how
to use them. Need just another small tip from you.

Thanks

Yuri

Subject: matrix manipulation

From: Yuri Geshelin

Date: 10 Apr, 2008 18:15:03

Message: 5 of 17

Thanks us,

but there seems to be no arrayfun in the version of matlab
I am using.

Yuri

"us " <us@neurol.unizh.ch> wrote in message <ftlkol$ef6
$1@fred.mathworks.com>...
> "Yuri Geshelin":
> <SNIP indexing evergreen...
>
> one of the solutions
>
> a=[
> 1 4
> -5 -2
> 30 32
> ];
> ix=arrayfun(@(x,y) x:y,a(:,1),a(:,2),'uni',false);
> ix=cat(2,ix{:})
> % ix = 1 2 3 4 -5 -4 -3 -2 30 31 32
>
> us

Subject: matrix manipulation

From: Jos

Date: 10 Apr, 2008 19:44:02

Message: 6 of 17

"Yuri Geshelin" <geshelin@hotmail.com> wrote in message
<ftlj46$1f1$1@fred.mathworks.com>...
> Hi,
>
> I have array a (3 x 2):
>
> >> a
>
> a =
>
> 1 4
> 2 5
> 3 6
>
> How can I obtain b from a such that b = [1:4 2:5 3:6] ?
>
> No loops pls.
>
> Thanks
>
> Yuri
>

a = ... % as above
b = cumsum([a(:,1) ones(size(a,1),3)],2)

but note that this will only work since all new rows are to
have 4 elements !!

In the more generic case you need to use cell arrays, that
can be created by arrayfun or, most easily, by a very
simple loop.

hth
Jos

Subject: matrix manipulation

From: Bruno Luong

Date: 10 Apr, 2008 20:53:01

Message: 7 of 17

"Yuri Geshelin" <geshelin@hotmail.com> wrote in message
<ftllf7$rcj$1@fred.mathworks.com>...

> but there seems to be no arrayfun in the version of matlab
> I am using.
>

I hate what I will write, but let's not be refrain. If you
do not like for-loop and do not have arrayfun, then a dirty
alternative may be this:

b = eval(['[' sprintf('%d:%d, ', a') ']'])

Bruno

Subject: matrix manipulation

From: Roger Stafford

Date: 10 Apr, 2008 20:54:02

Message: 8 of 17

"Yuri Geshelin" <geshelin@hotmail.com> wrote in message <ftlj46$1f1
$1@fred.mathworks.com>...
> Hi,
>
> I have array a (3 x 2):
>
> >> a
>
> a =
>
> 1 4
> 2 5
> 3 6
>
> How can I obtain b from a such that b = [1:4 2:5 3:6] ?
>
> No loops pls.
>
> Thanks
>
> Yuri
----------
  This is admittedly a very awkward solution, but at least it doesn't require
anonymous functions, 'arrayfun', or cell arrays (none of which I have, by the
way.) It works correctly with differing row counts. However, it fails if you
have something like 5:4 which ought to generate an empty set. It does
assume that 'a' is entirely integer-valued.

 x = a(:,1); y = a(:,2); z = y-x+1;
 b = ones(sum(z),1);
 b(cumsum([1;z(1:end-1)])) = x-[0;y(1:end-1)];
 b = cumsum(b)';

Roger Stafford

Subject: matrix manipulation

From: Yuri Geshelin

Date: 10 Apr, 2008 21:22:02

Message: 9 of 17

Thanks Jos,

Your cumsum fragment is nice and elegant, but not a
solution. As you pointed out, it will only work in a
specific case, because you did not even make use of the
right column of my array a. You just assumed that
a(:,2) = a(:,1) + 3, but of course, what I posted was a
simplified example.

I am very happy with Roger's solution.

Yuri

"Jos " <DELjos@jasenDEL.nl> wrote in message <ftlqm2
$ahj$1@fred.mathworks.com>...
> "Yuri Geshelin" <geshelin@hotmail.com> wrote in message
> <ftlj46$1f1$1@fred.mathworks.com>...
> > Hi,
> >
> > I have array a (3 x 2):
> >
> > >> a
> >
> > a =
> >
> > 1 4
> > 2 5
> > 3 6
> >
> > How can I obtain b from a such that b = [1:4 2:5 3:6] ?
> >
> > No loops pls.
> >
> > Thanks
> >
> > Yuri
> >
>
> a = ... % as above
> b = cumsum([a(:,1) ones(size(a,1),3)],2)
>
> but note that this will only work since all new rows are
to
> have 4 elements !!
>
> In the more generic case you need to use cell arrays,
that
> can be created by arrayfun or, most easily, by a very
> simple loop.
>
> hth
> Jos
>

Subject: matrix manipulation

From: Yuri Geshelin

Date: 10 Apr, 2008 21:25:03

Message: 10 of 17

Thanks Bruno,

Yes, I have already resorted to an eval solution, although
less elegant than yours.

Yuri

"Bruno Luong" <b.luong@fogale.fr> wrote in message
<ftlund$kpl$1@fred.mathworks.com>...
> "Yuri Geshelin" <geshelin@hotmail.com> wrote in message
> <ftllf7$rcj$1@fred.mathworks.com>...
>
> > but there seems to be no arrayfun in the version of
matlab
> > I am using.
> >
>
> I hate what I will write, but let's not be refrain. If you
> do not like for-loop and do not have arrayfun, then a
dirty
> alternative may be this:
>
> b = eval(['[' sprintf('%d:%d, ', a') ']'])
>
> Bruno

Subject: matrix manipulation

From: Yuri Geshelin

Date: 10 Apr, 2008 21:26:03

Message: 11 of 17


I wouldn't call it awkward, it's brilliant!

Thanks Roger!

"Roger Stafford"
<ellieandrogerxyzzy@mindspring.com.invalid> wrote in
message <ftlup9$p3r$1@fred.mathworks.com>...
> "Yuri Geshelin" <geshelin@hotmail.com> wrote in message
<ftlj46$1f1
> $1@fred.mathworks.com>...
> > Hi,
> >
> > I have array a (3 x 2):
> >
> > >> a
> >
> > a =
> >
> > 1 4
> > 2 5
> > 3 6
> >
> > How can I obtain b from a such that b = [1:4 2:5 3:6] ?
> >
> > No loops pls.
> >
> > Thanks
> >
> > Yuri
> ----------
> This is admittedly a very awkward solution, but at
least it doesn't require
> anonymous functions, 'arrayfun', or cell arrays (none of
which I have, by the
> way.) It works correctly with differing row counts.
However, it fails if you
> have something like 5:4 which ought to generate an empty
set. It does
> assume that 'a' is entirely integer-valued.
>
> x = a(:,1); y = a(:,2); z = y-x+1;
> b = ones(sum(z),1);
> b(cumsum([1;z(1:end-1)])) = x-[0;y(1:end-1)];
> b = cumsum(b)';
>
> Roger Stafford
>
>

Subject: matrix manipulation

From: Peter Boettcher

Date: 10 Apr, 2008 21:38:18

Message: 12 of 17


[Please post your comments after the post you respond to, trimming the
quotes as appropriate]

"Yuri Geshelin" <geshelin@hotmail.com> writes:

> "Roger Stafford"
> <ellieandrogerxyzzy@mindspring.com.invalid> wrote in
> message <ftlup9$p3r$1@fred.mathworks.com>...
>> "Yuri Geshelin" <geshelin@hotmail.com> wrote in message
> <ftlj46$1f1$1@fred.mathworks.com>...
>> > Hi,
>> >
>> > I have array a (3 x 2):
>> >
>> > >> a
>> >
>> > a =
>> >
>> > 1 4
>> > 2 5
>> > 3 6
>> >
>> > How can I obtain b from a such that b = [1:4 2:5 3:6] ?
>> >
>> > No loops pls.

>> This is admittedly a very awkward solution, but at least
>> it doesn't require anonymous functions, 'arrayfun', or cell arrays
>> (none of which I have, by the way.) It works correctly with
>> differing row counts. However, it fails if you have something like
>> 5:4 which ought to generate an empty set. It does assume that 'a' is
>> entirely integer-valued.
>>
>> x = a(:,1); y = a(:,2); z = y-x+1;
>> b = ones(sum(z),1);
>> b(cumsum([1;z(1:end-1)])) = x-[0;y(1:end-1)];
>> b = cumsum(b)';

>
> I wouldn't call it awkward, it's brilliant!
>
> Thanks Roger!

With apologies to Roger's inventive solution, how is that solution
better than a small function that does the job with a loop? This one
(indeed any vectorized solution) is unlikely to be faster, and it
certainly is not as readable or maintainable. What do you have against
loops?

for i=1:size(a,1)
  vec{i} = a(i,1):a(i,2);
end
b = [vec{:}];

There are dozens more variants of the above with various tradeoffs of
verbosity and speed. This one is probably not particularly good at
either. For instance, preallocate as Roger does, then insert the vector
directly into the correct location. Either way you'll be able to
understand it 6 months from now!

-Peter

Subject: matrix manipulation

From: Jos

Date: 10 Apr, 2008 22:00:21

Message: 13 of 17

"Yuri Geshelin" <geshelin@hotmail.com> wrote in message
<ftm0lb$7od$1@fred.mathworks.com>...
>
> I wouldn't call it awkward, it's brilliant!
>
> Thanks Roger!
>
> "Roger Stafford"
> <ellieandrogerxyzzy@mindspring.com.invalid> wrote in
> message <ftlup9$p3r$1@fred.mathworks.com>...
> > "Yuri Geshelin" <geshelin@hotmail.com> wrote in message
> <ftlj46$1f1
> > $1@fred.mathworks.com>...
> > > Hi,
> > >
> > > I have array a (3 x 2):
> > >
> > > >> a
> > >
> > > a =
> > >
> > > 1 4
> > > 2 5
> > > 3 6
> > >
> > > How can I obtain b from a such that b = [1:4 2:5
3:6] ?
> > >
> > > No loops pls.
> > >
> > > Thanks
> > >
> > > Yuri
> > ----------
> > This is admittedly a very awkward solution, but at
> least it doesn't require
> > anonymous functions, 'arrayfun', or cell arrays (none
of
> which I have, by the
> > way.) It works correctly with differing row counts.
> However, it fails if you
> > have something like 5:4 which ought to generate an
empty
> set. It does
> > assume that 'a' is entirely integer-valued.
> >
> > x = a(:,1); y = a(:,2); z = y-x+1;
> > b = ones(sum(z),1);
> > b(cumsum([1;z(1:end-1)])) = x-[0;y(1:end-1)];
> > b = cumsum(b)';
> >
> > Roger Stafford
> >
> >
>

Another obscure approach:

a = [1 4 ; 2 9 ; 3 8] ;
z = diff(a,[],2)+1 ;
b([(cumsum(z)-z+1) cumsum(z)]) = a(:) ;
b(~b) = interp1(find(b),b(~~b),find(~b))

Lesson: stick to the for-loop!

Jos

Subject: matrix manipulation

From: Yuri Geshelin

Date: 10 Apr, 2008 23:48:03

Message: 14 of 17

Peter Boettcher <boettcher@ll.mit.edu> wrote in message
<muyve2pe6gl.fsf@G99-Boettcher.llan.ll.mit.edu>...
>
> [Please post your comments after the post you respond to,
trimming the
> quotes as appropriate]
>
> "Yuri Geshelin" <geshelin@hotmail.com> writes:
>
> > "Roger Stafford"
> > <ellieandrogerxyzzy@mindspring.com.invalid> wrote in
> > message <ftlup9$p3r$1@fred.mathworks.com>...
> >> "Yuri Geshelin" <geshelin@hotmail.com> wrote in
message
> > <ftlj46$1f1$1@fred.mathworks.com>...
> >> > Hi,
> >> >
> >> > I have array a (3 x 2):
> >> >
> >> > >> a
> >> >
> >> > a =
> >> >
> >> > 1 4
> >> > 2 5
> >> > 3 6
> >> >
> >> > How can I obtain b from a such that b = [1:4 2:5
3:6] ?
> >> >
> >> > No loops pls.
>
> >> This is admittedly a very awkward solution, but at
least
> >> it doesn't require anonymous functions, 'arrayfun', or
cell arrays
> >> (none of which I have, by the way.) It works
correctly with
> >> differing row counts. However, it fails if you have
something like
> >> 5:4 which ought to generate an empty set. It does
assume that 'a' is
> >> entirely integer-valued.
> >>
> >> x = a(:,1); y = a(:,2); z = y-x+1;
> >> b = ones(sum(z),1);
> >> b(cumsum([1;z(1:end-1)])) = x-[0;y(1:end-1)];
> >> b = cumsum(b)';
>
> >
> > I wouldn't call it awkward, it's brilliant!
> >
> > Thanks Roger!
>
> With apologies to Roger's inventive solution, how is that
solution
> better than a small function that does the job with a
loop? This one
> (indeed any vectorized solution) is unlikely to be
faster, and it
> certainly is not as readable or maintainable. What do
you have against
> loops?
>
> for i=1:size(a,1)
> vec{i} = a(i,1):a(i,2);
> end
> b = [vec{:}];
>
> There are dozens more variants of the above with various
tradeoffs of
> verbosity and speed. This one is probably not
particularly good at
> either. For instance, preallocate as Roger does, then
insert the vector
> directly into the correct location. Either way you'll be
able to
> understand it 6 months from now!
>
> -Peter

It has been my experience that a vectorized solution is
faster than a for-loop, which is why I wanted to stay away
from the latter.

Surprisingly, your solution is faster than Roger's, even
though you do not preallocate. If so, then of course, there
is no need to do all that mind boggling and formiddable
stuff.

Well, perhaps there are different situations.

Thanks,

Yuri

Subject: matrix manipulation

From: Yuri Geshelin

Date: 10 Apr, 2008 23:58:04

Message: 15 of 17

"Jos " <DELjos@jasenDEL.nl> wrote in message
<ftm2ll$kfn$1@fred.mathworks.com>...
> "Yuri Geshelin" <geshelin@hotmail.com> wrote in message
> <ftm0lb$7od$1@fred.mathworks.com>...
> >
> > I wouldn't call it awkward, it's brilliant!
> >
> > Thanks Roger!
> >
> > "Roger Stafford"
> > <ellieandrogerxyzzy@mindspring.com.invalid> wrote in
> > message <ftlup9$p3r$1@fred.mathworks.com>...
> > > "Yuri Geshelin" <geshelin@hotmail.com> wrote in
message
> > <ftlj46$1f1
> > > $1@fred.mathworks.com>...
> > > > Hi,
> > > >
> > > > I have array a (3 x 2):
> > > >
> > > > >> a
> > > >
> > > > a =
> > > >
> > > > 1 4
> > > > 2 5
> > > > 3 6
> > > >
> > > > How can I obtain b from a such that b = [1:4 2:5
> 3:6] ?
> > > >
> > > > No loops pls.
> > > >
> > > > Thanks
> > > >
> > > > Yuri
> > > ----------
> > > This is admittedly a very awkward solution, but at
> > least it doesn't require
> > > anonymous functions, 'arrayfun', or cell arrays (none
> of
> > which I have, by the
> > > way.) It works correctly with differing row counts.
> > However, it fails if you
> > > have something like 5:4 which ought to generate an
> empty
> > set. It does
> > > assume that 'a' is entirely integer-valued.
> > >
> > > x = a(:,1); y = a(:,2); z = y-x+1;
> > > b = ones(sum(z),1);
> > > b(cumsum([1;z(1:end-1)])) = x-[0;y(1:end-1)];
> > > b = cumsum(b)';
> > >
> > > Roger Stafford
> > >
> > >
> >
>
> Another obscure approach:
>
> a = [1 4 ; 2 9 ; 3 8] ;
> z = diff(a,[],2)+1 ;
> b([(cumsum(z)-z+1) cumsum(z)]) = a(:) ;
> b(~b) = interp1(find(b),b(~~b),find(~b))
>
> Lesson: stick to the for-loop!
>
> Jos
>

It wasn't my goal to vectorize for the sake of
vectorization (see my reply to Peter).
Nevertheless, thanks for this, it is interesting.

Yuri

Subject: matrix manipulation

From: Peter Boettcher

Date: 11 Apr, 2008 13:31:31

Message: 16 of 17

"Yuri Geshelin" <geshelin@hotmail.com> writes:

> Peter Boettcher <boettcher@ll.mit.edu> wrote in message
> <muyve2pe6gl.fsf@G99-Boettcher.llan.ll.mit.edu>...

>> With apologies to Roger's inventive solution, how is that solution
>> better than a small function that does the job with a loop? This one
>> (indeed any vectorized solution) is unlikely to be faster, and it
>> certainly is not as readable or maintainable. What do you have
>> against loops?
>>
>> for i=1:size(a,1)
>> vec{i} = a(i,1):a(i,2);
>> end
>> b = [vec{:}];

[snip]

> It has been my experience that a vectorized solution is
> faster than a for-loop, which is why I wanted to stay away
> from the latter.
>
> Surprisingly, your solution is faster than Roger's, even
> though you do not preallocate. If so, then of course, there
> is no need to do all that mind boggling and formiddable
> stuff.
>
> Well, perhaps there are different situations.

Absolutely. Two more general comments:

1- The MATLAB JIT compiler and accelerator are doing a better and better
job at making loops go fast. This is good for more than just "lazy"
MATLAB coding. It also often results in code that accesses memory in a
more efficient pattern, resulting in faster code. Obviously this
depends on what you're doing. When there is a native MATLAB (or MEX)
function that something close to what you want, you can't beat it.

2- Donald Knuth: "We should forget about small efficiencies, say about
97% of the time: premature optimization is the root of all evil."
Especially as architectures, compilers, interpreters, etc get more
complicated, it can be very difficult to predict performance problems.
Instead, write your code in the simplest, cleanest way possible, even if
you think it might be slow. Get it all to work, focusing on an
efficient algorithm. Then use the profiler to find out where your
specific performance bottlenecks are, and tackle them in a targeted
manner. I find that the simpler slow code in those few cases is STILL
useful as documentation, or as a fallback for more general input cases
that you might not need to optimize.

Just my 2.5 cents...

-Peter

Subject: matrix manipulation

From: Roger Stafford

Date: 11 Apr, 2008 15:52:01

Message: 17 of 17

Peter Boettcher <boettcher@ll.mit.edu> wrote in message
<muyiqyoecwc.fsf@G99-Boettcher.llan.ll.mit.edu>...
> Absolutely. Two more general comments:
>
> 1- The MATLAB JIT compiler and accelerator are doing a better and better
> job at making loops go fast. This is good for more than just "lazy"
> MATLAB coding. It also often results in code that accesses memory in a
> more efficient pattern, resulting in faster code. Obviously this
> depends on what you're doing. When there is a native MATLAB (or MEX)
> function that something close to what you want, you can't beat it.
>
> 2- Donald Knuth: "We should forget about small efficiencies, say about
> 97% of the time: premature optimization is the root of all evil."
> Especially as architectures, compilers, interpreters, etc get more
> complicated, it can be very difficult to predict performance problems.
> Instead, write your code in the simplest, cleanest way possible, even if
> you think it might be slow. Get it all to work, focusing on an
> efficient algorithm. Then use the profiler to find out where your
> specific performance bottlenecks are, and tackle them in a targeted
> manner. I find that the simpler slow code in those few cases is STILL
> useful as documentation, or as a fallback for more general input cases
> that you might not need to optimize.
>
> Just my 2.5 cents...
>
> -Peter
---------
  Well said, Peter! It is often forgotten by Matlab users seeking "vectorized"
solutions that the Mathworks' official functions are themselves doing the
equivalent of for-loops, while-loops, not to mention a few other kinds of
repetitive behavior. Because they are able to make use of code that comes
closer to machine language in computers, this looping can usually be done
with less time wasted on overhead than in the higher Matlab language.
However, as Knuth indicates, this is frequently of small consequence in
comparison to an algorithm's inherent efficiency or lack thereof. The
conception that operations on arrays of numbers, as in matrix multiplication,
occur in parallel in inherently serial computers is an oxymoron.

Roger Stafford

Tags for 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