Wookeun Lee
Wookeun Lee

Reputation: 463

How do I lag a data.frame?

I'd like to lag whole dataframe in R.

In python, it's very easy to do this, using shift() function (ex: df.shift(1))

However, I could not find any as an easy and simple method as in pandas shift() in R.

How can I do this?

> x = data.frame(a=c(1,2,3),b=c(4,5,6))
> x
  a b
1 1 4
2 2 5
3 3 6

What I want is,

> lag(x,1)
> 
  a b
1 NA NA
2 1 4
3 2 5

Any good idea?

Upvotes: 4

Views: 7741

Answers (3)

Denis
Denis

Reputation: 12077

Just for completeness this would be analogous to how zoo implements it (but for a data.frame since the zoo lag(...) method doesn't work on data.frame objects):

lag.df <- function(x, lag) {
  if (lag < 0)
    rbind(NA, head(x, lag))
  else
    rbind(tail(x, -lag), NA)
}

and use like this:

x <- data.frame(dt=c(as.Date('2019-01-01'), as.Date('2019-01-02'), as.Date('2019-01-03')), a=c(1,2,3),b=c(4,5,6))
lag.df(x, -1)
lag.df(x, 1)

or you can just use zoo:

library(zoo)
x <- data.frame(dt=c(as.Date('2019-01-01'), as.Date('2019-01-02'), as.Date('2019-01-03')), a=c(1,2,3),b=c(4,5,6))
x.zoo <- read.zoo(x) 
lag(x.zoo, -1)
lag(x.zoo, 1)

Upvotes: 1

lmo
lmo

Reputation: 38500

Pretty simple in base R:

rbind(NA, head(x, -1))
   a  b
1 NA NA
2  1  4
3  2  5

head with -1 drops the final row and rbind with NA as the first argument adds a row of NAs.


You can also use row indexing [, like this

x[c(NA, 1:(nrow(x)-1)),]
    a  b
NA NA NA
1   1  4
2   2  5

This leaves an NA in the row name of the first variable, to "fix" this, you can strip the data.frame class and then reassign it:

data.frame(unclass(x[c(NA, 1:(nrow(x)-1)),]))
   a  b
1 NA NA
2  1  4
3  2  5

Here, you can use rep to produce the desired lags

data.frame(unclass(x[c(rep(NA, 2), 1:(nrow(x)-2)),]))
   a  b
1 NA NA
2 NA NA
3  1  4

and even put this into a function

myLag <- function(dat, lag) data.frame(unclass(dat[c(rep(NA, lag), 1:(nrow(dat)-lag)),]))

Give it a try

myLag(x, 2)
   a  b
1 NA NA
2 NA NA
3  1  4

Upvotes: 7

Dan
Dan

Reputation: 12074

library(dplyr)
x %>% mutate_all(lag)

   a  b
1 NA NA
2  1  4
3  2  5

Upvotes: 4

Related Questions