Search code examples
rdataframedatereshape2

How to shift data by a factor of two months in R?


I would like to move down my entire data by a factor of two months. For example, if my data starts on Jan 01, i want to move the data in such a way that the data corresponds to March 01. Likewise, November data would become January data for the next year. Here is my sample code

DF <- data.frame(seq(as.Date("2001-01-01"), to= as.Date("2003-12-31"), by="day"),
                     A = runif(1095, 0,10),
                     D = runif(1095,5,15))
colnames(DF) <-  c("Date", "A", "B")

I tried DF$Date <- DF$Date + 61 but this moved the entire data.frame by a factor of two months including the dates- I just want the data to moved down.


Solution

  • I think a simple merge with itself will work here.

    First, random data that you can reproduce,

    headtail <- function(x, n = 4) { print(head(x, n=n)); print(tail(x, n=n)); }
    
    set.seed(42)
    DF <- data.frame(seq(as.Date("2001-01-01"), to= as.Date("2003-12-31"), by="day"),
                         A = runif(1095, 0,10),
                         D = runif(1095,5,15))
    colnames(DF) <-  c("Date", "A", "B")
    headtail(DF)
    #         Date        A         B
    # 1 2001-01-01 9.148060 10.049361
    # 2 2001-01-02 9.370754 10.324953
    # 3 2001-01-03 2.861395  5.868702
    # 4 2001-01-04 8.304476 14.156014
    #            Date         A         B
    # 1092 2003-12-28 0.3284422  6.449250
    # 1093 2003-12-29 7.7729724  7.270769
    # 1094 2003-12-30 5.2614178 11.023033
    # 1095 2003-12-31 2.6612188 13.923079
    

    Now the merge. I use just the Date on the first frame so that the shifted Date will attached the data from the second frame.

    out <- merge(DF["Date"], transform(DF, Date = Date + 61),
                 by = "Date", all = TRUE)
    headtail(out)
    #         Date  A  B
    # 1 2001-01-01 NA NA
    # 2 2001-01-02 NA NA
    # 3 2001-01-03 NA NA
    # 4 2001-01-04 NA NA
    #            Date         A         B
    # 1153 2004-02-27 0.3284422  6.449250
    # 1154 2004-02-28 7.7729724  7.270769
    # 1155 2004-02-29 5.2614178 11.023033
    # 1156 2004-03-01 2.6612188 13.923079
    

    That is preserving all data. If you want just up until the last date of the original frame, then just change all= to all.x=:

    out <- merge(DF["Date"], transform(DF, Date = Date + 61),
                 by = "Date", all.x = TRUE)
    headtail(out)
    #         Date  A  B
    # 1 2001-01-01 NA NA
    # 2 2001-01-02 NA NA
    # 3 2001-01-03 NA NA
    # 4 2001-01-04 NA NA
    #            Date         A         B
    # 1092 2003-12-28 9.7939015 14.165207
    # 1093 2003-12-29 1.7047221  8.269991
    # 1094 2003-12-30 0.4273437  8.041551
    # 1095 2003-12-31 1.4283236  5.053276
    

    dplyr

    library(dplyr)
    as_tibble(DF) %>%
      mutate(Date = Date + 61) %>%
      full_join(., select(DF, Date), by = "Date") %>%
      arrange(Date)