【问题标题】:data.table: calculate statistics of rows time within time moving windowdata.table:计算时间移动​​窗口内的行时间统计
【发布时间】:2018-09-11 22:34:03
【问题描述】:
library(data.table)
library(lubridate)
df <- data.table(col1 = c('A', 'A', 'A', 'B', 'B', 'B'), col2 = c("2015-03-06 01:37:57", "2015-03-06 01:39:57", "2015-03-06 01:45:28", "2015-03-06 02:31:44", "2015-03-06 03:55:45", "2015-03-06 04:01:40"))

对于每一行,我想计算具有相同 'col1' 值的行的时间标准偏差(col2)和该行时间之前过去 10 分钟窗口内的时间(包括)

我使用下一种方法:

df$col2 <- as_datetime(df$col2)
gap <- 10L
df[, feat1 := .SD[.(col1 = col1, t1 = col2 - gap * 60L, t2 = col2)
                   , on = .(col1, col2 >= t1, col2 <= t2)
                   , .(sd_time = sd(as.numeric(col2))), by = .EACHI]$sd_time][]

结果我只看到 NA 值而不是几秒钟内的值

例如对于第三行(col="A" and col2 = "2015-03-06 01:45:28") 我已经通过下一种方式手动计算:

v <- c("2015-03-06 01:37:57", "2015-03-06 01:39:57", "2015-03-06 01:45:28")
v <- as_datetime(v)
sd(v) = 233.5815

【问题讨论】:

  • sd 应用于长度为 1 的向量是 NA 您的粒度使得所有日期向量的长度为 1。
  • Max Ft,在很多情况下你是对的,但是对于 col1='A' 和 col2 = "2015-03-06 01:45:28" 你错了,对于这一行也是 NA,所以我认为需要修改data.table请求
  • 基于 my answer 到您之前的问题,您可以这样做:df[.(col1 = col1, t1 = col2 - gap * 60L, t2 = col2), on = .(col1, col2 &gt;= t1, col2 &lt;= t2)][, .(feat1 = sd(as.numeric(col2))), .(col1, col2.1)],但这不会给您带来有意义的答案,因为它要么返回 NA,因为您无法计算 @ 987654329@ 一个数字(如@MaxFt 所说)或0 因为当您有多个值时,它们将是相同的。
  • @Jaap,你错了 - 请分析 col1='A' 和 col2 = "2015-03-06 01:45:28" 的行的手动计算:v

标签: r data.table


【解决方案1】:

data.table解决方案:

df[,col3:=as.numeric(col2)]
df[, feat1 := {
  d <- data$col3 - col3
  sd(data$col3[col1 == data$col1 & d <= 0 & d >= -gap * 60L])
},
by = list(col3, col1)]

mapply遍历col1、col2的所有组合的另一种方法:

df[,col3:=as.numeric(col2)]

df[, feat1:=mapply(Date = col3,ID = col1, function(Date, ID) {
  DateVect=df[col1 == ID,col3]
  d <- DateVect - Date
  sd(DateVect[d <= 0 & d >= -gap * 60L])})][]

【讨论】:

    【解决方案2】:

    两种可选的data.table 解决方案(my previous answer 的变体):

    # option 1
    df[.(col1 = col1, t1 = col2, t2 = col2 + gap * 60L)
       , on = .(col1, col2 >= t1, col2 <= t2)
       , .(col1, col2 = x.col2, times = as.numeric(t1))
       ][, .(feat1 = sd(times))
         , by = .(col1, col2)]
    
    # option 2
    df[, feat1 := .SD[.(col1 = col1, t1 = col2, t2 = col2 + gap * 60L)
                      , on = .(col1, col2 >= t1, col2 <= t2)
                      , .(col1, col2 = x.col2, times = as.numeric(t1))
                      ][, .(sd_times = sd(times))
                        , by = .(col1, col2)]$sd_times][]
    

    两者都给出:

       col1                col2     feat1
    1:    A 2015-03-06 00:37:57        NA
    2:    A 2015-03-06 00:39:57  84.85281
    3:    A 2015-03-06 00:45:28 233.58153
    4:    B 2015-03-06 01:31:44        NA
    5:    B 2015-03-06 02:55:45        NA
    6:    B 2015-03-06 03:01:40 251.02291
    

    【讨论】:

    • 您的解决方案看起来正确-但结果非常奇怪-我询问了当前行的过去时间窗口-不是下一个作为您的输出:您不正确,因为第三行的feat1 = 233.5815-不是您的第一个,对于六排也是feat1 = 251.0229 - 而不是像你这样的五排。请更正您的 data.table.query。
    • 简而言之,你的查询在前 10 分钟看起来像窗口,但输出在未来 10 分钟内给出了窗口的偏差,这对我来说很奇怪
    • @evgeniiershenko 很抱歉造成混乱。我已经更新了代码。 HTH
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-29
    • 2021-11-19
    • 1970-01-01
    • 1970-01-01
    • 2019-09-07
    • 2020-11-18
    相关资源
    最近更新 更多