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.