Loren on the Art of MATLAB

Turn ideas into MATLAB

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

|

Comments

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