ManInMoon
ManInMoon

Reputation: 7005

Why lag in r is not working for matrix?

I am trying to lag a matrix:

> B = matrix( c(2, 4, 3, 1, 5, 7),  nrow=3, ncol=2)
> B
     [,1] [,2]
[1,]    2    1
[2,]    4    5
[3,]    3    7
> lag(B)
     [,1] [,2]
[1,]    2    1
[2,]    4    5
[3,]    3    7

Why does lag(B) NOT give:

> lag(B)
     [,1] [,2]
[1,]    0    0
[2,]    2    1
[3,]    4    5

Upvotes: 7

Views: 4362

Answers (4)

SavedByJESUS
SavedByJESUS

Reputation: 3314

The EASIEST way to lag a matrix in R is by using the `embed()' function. Here is a quick reproducible example:

> # Create a 5x2 matrix
> m <- replicate(2, 1:5)
> m
     [,1] [,2]
[1,]    1    1
[2,]    2    2
[3,]    3    3
[4,]    4    4
[5,]    5    5
> 
> # Use the 'embed()' function to lag the matrix
> lag_m <- embed(m, 3)
> lag_m
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    3    3    2    2    1    1
[2,]    4    4    3    3    2    2
[3,]    5    5    4    4    3    3

A few important words about the embed() function and its output.

  • The function is used as follows: embed(matrix, lag+1)

The first argument of the function is the matrix we want to lag. The second argument; however, is the number of lags we want "plus 1". Therefore, embed(matrix, 3) means that we want to lag the matrix by 2 time periods.

  • The output of the function is the lagged matrix and it is as follows:

. the first two columns represent the original m matrix, but the number of rows is adjusted for the number of lags (5 rows originally minus a 2-time-period lag)

. the second set of columns (columns 3 and 4) are the m matrix lagged by 1 time period

. the third set of columns (columns 5 and 6) are the m matrix lagged by 2 time periods.

Upvotes: 1

G. Grothendieck
G. Grothendieck

Reputation: 269481

It is because lag shifts the times of the object, not the data values. Its really intended for time series objects.

When lag is used on a plain matrix, B, the lag.default method is invoked. Since there is no time associated with a plain matrix it assumes the times are 1, 2, ..., NROW(B) :

> time(B)
[1] 1 2 3
attr(,"tsp")
[1] 1 3 1

and shifts the times by one so that they now start from 0:

> time(lag(B))
[1] 0 1 2
attr(,"tsp")
[1] 0 2 1

Use a time series class if you want to combine objects that have times. (The first column is the times in the displays below.)

> library(zoo)
>
> # zooreg - regular series or almost so
> B.zr <- zooreg(B)
> merge(B.zr, lag(B.zr))
  B.zr.1 B.zr.2 lag(B.zr).1 lag(B.zr).2
0     NA     NA           2           1
1      2      1           4           5
2      4      5           3           7
3      3      7          NA          NA

> # zoo - irregular series
> B.z <- zoo(B)
> merge(B.z, lag(B.z))
  B.z.1 B.z.2 lag(B.z).1 lag(B.z).2
1     2     1          4          5
2     4     5          3          7
3     3     7         NA         NA

Note the difference between lag.zooreg which can extend beyond the range of the original times producing a 0 time and lag.zoo which cannot because there is no regularity assumption in the latter.

We can also use ts class which assumes regularity so a 0 time can be produced but there is no merge.ts making it less useful here.

Upvotes: 4

Jilber Urbina
Jilber Urbina

Reputation: 61154

I've never understood lag function, instead I'd use Lag from quantmod package:

> # library(quantmod)
> apply(B, 2, Lag)
     [,1] [,2]
[1,]   NA   NA
[2,]    2    1
[3,]    4    5

If you want (or need) lag a matrix without ts attributes one way could be using apply and Lag from quantmod package, but if you don't want to install a package for just one function, then you could write your own function, an idea would be like this:

lag.matrix <- function(x, k=1){
  N <- ncol(B)
  l <- matrix(embed(x,k+1)[, -c(1:(k*N))], ncol=N)
  NAs <- matrix(rep(NA, k*N), ncol=N)
  rbind(NAs, l)
}
> lag.matrix(B, k=1)
     [,1] [,2]
[1,]   NA   NA
[2,]    2    1
[3,]    4    5
> lag.matrix(B, k=2)
     [,1] [,2]
[1,]   NA   NA
[2,]   NA   NA
[3,]    2    1

Another soluction could be the one posted as a comment by @GSee which uses lag as you wish.

> lag(xts(B, .POSIXct(0)+0:(nrow(B)-1)))
                    [,1] [,2]
1970-01-01 01:00:00   NA   NA
1970-01-01 01:00:01    2    1
1970-01-01 01:00:02    4    5

Upvotes: 2

Matthew Lundberg
Matthew Lundberg

Reputation: 42639

l <- matrix(0,nrow(B),nrow(B))
l[-1,-nrow(B)] <- diag(nrow(B)-1)
l
##     [,1] [,2] [,3]
## [1,]    0    0    0
## [2,]    1    0    0
## [3,]    0    1    0

l %*% B
##      [,1] [,2]
## [1,]    0    0
## [2,]    2    1
## [3,]    4    5

Upvotes: 1

Related Questions