Contents
 
Introduction
To R

Matrix Mania

Everything we've done so far has been based on vectors. R can also handle matrices:

Making Matrices

There are several ways of constructing a matrix. The function matrix() takes a vector argument and turns it into a matrix:
> x <- 1:12
> xmat <- matrix(x,ncol=3)
> xmat
     [,1] [,2] [,3] 
[1,]    1    5    9
[2,]    2    6   10
[3,]    3    7   11
[4,]    4    8   12
Here we construct a matrix with 3 columns and 4 rows using the numbers 1 to 12. Note how the matrix is filled by going down the rows first. We can change this behaviour by using the optional argument byrow=T, to tell it to fill the matrix by rows first:
>  matrix(x,ncol=3,byrow=T)
     [,1] [,2] [,3] 
[1,]    1    2    3
[2,]    4    5    6
[3,]    7    8    9
[4,]   10   11   12

Matrix Info

You can get the dimension of a matrix with the dim() function:
> x1 <- matrix(1:12,ncol=4)
> x1
     [,1] [,2] [,3] [,4] 
[1,]    1    4    7   10
[2,]    2    5    8   11
[3,]    3    6    9   12
> dim(x1)
[1] 3 4
The return value is a vector giving the number of rows and columns.

The summary function looks at each column in the matrix as vectors:

> summary(x1)
       X1            X2            X3            X4      
 Min.   :1.0   Min.   :4.0   Min.   :7.0   Min.   :10.0  
 1st Qu.:1.5   1st Qu.:4.5   1st Qu.:7.5   1st Qu.:10.5  
 Median :2.0   Median :5.0   Median :8.0   Median :11.0  
 Mean   :2.0   Mean   :5.0   Mean   :8.0   Mean   :11.0  
 3rd Qu.:2.5   3rd Qu.:5.5   3rd Qu.:8.5   3rd Qu.:11.5  
 Max.   :3.0   Max.   :6.0   Max.   :9.0   Max.   :12.0  

An overall summary of all elements in the matrix can be done using:
> summary(as.numeric(x1))
 Min. 1st Qu. Median Mean 3rd Qu. Max. 
    1    3.75    6.5  6.5    9.25   12

Matrix Maths

All the usual functions and operators work on matrices just as they did on vectors - element by element. If you multiply two matrices with * you'll get the product of each element, not the usual matrix multiplication - for that you use %*% like this:
> x1 <- matrix(1:6,ncol=2)  a 3x2 matrix...
> x1
     [,1] [,2] 
[1,]    1    4
[2,]    2    5
[3,]    3    6
> x2 <- matrix(6:1,ncol=3)  a 2x3 matrix...
> x2
     [,1] [,2] [,3] 
[1,]    6    4    2
[2,]    5    3    1
> x1 %*% x2               product is 3x3...
     [,1] [,2] [,3] 
[1,]   26   16    6
[2,]   37   23    9
[3,]   48   30   12
> t(x1)*x2                product is 2x3...
     [,1] [,2] [,3]
[1,]    6    8    6
[2,]   20   15    6

More Building

There are more functions that for constructing matrices - cbind and rbind augment matrices by adding columns or rows to existing matrices:
> x <- matrix(10:1,ncol=2)
> y <- cbind(x,1:5)
> y
     [,1] [,2] [,3]     
[1,]   10    5    1     
[2,]    9    4    2     This is now x
[3,]    8    3    3     with 1:5 added on.
[4,]    7    2    4
[5,]    6    1    5

> y <- rbind(y,c(99,99,99)) add a new row...
> y
     [,1] [,2] [,3] 
[1,]   10    5    1
[2,]    9    4    2
[3,]    8    3    3
[4,]    7    2    4
[5,]    6    1    5
[6,]   99   99   99  <- here

You can cbind() and rbind() matrices together:
> z <- cbind(y,rep(88,6),y)
> z
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] 
[1,]   10    5    1   88   10    5    1
[2,]    9    4    2   88    9    4    2
[3,]    8    3    3   88    8    3    3
[4,]    7    2    4   88    7    2    4
[5,]    6    1    5   88    6    1    5
[6,]   99   99   99   88   99   99   99

Matrix Subscripts

In the same way that you can extract part of a vector with square brackets, you can extract parts of a matrix. Only its slightly more complicated, of course.

You use square brackets with two numbers to get a single element:

> z[2,5]
[1] 9
You extract rows and columns by using one number with a comma. A single row or column from a matrix becomes a vector:
> z[,4]                A column
[1] 88 88 88 88 88 88
> z[3,]                A row
[1]  8  3  3 88  8  3  3
By using a vector as a subscript you can select several rows or columns - the resulting object then being a matrix:
> z[c(1,3,5),]                           three rows...
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] 
[1,]   10    5    1   88   10    5    1
[2,]    8    3    3   88    8    3    3
[3,]    6    1    5   88    6    1    5
>
> z[,5:7]                           three cols...
     [,1] [,2] [,3] 
[1,]   10    5    1
[2,]    9    4    2
[3,]    8    3    3
[4,]    7    2    4
[5,]    6    1    5
[6,]   99   99   99

> z[c(2,3),c(4,6)]       a 2x2 sub-matrix...
     [,1] [,2] 
[1,]   88    4
[2,]   88    3

More complicated subscripts...

A common thing to do is to get all the rows of a matrix which satisfy some condition defined by columns. Often you will store data in a matrix where each row corresponds to a person or a unit of some sort, and columns refer to measurement. You often want to get all the people (rows) that meet some qualification (age, sex, etc).

Let's define a matrix where the columns store an index from 1 to 5, then age, then sex (coded as 0/1) for five people.

> people <- cbind(c(1,2,3,4,5),c(43,55,52,23,46),c(1,1,0,1,1))
> people
     [,1] [,2] [,3] 
[1,]    1   43    1
[2,]    2   55    1
[3,]    3   52    0
[4,]    4   23    1
[5,]    5   46    1
Now we want to extract all the people who are over 50. We do it in one line, like this:
> oldies <- people[people[,2]>50,]
> oldies
     [,1] [,2] [,3] 
[1,]    2   55    1
[2,]    3   52    0
This looks tricky, but we can break it down, starting from the innermost stuff and working out.
> people[,2]
This is just the second column of the matrix - it is the vector c(43,55,52,23,46)
> people[,2]>50
This is a comparison of that vector with the number 50. The result is the vector of True and False values.
> people[ people[,2]>50 , ]
This just selects those rows that have a True value for the condition.

Reading Matrices from Files

You can read the file data.dat into a matrix using a combination of scan() which slurps everything into a vector, and matrix() to convert it into a matrix. You'll need to specify the byrow=F argument to matrix() in most cases:
> system('more data.dat')     look at the file...
1 3 4 3 4 5
3 4 5 4 3 2
2 3 2 1 2 1
> dat <- matrix(scan('data.dat'),ncol=6,byrow=F)
> dat
     [,1] [,2] [,3] [,4] [,5] [,6] 
[1,]    1    3    3    4    2    1
[2,]    3    4    4    3    3    2
[3,]    4    5    5    2    2    1

Contents