Shift multiple columns, each with a different offset

前端 未结 3 750
Happy的楠姐
Happy的楠姐 2021-01-01 09:25

I have a data.table like this:

 date a b c d e f 
 2008 1 5 3 6 9 8 
 2008 3 6 2 1 5 8
 2008 2 8 3 4 3 0
 2009 5 5 3 6 9 8
 2009 3 3 2 2 5 5
 2010 2 8 3 7 7          


        
相关标签:
3条回答
  • 2021-01-01 09:48

    You can use Map to apply a different n to each column:

    cols <- setdiff(names(DT), "date")
    DT[, (cols) := Map(shift, .SD, seq_along(.SD) - 1L, fill = 0), .SDcols = cols]
    
    > DT
       date a b c d e f
    1: 2008 1 0 0 0 0 0
    2: 2008 3 5 0 0 0 0
    3: 2008 2 6 3 0 0 0
    4: 2009 5 8 2 6 0 0
    5: 2009 3 5 3 1 9 0
    6: 2010 2 3 3 4 5 8
    
    0 讨论(0)
  • 2021-01-01 09:50

    Here is a tidyverse solution. Approach is to remove the date column, then use purrr::map2_dfc and dplyr::lag to apply the correct shifts. map2 allows you to iterate along each column along with a vector of the correct shifts for each column, and then _dfc just makes sure it binds the columns back together into a data frame. The last line is just to add the date column back on the left hand side.

    library(tidyverse)
    tbl <- read_table2(
      "date a b c d e f
       2008 1 5 3 6 9 8
       2008 3 6 2 1 5 8
       2008 2 8 3 4 3 0
       2009 5 5 3 6 9 8
       2009 3 3 2 2 5 5
       2010 2 8 3 7 7 0"
    )
    
    tbl %>%
      select(-date) %>%
      map2_dfc(.x = ., .y = 1:ncol(.), ~ lag(.x, n = .y - 1, default = 0)) %>%
      bind_cols(date = tbl$date, .)
    #> # A tibble: 6 x 7
    #>    date     a     b     c     d     e     f
    #>   <int> <int> <dbl> <dbl> <dbl> <dbl> <dbl>
    #> 1  2008     1  0     0     0     0     0   
    #> 2  2008     3  5.00  0     0     0     0   
    #> 3  2008     2  6.00  3.00  0     0     0   
    #> 4  2009     5  8.00  2.00  6.00  0     0   
    #> 5  2009     3  5.00  3.00  1.00  9.00  0   
    #> 6  2010     2  3.00  3.00  4.00  5.00  8.00
    

    Created on 2018-02-23 by the reprex package (v0.2.0).

    0 讨论(0)
  • 2021-01-01 10:04

    doing it manually with shift, which shifts a column (either leading or lagging for upward or downward) n units, padding with whatever you want:

    library(data.table)
    DT <- data.table(date=c(2008, 2008, 2008, 2009, 2009, 2010), a=c(1,3,2,5,3,2),b=c(5,6,8,5,3,8),c=c(3,2,3,3,2,3),d=c(6,1,4,6,2,7),e=c(9,5,3,9,5,7),f=c(8,8,0,8,5,0))
    
    DT[,b := shift(b, n=1, type="lag", fill=0)]
    DT[,c := shift(c, n=2, type="lag", fill=0)]
    DT[,d := shift(d, n=3, type="lag", fill=0)]
    DT[,e := shift(e, n=4, type="lag", fill=0)]
    DT[,f := shift(f, n=5, type="lag", fill=0)]
    
    0 讨论(0)
提交回复
热议问题