bio_img_loren

Loren on the Art of MATLAB

Turn ideas into MATLAB

Note

Loren on the Art of MATLAB has been archived and will not be updated.

All about the Colon Operator

I have written several blog articles that cover some aspects of the : operator. Based on some recent posts to the MATLAB newsgroup, it seems worthwhile for me to compile the information.

Contents

Uses of :

There are several ways that you can use the : operator in MATLAB, and they serve different purposes. Most, but not all of them, have to do with indexing into an array.

  • Creating a list of numbers
  • Collapsing trailing dimensions (right- or left-hand side)
  • Creating a column vector (right-hand side behavior related to reshape)
  • Retaining an array shape during assignment (left-hand side behavior)
  • Working with all the entries in specified dimensions

Creating a List of Numbers

You can use the : operator to create a vector of evenly-spaced numbers. Here are the integers from -3 to 3.

list1 = -3:3
list1 =
    -3    -2    -1     0     1     2     3

Here are the first few odd positive integers.

list2 = 1:2:10
list2 =
     1     3     5     7     9

Here's how to divide the interval between 0 and pi into equally spaced samples.

nsamp = 5;
sliceOfPi = (0:1/(nsamp-1):1)*pi
sliceOfPi =
         0    0.7854    1.5708    2.3562    3.1416

Note that even though only a few digits of each value in sliceOfPi are printed out, they are double precision numbers. To see more digits, check out the function format.

Collapsing Trailing Dimensions

I have a 4-dimensional array and would like to find the sum of all the elements that are in the final row and column.

b = rand(3,2,6,4);
b32sum = sum(b(3,2,:))
b32sum =
   11.4622

If instead, I sum using all the dimensions, in this case, I get a 1x1x1x4 array instead of scalar output. If I sum these output values, I get my overall sum.

b32sumAll = sum(b(3,2,:,:))
overall = sum(b32sumAll)
b32sumAll(:,:,1,1) =
    2.8279
b32sumAll(:,:,1,2) =
    3.4177
b32sumAll(:,:,1,3) =
    1.9352
b32sumAll(:,:,1,4) =
    3.2815
overall =
   11.4622

Creating a Column Vector

Here's the size of the array b32sumAll.

size(b32sumAll)
ans =
     1     1     1     4

If I want to transform this into a column vector, I can use reshape, permute or : on the right-hand side.

b32vecR = reshape(b32sumAll,[],1);
b32vecP = permute(b32sumAll, [4 1:3]);
b32vec = b32sumAll(:)
allthesame = isequal(b32vec, b32vecP, b32vecR)
b32vec =
    2.8279
    3.4177
    1.9352
    3.2815
allthesame =
     1

Retaining Array Shape During Assignment

Now let me pour some new values into b32sumAll, the array that looks almost like a vector.

b32sumAll(:) = [1 2; 3 5]
b32sumAll(:,:,1,1) =
     1
b32sumAll(:,:,1,2) =
     3
b32sumAll(:,:,1,3) =
     2
b32sumAll(:,:,1,4) =
     5

Notice that I only have to have the same number of elements on both the left- and right-hand sides. The values are poured in from the right-hand side ordered as if that array had been turned into a column vector. Note that a scalar for the right-hand side is also acceptable and then MATLAB performs a scalar expansion to fill the left-hand side.

Working with All the Entries in Specified Dimensions

If I want to manipulate values in some specific dimensions, I can also use the : operator to specify the dimensions I'd like to leave alone. For example, suppose I want to perform a left shift on the values in the second dimension of my 3-D array. Let me first create an array for illustration.

a3 = zeros(2,3,2);
a3(:) = 1:numel(a3)
a3(:,:,1) =
     1     3     5
     2     4     6
a3(:,:,2) =
     7     9    11
     8    10    12

Now let's shift the column values all over to the left, and have the right-most one become the last column. Note that columns are dimension 2. Here's a way to do this.

a3r1 = a3(:,[2:size(a3,2) 1],:)
a3r1(:,:,1) =
     3     5     1
     4     6     2
a3r1(:,:,2) =
     9    11     7
    10    12     8

How do I do this if the array could be any number of dimensions, not just 3? I can't index with :, because I don't know how many : to use, since I don't knwo the dimension. In this case, use the string value ':', create the indices in a cell array, and use the notion of the comma-separated list to perform the actual indexing. For a3, here's what this looks like.

indices = {':', [2:size(a3,2) 1],':'}
a3rnew = a3(indices{:})
sameshifts = isequal(a3r1, a3rnew)
indices = 
    ':'    [1x3 double]    ':'
a3rnew(:,:,1) =
     3     5     1
     4     6     2
a3rnew(:,:,2) =
     9    11     7
    10    12     8
sameshifts =
     1

Now, more generally, when the number of dimensions is not known, I simply create a cell array of all ':' string values, replace the specific dimensions I care about with some other indexing expression, and then I can use the index cell array to do the operation.

a5 = zeros(2,5,2,3,4);
a5(:) = 1:numel(a5);
indices = repmat({':'}, 1, ndims(a5));
myshift = [2:size(a5,2) 1]
indices{2} = myshift
a5new = a5(indices{:});
myshift =
     2     3     4     5     1
indices = 
    ':'    [1x5 double]    ':'    ':'    ':'

Let's compare two "rows" and see that the values have shifted left by 1 column.

a5(1,:,2,2,3)
a5new(1,:,2,2,3)
ans =
   151   153   155   157   159
ans =
   153   155   157   159   151

Related Reference Material

For more in depth understanding of the various ways in which the : operator can be used, look in the MATLAB documention

and in related blog articles

: is Complicated

The : operator behaves differently in MATLAB depending on its usage. This can lead to confusion. Have I missed anything major on this topic? Let me know.




Published with MATLAB® 7.3


  • print

Comments

To leave a comment, please click here to sign in to your MathWorks Account or create a new one.

Loading...