Home > Software design >  Adding a countdown to data.table
Adding a countdown to data.table

Time:11-08

I have a data.table to which I want to add a countdown until a value of 1 appears in the flag column.

dt = structure(list(date = structure(19309:19318, class = c("IDate", 
"Date")), flag = c(0, 0, 0, 0, 0, 1, 0, 0, 0, 1)), class = c("data.table", 
"data.frame"), row.names = c(NA, -10L), .internal.selfref = <pointer: 0x55af7de49cb0>)
> dt
          date flag
 1: 2022-11-13    0
 2: 2022-11-14    0
 3: 2022-11-15    0
 4: 2022-11-16    0
 5: 2022-11-17    0
 6: 2022-11-18    1
 7: 2022-11-19    0
 8: 2022-11-20    0
 9: 2022-11-21    0
10: 2022-11-22    1

Here is the expected output

          date flag countdown
 1: 2022-11-13    0 5
 2: 2022-11-14    0 4
 3: 2022-11-15    0 3
 4: 2022-11-16    0 2
 5: 2022-11-17    0 1
 6: 2022-11-18    1 0
 7: 2022-11-19    0 3
 8: 2022-11-20    0 2
 9: 2022-11-21    0 1
10: 2022-11-22    1 0

A data.table solution is preferred.

CodePudding user response:

A data.table solution is not only preferred but also beautiful.

library(data.table)

dt = structure(list(date = structure(19309:19318, class = c("IDate", 
"Date")), flag = c(0, 0, 0, 0, 0, 1, 0, 0, 0, 1)), class = c( 
"data.frame"), row.names = c(NA, -10L))

setDT(dt)

dt[, countdown := rev(1:.N), by=rleid(flag)][flag==1, countdown:=0 ]
dt
#>           date flag countdown
#>  1: 2022-11-13    0         5
#>  2: 2022-11-14    0         4
#>  3: 2022-11-15    0         3
#>  4: 2022-11-16    0         2
#>  5: 2022-11-17    0         1
#>  6: 2022-11-18    1         0
#>  7: 2022-11-19    0         3
#>  8: 2022-11-20    0         2
#>  9: 2022-11-21    0         1
#> 10: 2022-11-22    1         0

Created on 2022-11-07 with reprex v2.0.2

edit

dt[, countdown := .N:1 * !flag, by=rleid(flag)]

for brevity.

CodePudding user response:

Another data.table option

> cbind(dt, dt[, .(countdonwn = .N - seq(.N)), rev(cumsum(rev(flag)))][, 2])
          date flag countdonwn
 1: 2022-11-13    0          5
 2: 2022-11-14    0          4
 3: 2022-11-15    0          3
 4: 2022-11-16    0          2
 5: 2022-11-17    0          1
 6: 2022-11-18    1          0
 7: 2022-11-19    0          3
 8: 2022-11-20    0          2
 9: 2022-11-21    0          1
10: 2022-11-22    1          0
  • Related