Doug's MATLAB Video Tutorials

March 13th, 2009

Reshape a matrix without using a for loop

RESHAPE is a very useful function, but it is something that a lot of MATLAB users do not discover until someone is looking at their code and says “Why are you using a for loop for that?” If you know how to use RESHAPE, there is not much to be learned from this video. If you do not know about RESHAPE, well consider me that person looking over your shoulder saying “Why are you…”

70 Responses to “Reshape a matrix without using a for loop”

  1. Waggy replied on :

    Doug,

    I have a quick question which is very much pertinent to your phrase “why are you using a for loop for that?” – I may be about to be on the receiving end of that statement!

    I have a cell of 10000 strings of which i am identifying relevant strings using strmatch. This returns me the row numers of each match. However i require a logic return of equal dimension (1 = match). The only way i can acheieve this is using a for loop that;

    a = strmatch(‘abc’, data, ‘exact’)

    for loop = 1:10
    b(a(loop)) = 1
    end

    Problem is, with a huge data set this can take a long time!! Can i speed this process up??

    Many thanks,

    Waggy

  2. Doug replied on :

    Waggy,

    How about this example?

    list = {‘a’,'b’,'c’,'a’,'b’}
    a = strmatch(‘a’,list,’exact’)
    b = zeros(size(list))
    b(a) = 1

    -Doug

  3. Waggy replied on :

    Doug,

    That’s such a simple way of speeding up the process, thanks!! I have a similar issue involving the HUGE delays of ‘For Loops’. I have a date,hr,min,sec column of data however as it is in the format eg ’04 134911′ xlsread imports as a string. I therefore have to str2num, which give a double eg [04,134911]. I only require the hr,min,sec so i then assign the (1,2) double to my data set. This works fine however is very slow with a 1:3000 ‘for loop’!! Is there a similar method that would improve the efficiency of my code??

    Many thanks,

    Waggy

  4. dhull replied on :

    @Waggy,

    Look at the profiler for your code. You may find it is not the FOR loop that is slowing things, but specific functions in the FOR loop.

    Please show a simple version of your code, I bet we can figure it out if you do.

    Doug

  5. John S replied on :

    I have a similar problem as mentioned above: my for loops appear to be really slow. I’ve read online that for loops in matlab are “slow” and “not elegant”. I’ll paste some simplified text below, but essentially I have a video (~20-30 images long) of 512×512 pixel images and want to test each pixel for certain constraints and then save data on the pixels I like. As it is it takes around 30 minutes to go through a 30-frame movie. I have 2 nested for loops doing this:

    
    function d= get_frames(im, startframe)
    
    for frame=framefirst:framelast;
    
    data = get_frames(handles.im, frames);
        addframe=0;
        for ycount=yfirst:ylast;
            addframe=0;
            for xcount=xfirst:xlast; 
    
               while dwellcheck==1;
    
               %calculate ~10 parameters (means and stds and such)
    
               if spot>=parameter1 & spot>=parameter2 & spot>constant
    

    after this i check to see if the same spot (x,y) in the next frame (data = get_frames(handles.im, frames+addframe);) also meets these parameters.

    when checked all frames, then save spot and go back to searching for next x,y spot.

    then go to next startframe.

    Any advice? Or am I stuck with the speed? Thanks a lot!

  6. dhull replied on :

    John,

    Please check this video:
    http://blogs.mathworks.com/videos/2006/10/19/profiler-to-find-code-bottlenecks/

    It is important to find out where your bottleneck really is. then it can be diagnosed at the line level.

    Doug

  7. John S replied on :

    Ok sweet, I played with the profiler for a while and was able to cut the program time to about half what it was (now it takes about 75 seconds to run through each image of a movie). It turns out having to do the following calculations at each point in a 512×512 pixel image take up all the time (duh):

    accstdev = std([datamatrixacc(1,1:5)...
                        datamatrixacc(2,1) datamatrixacc(2,5)...
                       datamatrixacc(3,1) datamatrixacc(3,5)...
                       datamatrixacc(4,1) datamatrixacc(4,5)...
                       datamatrixacc(5,1:5)]);  %takes up 32% of the time
    donstdev = std([datamatrixdonor(2, 2:4) datamatrixdonor(3,2:4) datamatrixdonor(4,2:4)]); %takes up 30% of the time
    spotmean3 = mean2(datamatrixacc(2:4, 2:4)); %each of these take up about 5% of the time
    spotmean4 = mean2(datamatrixacc(1:5, 1:5));
    spotmean1 = mean2(datamatrixdonor(2:4, 2:4));
    spotmean2 = mean2(datamatrixdonor(1:5, 1:5));
    

    I saved a lot of time by creating a new 5×5 matrix around each spot and accessing that instead of the entire 512×512 matrix. Any other recommendations? Thanks again.

  8. dhull replied on :

    John,

    I am glad the profiler is working as you need. Assuming that datamatrixacc is changing each time through the loop (no sense doing those calculations over and over on static data…) I think that things look good here.

    In the profiler, it should say how many times each line is being executed. I think that each of these calculations is very quick, but you are doing them an extraordinarily large number of times.

    -Doug

  9. John S replied on :

    Yeah the “datamatrixacc” is a 5×5 matrix around each individual pixel taken from the entire 512×512 matrix of the image while I run through multiple for loops (“for x=1:512″ and “for y=1:512″).

    When I googled “how to make matlab faster” one thing they recommended was using vectorization instead of for loops (I guess instead of “for x=1:512″ do something like “x=1:512″ and call it each time as x(1), x(2), etc.). Will that really make anything faster, or is it going to take a while when I’m going through ~250000 pixels/frame no matter what?

    Thanks for the advice.

    John

  10. dhull replied on :

    John,

    It is going to take a while. The idea that vectorization is faster than for loops was once true, but with the JIT accelerator, it is mostly stylistic choice at this point.

    I do not see a more clever way of doing this kind of operation. Some things are just computationally expensive.

    -Doug

  11. dross replied on :

    Hi,
    i have a concantenated matrix of 118×9. each row represent a particular time/frame.i want to construct a rotation matrix by extracting every row,reshaping the row into a 3×3 matrix for each row.anybody with an idea.
    cheers

  12. dhull replied on :

    @dross,

    Loop through each row, use reshape.

    Doug

  13. dross replied on :

    i try doing that and it says to me and it gives me this error:
    >> for t=1:118;
    x(t)=[i_twalk(t,:) j_twalk(t,:) k_twalk(t,:)];

    A=reshape (x(t),3,3);
    end
    ??? In an assignment A(I) = B, the number of elements in B and
    I must be the same.
    i do not know what is wrong.help

  14. dhull replied on :

    Dross,

    Take a look at this similar problem,

    m = rand(3,9)
    for i = 1:3
    a(:,:,i) = reshape(m(i,:),3,3);
    end

    a

    Notice how a is becoming a 3 dimensional matrix, storing each in its own layer?

    Doug

  15. dross replied on :

    hello,
    is there anyway i can change the dimension of my 3x3x118 rotation array so that i have a 3×354 array but with the elements in the same order ie;for every 3x3x1 element followed by 3x3x2….till 3x3x118? squeeze or reshape??help.
    thanks

  16. dhull replied on :

    @dross,

    This works,

    a = rand(3,3,118);
    b = reshape(a,[3 354])

    You will need to be more clear with the ordering of the elements to explain more. A for loop will certainly work if reshape can not be convinced to.

    Doug

  17. dross replied on :

    Doug,
    thanks a lot for your replies,they are very helpful. i want to calculate the norm for mxn matrix? i have a concantenated matrix which i have to get the norm of each row. any help?

  18. dhull replied on :

    dross,

    If you have a matrix:

    A = [1 2 3; 1 2 3; 1 2 3];
    You can get the sub matrices

    JustOnes = A(:,1)

    Then you can do what ever operations you want with that.

    Doug

  19. Karen replied on :

    Hello,
    I’m a bit of a matlab beginner and I’m hoping someone can help me. I am trying to find a way to change the ordering of where reshape puts the elements when I am going from a single row vector of many elements into an array. This may be one of those cases where I have to use a forloop instead of reshape…

    Say I have vector A which is [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]

    If I do reshape(A,4,4,1) I get:

    1 5 9 13
    2 6 10 14
    3 7 11 15
    4 8 12 16
    But I want to reshape my vector into a matrix in a zig-zag (or snaking) pattern, instead of always starting at the top and moving down. For example, I want to “reshape” (or use some other code) to yield:

    1 8 9 16
    2 7 10 15
    3 6 11 14
    4 5 12 13

    I need code that will perform this operation on vectors that have many, many elements. Thanks!

  20. dhull replied on :

    We were just solving this problem internally for a contest!

    Here is the solution:

    n = 4
    a = reshape(1:n^2,n,n)’
    a(2:2:end,:) = fliplr(a(2:2:end,:));
    a=a’

    http://en.wikipedia.org/wiki/Boustrophedon

    Enjoy,
    Doug

  21. Charles replied on :

    Doug,

    I just can’t seem to find any help on ‘for’ loops that actually help, would please take a look at the following and see what help you can offer?

    I have 5 [1X1270] matrices that I need to perform the following equation with at each timestep:

    x=((a*b)-(c*d))/e

    I know it takes a for loop but I can’t get one to work. Matlab gives me an error everytime.

    Charles

  22. dross replied on :

    hello all,
    i have a multidimensional array,1x1x116 and i want to re-arrange it into a 1×116 matrix.any ideas?

  23. dhull replied on :

    @dross,

    Use the function SQUEEZE to do this.

    Doug

  24. dhull replied on :

    @ Charles,

    Since MATLAB is matrix based, you do not need a for loop to do this. You need array multiplication and array division:

    x = ((a.*b)-(c.*d))./e

    Notice the “.*” and “./” instead of “*” and “/”.

    See this video for more info:
    http://blogs.mathworks.com/videos/2009/08/27/basics-implementing-a-formula-in-matlab/

    I just put it up last week. What timing!

    Doug

  25. Charles replied on :

    Doug,

    Appreciate your help and I’ll have a looksy at the video.

    Thanks again

  26. Faisal replied on :

    dear all

    i am a beginner in matlab, i have some problem. i have matrix with 500×500 dimension, i want to partition in each have 20×20 dimension so there is have 25 groups matrix. what the code looping in matlab. thx

  27. dhull replied on :

    @Faisal,

    What is a “groups matrix”?

    Doug

  28. asad replied on :

    i am the matlab beginer.i have to convert any n*n matrix into a single row vector.plz help

  29. dhull replied on :

    @asad,

    M = magic(4)
    M(:)’

    Doug

  30. crazee replied on :

    Hi Doug,

    I have a question. I have a 4-D matrix like 1000x2x2x10. I reshape it to a 2-D 1000×40 matrix using:
    newmatrix = reshape(oldmatrix,1000,2*2*10)

    I wanted to know how is the reshape working? Basically I wanted to know what are the 40 columns in the new matrix corresponding to the original dimensions (2x2x10) of my old matrix. Does it go like:
    newmatrix(:,1) = oldmatrix(:,1,1,1)
    newmatrix(:,2) = oldmatrix(:,1,1,2)
    .
    .
    newmatrix(:,11) = oldmatrix(:,1,2,1)
    .
    .
    newmatrix(:,21) = oldmatrix(:,2,1,1)
    .
    .
    newmatrix(:,31) = oldmatrix(:,2,2,1)
    .
    .
    newmatrix(:,40) = oldmatrix(:,2,2,10)

    Appreciate your help. Thanks!

  31. dhull replied on :

    @”Crazee”

    When I am faced with a problem like this, I make a simple test case and see what happens. Look at this:

    a = [1 2; 3 4]
    A(:,:,1) = a
    A(:,:,2) = a+4
    A(:,:,:,2) = A + 10
    reshape(A,[2,8])
    
    a =
    
         1     2
         3     4
    
    A =
    
         1     2
         3     4
    
    A(:,:,1) =
    
         1     2
         3     4
    
    A(:,:,2) =
    
         5     6
         7     8
    
    A(:,:,1,1) =
    
         1     2
         3     4
    
    A(:,:,2,1) =
    
         5     6
         7     8
    
    A(:,:,1,2) =
    
        11    12
        13    14
    
    A(:,:,2,2) =
    
        15    16
        17    18
    
    ans =
    
         1     2     5     6    11    12    15    16
         3     4     7     8    13    14    17    18
    
  32. Carolyn replied on :

    Hey everyone. I am having a problem that ‘kind of’ relates to this. I have a mtx that is 9511×2, and I am trying to break it up according to the value in the second column, into smaller matrices for each value. for example i have

    345 2
    367 2
    122 2
    12 2
    345 3
    12 3
    34 3

    i want to end up with a mtx
    345 2
    367 2
    122 2
    12 2

    and another
    345 3
    12 3
    34 3

    etc

    so that I can use the each on its own for further manipulation. I’ve tried to used if else statements and such to delete rows, etc. but it is slow, not working, and I keep making loops that run forever (and I’m on a mac so I’m pretty sure I don’t have a break key). I know there has to be an easy way to do this, please help!

  33. dhull replied on :
    a  = [11 1; 12 1; 23 2; 24 2]
    
    target = 2;
    [vr, vc] = find(a(:,2) == target);
    
    newMatrix = a(vr, :)
    
  34. niken replied on :

    I have a problem related to loop for string

    how to make

    y = havehavehave……

    i used
    n=1;
    k=’used’;
    while k=<5
    disp(k)
    n=n+1;
    end

    the result is
    have
    have
    have
    heve

    how to make the result is y=havehavehavehave ?

  35. dhull replied on :

    @Niken,

    Create the string and then display it at the end. DISP is going to automatically put a line feed carriage return in there.

    Doug

  36. Carolyn replied on :

    Thanks Doug! This is exactly what I needed, I appreciate your help!

  37. sangeeta angadi replied on :

    i want to divide 16×18 matrix into smaller 3×3 matrices. how to do this

  38. dhull replied on :

    @sangeeta

    This should show you what you need.

    >> a = magic(6)
    
    a =
    
        35     1     6    26    19    24
         3    32     7    21    23    25
        31     9     2    22    27    20
         8    28    33    17    10    15
        30     5    34    12    14    16
         4    36    29    13    18    11
    
    >> b = a(1:3,1:4)
    
    b =
    
        35     1     6    26
         3    32     7    21
        31     9     2    22
    
  39. elnaz replied on :

    I have a problem with vectorizing the loops below:

    
     for u=1:13
            c=0;
            for i=i1:i2
                for j=j1:j2
                    a=I3(i,j);
    
                    if (a==u)
                        x=[i,j];
                        c=k(norm((x-center)./dim)^2)+c;
                    end
                end
            end
            q(u)=c/f;
        end
    

    would you please give me an obvious answer

  40. dhull replied on :

    @Elnaz,

    Why do you want to vectorize this? The code looks fine to me, why do you want to change it?

    Doug

  41. elnaz replied on :

    I think that if I vectorize it, it would be faster.@dhull

  42. dhull replied on :

    Have you run it through the profiler to find out where the bottlenecks are? How long is it taking, what is your goal speed? Is this part of a larger project where a speed-up here will matter in the context of the whole project?

    Please post code that can be copied and pasted and works so we can see it. Your code above is using variables of unknown composition, so we can not really do much with it.

  43. elnaz replied on :

    hi everyone.I have a problem . I have encountered with aproblem. I want to know how long it takes for a specified mfile to be executed so I use the ” tic toc” command but it does not give a correct result. I mean it is different from the time that I measure by my own watch. for example it takes less than a second according to my watch but the “tic toc” command gives 12 seconds.I am mixed up. can anyone explain this problem for me???!
    thanks in advance.

  44. dhull replied on :

    @elnaz

    Is your code short enough to be posted? If not please e-mail it to me so I can reproduce it.

    Doug

  45. elnaz replied on :

    oh, I have another question ,too.do you know any command which draws a rectangle or square by using the center , length and width of the rectangle. I am working on object tracking so I need a simple command to plot a rectangle arround the object.

  46. dhull replied on :

    @elnaz,

    Let’s keep these comments focused on the topics of the video. There are better forums for these questions.

    http://www.mathworks.com/matlabcentral/newsreader/

    Doug

  47. Obi replied on :

    Hi Doug,
    The reshape function when used to transform an n x m matrix to an (nm) x 1 vector reorders column-wise. How do i get it to perform the transformation row-wise?

    if a = 1 2 3
    4 5 6
    I would like [1 2 3 4 5 6] rather than [1 4 2 5 3 6]

    Thanks.

  48. dhull replied on :

    @obi,

    Transpose first. (‘ after matrix transposes)

    Doug

  49. Daniel replied on :

    Hi,
    I have a vector x=[2 4 6].
    How would you create a 3,3,3 matrix with
    A(:,:,1)=[2 2 2; 2 2 2; 2 2 2]
    A(:,:,2)=[4 4 4; 4 4 4; 4 4 4]
    A(:,:,6)=[6 6 6; 6 6 6; 6 6 6]
    Any hints?

    Best wishes
    Daniel

  50. dhull replied on :

    @Dabiel,

    I think you just did.

    How about this modification:

    A(:,:,1)=ones(3)*x(1);
    A(:,:,2)=ones(3)*x(2);
    A(:,:,6)=ones(3)*x(3);

    Doug

  51. dhull replied on :

    @Dabiel,

    I think you just did.

    How about this modification:

    
    A(:,:,1)=ones(3)*x(1);
    A(:,:,2)=ones(3)*x(2);
    A(:,:,6)=ones(3)*x(3);
    

    Doug

  52. Daniel replied on :

    @dhull,
    Hi Doug,
    thanks for your quick reply.
    Of course i do not want to write that explicitly. What if x is 1 by 10?
    I hope there is a neat repmat/reshape combo which i can use.
    Daniel

  53. dhull replied on :

    @Daniel,

    I do not see the mapping from elements of x to a specific layer of A. They were going to layers 1,2 and 6. If there is no pattern, you have to do this manually.

    Doug

  54. Daniel replied on :

    In other words:
    I want

    x=[2 4 6]
    for k=1:numel(x)
        A(:,:,k)=ones(numel(x)).*x(k);
    end
    

    without the loop.
    Daniel

  55. Daniel replied on :

    Sorry, Doug!
    I have a typo in #49, A(:,:,6) is A(:,:,3)
    Daniel

  56. dhull replied on :

    @Daniel,

    There might be some crazy, convoluted way to do this without a loop, but the loop is clear and efficient (especially if you pre-allocate) Why bother making something more obscure and hard to read?

    Doug

  57. Daniel replied on :

    I think it looks sexier. :-)
    Daniel

  58. dhull replied on :

    @Daniel

    You can comment out something like this:

    % A = reshape(reshape(transpose(magicalReshape(x,-4,3)),4,-10),-3,3.14);
    % The above line works, but so that you Noobs can maintain this, I will write it out with a non-guru type of loop.

    You get to feel clever and have maintainable code!

    -Doug

  59. david replied on :

    how to convert [1 2 3 4] to
    [1 1 3 3
    2 2 4 4]?

  60. Loren replied on :

    David-

    Something like this should work:

    A = 1:4;
    B = reshape(A,2,2)
    C = B(:,[1 1 2 2])
    

    –Loren

  61. Jerry replied on :

    Hi Doug,

    I also have a question about row-wise transformation.
    suppose a=[ 1 2 3 4; 5 6 7 8], if I want to get
    b=[1 2; 5 6; 3 4; 7 8]. Is there a simple way of using reshape without for loop? Thanks in advance.

    Jerry

  62. dhull replied on :

    @Jerry,

    There might be some clever way to do this without for loops, but it would be confusing and non-intuitive. Just use a clear and easy loop to do this.

    Doug

  63. Kwashie replied on :

    I have a 1 x 6 matrix which i need to add to a 1 x 12 matrix after which i have to multiply by a 1 x 18 matrix. Can you please guve me an idea on how i con do that. Thanks

  64. dhull replied on :

    Kwashie,

    What does it even meant to do these operations? I can not understand what that would even look like.

    Doug

  65. dan replied on :

    hello lets say i have
    a = [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20]
    instead of reshape it up n down which will result to this
    1 3 5 7 9 11 13 15 17 19
    2 4 6 8 10 12 14 16 18 20

    i want it to be like these
    1 2 3 4 5 6 7 8 9 10
    11 12 13 14 15 16 17 18 19 20

    is it possible? Thanks in advance.

  66. dhull replied on :

    @dan,

    Transpose it first, then reshape.

    Doug

  67. dan replied on :

    Do you mean this?

    a = [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20];
    b = transpose(a);
    c = reshape(b,2,10)

    I still get the up and down result. Sorry I’m very new to matlab. Hope you can help.Many many thanks in advance.

  68. dan replied on :

    Hi, sorry to bother you i think i got it. Thank you for you wonderful tips!

  69. Vishnu replied on :

    Doug, I have a quick question, the answer to which I couldn’t find anywhere. Does reshape work the exact same way each time you do it? For example, I want to reshape a 3D matrix to a single vector. However, each dimension means something to me and I need to do this for many 3D matrices and want the entries in the final vector to correspond to the same dimensions. So does reshape go through the 3D matrix in the same order every time I reshape a 3D matrix? Sorry if this is a dumb question.. I’m a matlab beginner. Thanks for your time!

  70. Doug replied on :

    Vishnu,

    There is no randomness in reshape. It is deterministic, and will always give the same results for the same inputs.

    Doug

Leave a Reply

Wrap code fragments inside <pre> tags, like this:

<pre class="code">
a = magic(3);
sum(a)
</pre>

If you have a "<" character in your code, either follow it with a space or replace it with "&lt;" (including the semicolon).


MathWorks

Doug Hull is a proud MathWorker who is on a mission to help you with MATLAB.

Doug's picture

These postings are the author's and don't necessarily represent the opinions of The MathWorks.