【问题标题】:subset a time series around a specific value in a data.table围绕 data.table 中的特定值对时间序列进行子集化
【发布时间】:2021-02-12 01:20:59
【问题描述】:

这可能是一个基本问题,但是如何围绕 data.table 中的特定值对时间序列进行子集化?我有数据:

DT <- data.table(time = seq(1, 14), b = c(0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1 ,0, 0))

现在我想在b 中查找所有带有 1 的行,并在找到的观察之前和之后保留,比如说 2 行。最好有一个灵活的窗口,您可以在其中定义检测到的观察前后所需的时间窗口。结果应如下所示:

RES <- data.table(time = c(2, 3, 4, 5, 6, 10, 11, 12, 13, 14), b = c(0, 0, 1, 0, 0, 0, 0, 1, 0, 0))

【问题讨论】:

    标签: r time-series data.table subset


    【解决方案1】:

    这是一个(快速而肮脏的)选项:

    n <- 2L
    DT[{rows <- rep(which(b==1), each = n*2L+1L) + -n:n; fifelse(rows %between% c(1,.N), rows, 0)}]
    
        time b
     1:    2 0
     2:    3 0
     3:    4 1
     4:    5 0
     5:    6 0
     6:   10 0
     7:   11 0
     8:   12 1
     9:   13 0
    10:   14 0
    

    要在单独的 data.frames 中获取结果,您可以使用 lapply():

    lapply(
      DT[b==1, which=TRUE], 
      function(i) DT[{rows <- rep(i, each = n*2L+1L) + -n:n; fifelse(rows %between% c(1,.N), rows, 0)}]
    )
    
    # [[1]]
    #    time b
    # 1:    2 0
    # 2:    3 0
    # 3:    4 1
    # 4:    5 0
    # 5:    6 0
    # 
    # [[2]]
    #    time b
    # 1:   10 0
    # 2:   11 0
    # 3:   12 1
    # 4:   13 0
    # 5:   14 0
    

    【讨论】:

    • 这看起来不错,也很有效。但是最后零在做什么呢?如果我不使用零,有什么区别吗?是否有可能单独保存找到的 1 个案例及其时间窗口,所以在这种情况下会产生 2 个单独的 data.tables?
    • 如果 b=1 接近开始,则 0 处理边缘情况。但是如果 b=1 靠近边缘,也会有边缘情况。
    • 是否可以设置开始和结束索引而不是时间窗口n?例如,如果b = 1 然后在观察之前取 3 行,之后只取 1 行。我已经尝试将 n 拆分为 2 个单独的变量,但出现了一些错误。
    • @Bolle 是的,密钥在-n:n 你可以改为-3:1
    猜你喜欢
    • 2020-06-13
    • 1970-01-01
    • 2021-06-08
    • 1970-01-01
    • 2020-10-25
    • 2023-02-26
    • 2015-05-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多