R:根据事件时间传播时间序列数据

问题描述

我有一个很大的时间序列数据集,当前正在对数据进行迭代,以将时间序列数据更改为按时间间隔划分的事件。我正在寻找比迭代更流畅的方法,因为随着我的数据量的增加,它变得相当慢。我的起始数据帧看起来类似于以下简单数据帧:

structure(list(Name = structure(c(1L,1L,2L,3L,3L),.Label = c("a","b","c"),class = "factor"),datetime = structure(c(1597203000,1597201200,1597199400,1597186800,1597185000,1597183200,1597197600,1597195800,1597194000,1597181400,1597179600,1597177800,1597192200,1597190400,1597188600,1597176000,1597174200,1597172400),class = c("POSIXct","POSIXt"),tzone = ""),percent = c(0,2,1,3,4,5,0)),class = "data.frame",row.names = c(NA,-18L))

数据是半小时的,所以如果一个Name变量具有两个连续的半小时的datetime值,我认为它是事件的一部分。我还要宽大处理,因此,如果数据没有显示连续的半小时值,但是有连续的小时值,那也将起作用。因此,目标是返回看起来像这样的数据框:

structure(list(Name = structure(c(1L,startdate = structure(c(1597203000,1597176000),enddate = structure(c(1597199400,tzone = "")),-6L))

在此先感谢您提供任何令人眼花solutions乱的解决方案!

编辑:日期时间值不一定按顺序排在列表中。

解决方法

我不确定您的循环是什么样子,但是如果您使用以下代码,则可以推迟循环,直到以后至少可以使事情运行得更快一点。

df= with(df,df[order(Name,datetime),]) %>% 
         mutate(dftime = difftime(lead(datetime),datetime,units = "mins")) %>%
         mutate(eventnum = 0)

i = 1
j = 1
for(i in 1:length(df$eventnum)){
  if(df$dftime[i] <= 60){          # accounting for your consecutive hours comment
    df$eventnum[i] = j
  } else{df$eventnum[i] = j
         j = j + 1}
  i = i + 1
}

然后,您可以使用类似akrun的答案的汇总设置,如下所示:

df_lengths = df %>% group_by(eventnum,Name) %>% 
                     summarise(startdate = first(datetime),enddate = last(datetime)) %>% 
                     ungroup %>% select(-eventnum)

但这只是一个更好的答案,假设您在数据组织中进行了较早的循环,例如,如果您循环进行了时差计算和时间间隔检查,那么

,

在“名称”列上使用rleid(来自data.table)创建分组变量,然后通过返回summarise和{{ 1}}元素分为两列

first