如何在R中反聚合时间间隔数据?

如何在R中反聚合时间间隔数据?,r,time,time-series,R,Time,Time Series,我有开始和停止时间形式的数据(分:秒格式)。一个简单的例子可能是灯光打开的时间戳,以及随后灯光关闭的时间戳 例如: Start Stop 00:03.1 00:40.9 00:55.0 01:38.2 01:40.0 02:01.1 我想重新排列数据,这样我最终可以用R中的整分钟间隔箱来查看它 选项1:每十分之一秒将数据转换为二进制列表,然后按时间戳聚合数据 Time.in.sec Yes.or.No 0.0 N 0.1 N ...

我有开始和停止时间形式的数据(分:秒格式)。一个简单的例子可能是灯光打开的时间戳,以及随后灯光关闭的时间戳

例如:

Start    Stop   
00:03.1  00:40.9
00:55.0  01:38.2
01:40.0  02:01.1
我想重新排列数据,这样我最终可以用R中的整分钟间隔箱来查看它

选项1:每十分之一秒将数据转换为二进制列表,然后按时间戳聚合数据

Time.in.sec   Yes.or.No
0.0           N
0.1           N
...           ...
3.0           N
3.1           Y
3.2           Y
...           ...
40.8          Y
40.9          N
...           ...
选项2:按分钟标记拆分时间间隔,并使用某种逻辑规则聚合每分钟的总时间(从时间=0:00.0开始)

Start        Stop
00:03.10     00:40.90
00:55.00     00:59.99
01:00.00     01:38.20
01:40.00     01:59.99
02:00.00     02:01.10
我曾尝试研究过lubridate函数(即,将每个范围划分为一个区间类)和
cut()
,但我似乎不知道如何使这两种想法都起作用。我也不清楚像zoo这样的软件包是否适合这样做;老实说,我对日期/时间格式和时间序列几乎没有经验

关于Stackoverflow的其他问题似乎是解决从原始时间戳(例如,和)生成箱子的问题,但我基本上想做相反的事情


编辑1:这里是示例数据的CSV格式,一直到第6分钟

Start, Stop 
00:03.1, 00:40.9
00:55.0, 01:38.2
01:40.0, 02:01.1
03:03.1, 04:30.3
04:50.0, 05:01.5
05:08.7, 05:22.0
05:40.1, 05:47.9

编辑2:我的最终目标是以一种格式提供数据,我可以使用这种格式将观察值分为标准化的时间段(1分钟、2分钟等),以获得数据为“是”时的逐分钟百分比。基本上,我想按分钟获得状态分布的摘要,因为数据是二进制的,所以我可以通过查看“是”状态来实现这一点

在前3分钟(从00:00.0到03:00.0),输出如下:

Minute  time.yes.sec  perc.time.yes
1       42.8          71.33
2       58.2          96.98
3       1.1           1.83

# *NOTE: Here, Minute 1 = [0, 60), Minute 2 = [60, 120), etc.; I'm not opposed 
# to the reverse definitions though (Minute 1 = (0, 60], etc.).  

我也可以将数据视为累积分布图,每个连续的时间点更新“total time yes”的值。但是,如果我能够以选项1的格式获取数据,我将可以灵活地以任何方式查看数据。

在编辑之前,我使用您的原始数据执行了以下操作:

Start    Stop   
00:03.1  00:40.9
00:55.0  01:38.2
01:40.0  02:01.1

agg <- read.table(con<-file("clipboard"), header=T)
为了验证它是否有效,让我们看看
table()


从注释中的“我的版本”轻松编辑的选项:

library(tidyverse)
library(lubridate)

df %>% mutate_all(funs(period_to_seconds(ms(.)))) %>%    # convert each time to seconds
    rowwise() %>%    # evaluate the following row-by-row
    # make a sequence from Start to Stop by 0.1, wrapped in a list
    mutate(instant = list(seq(Start, Stop, by = 0.1))) %>% 
    unnest() %>%    # expand list column
    # make a factor, cutting instants into 60 second bins
    mutate(minute = cut(instant, breaks = (0:6) * 60, labels = 1:6)) %>% 
    group_by(minute) %>%    # evaluate the following grouped by new factor column
    # for each group, count the rows, subtracting 1 for starting instants, and
    # dividing by 10 to convert from tenths of seconds to secontds
    summarise(elapsed = (n() - n_distinct(Start)) / 10,
              pct_elapsed = elapsed / 60 * 100)    # convert to percent

## # A tibble: 6 × 3
##   minute elapsed pct_elapsed
##   <fctr>   <dbl>       <dbl>
## 1      1    42.8   71.333333
## 2      2    58.1   96.833333
## 3      3     1.0    1.666667
## 4      4    56.9   94.833333
## 5      5    40.2   67.000000
## 6      6    22.5   37.500000
库(tidyverse)
图书馆(lubridate)
df%>%突变所有(funs(周期到秒(毫秒))%>%将每次转换为秒
rowwise()%>%#逐行计算以下内容
#按0.1从开始到停止制作一个序列,包装在一个列表中
突变(瞬间=列表(顺序(开始、停止、按=0.1))%>%
unnest()%>%#展开列表列
#制作一个因子,将瞬间切割成60秒的存储箱
突变(分钟=切割(瞬间,断裂=(0:6)*60,标签=1:6))%>%
按(分钟)分组%>%#按新系数列分组评估以下内容
#对于每个组,计算行数,开始瞬间减去1,然后
#除以10将十分之一秒转换为秒
总结(已用=(n()-n_distinct(Start))/10,
pct_经过=经过/60*100)#转换为百分比
###A tible:6×3
##已用分钟pct\U已用分钟
##             
## 1      1    42.8   71.333333
## 2      2    58.1   96.833333
## 3      3     1.0    1.666667
## 4      4    56.9   94.833333
## 5      5    40.2   67.000000
## 6      6    22.5   37.500000
注意:计算起始瞬间的修正是不完美的,因为它将减去每个起始瞬间,即使它是前一分钟序列的延续。如果精度很重要的话,可以更彻底地计算

更精确但有点困难的路线是在每分钟的转弯处增加停车和起步:

df %>% mutate_all(funs(period_to_seconds(ms(.)))) %>%    # convert to seconds
    gather(var, val) %>%    # gather to long form
    # construct and rbind data.frame of breaks at minute changes
    bind_rows(expand.grid(var = c('Start', 'Stop'), 
                          val = seq(60, by = 60, length.out = floor(max(.$val)/60)))) %>% 
    arrange(val, desc(var)) %>%    # sort
    mutate(index = rep(seq(n()/2), each = 2)) %>%    # make indices for spreading
    spread(var, val) %>%    # spread back to wide form
    mutate(elapsed = Stop - Start) %>%    # calculate elapsed time for each row
    # add and group by factor of which minute each falls in
    group_by(minute = cut(Stop, seq(0, by = 60, length.out = ceiling(max(Stop) / 60 + 1)), 
                        labels = 1:6)) %>% 
    summarise(elapsed = sum(elapsed),    # calculate summaries
              pct_elapsed = elapsed / 60 * 100)

## # A tibble: 6 × 3
##   minute elapsed pct_elapsed
##   <fctr>   <dbl>       <dbl>
## 1      1    42.8   71.333333
## 2      2    58.2   97.000000
## 3      3     1.1    1.833333
## 4      4    56.9   94.833333
## 5      5    40.3   67.166667
## 6      6    22.6   37.666667
df%>%mutate\u all(funs(周期到秒(毫秒)))%>%convert到秒
聚集(var,val)%>%#聚集为长形式
#构建并重新绑定数据。微小变化时的中断帧
绑定行(expand.grid(var=c('Start','Stop'),
val=序号(60,by=60,length.out=floor(max(.$val)/60)))%>%
排列(val,描述(var))%>%#排序
变异(index=rep(seq(n()/2),each=2))%>%#为传播制作索引
价差(var,val)%>%#价差回到宽幅形式
mutate(经过=停止-启动)%>%#计算每行经过的时间
#按每分钟的时间因素进行添加和分组
分组依据(分钟=切割(停止,序号(0,by=60,长度=天花板(最大停止)/60+1)),
标签=1:6))%>%
总结(已用=总结(已用),#计算总结
pct_经过=经过/60*100)
###A tible:6×3
##已用分钟pct\U已用分钟
##             
## 1      1    42.8   71.333333
## 2      2    58.2   97.000000
## 3      3     1.1    1.833333
## 4      4    56.9   94.833333
## 5      5    40.3   67.166667
## 6      6    22.6   37.666667

我刚才添加的CSV格式的数据摘录够了吗?这次没问题,因为我继续使用了原始数据,您必须编写一个答案。如果你有任何问题,请告诉我。干杯你为什么要这样做?你想解决的更大的问题是什么?在整个分秒表中,你感兴趣的是什么?转换次数?正转换次数(从关闭到打开)?最短间隔时间?总间隔时间?重新排列数据的“最佳”方式取决于您试图用它做什么。不是100%取决于您想要什么,而是有趣的:
library(tidyverse);df%%>%mutate\u all(funs(as.numeric(lubridate::ms()))%%>%rowwise()%%>%mutate(instant=list(seq(Start,Stop,by=0.1)))%%>%unnest()%%>%mutate(minute=cut(instant,(0:6)*60))%%>%group\u by(minutes)%%>%summary(appeased=(n()-1)/10)
我认为这正是我想要的。但是,观察期实际上从0:00.0开始,持续整分钟。这不一定由第一个时间戳或最后一个时间戳反映
   N    Y 
 201 1019
option1$minute <- ifelse(option1$time < lubridate::seconds(60), 0, 1)
option1$minute[option1$time > lubridate::seconds(120)] <- 2

table(option1$flag, option1$minute)
    0   1   2
N 172  19  10
Y 427 582  10
prop.table(table(option1$flag, option1$minute),2)
             0          1          2
  N 0.28714524 0.03161398 0.50000000
  Y 0.71285476 0.96838602 0.50000000
library(tidyverse)
library(lubridate)

df %>% mutate_all(funs(period_to_seconds(ms(.)))) %>%    # convert each time to seconds
    rowwise() %>%    # evaluate the following row-by-row
    # make a sequence from Start to Stop by 0.1, wrapped in a list
    mutate(instant = list(seq(Start, Stop, by = 0.1))) %>% 
    unnest() %>%    # expand list column
    # make a factor, cutting instants into 60 second bins
    mutate(minute = cut(instant, breaks = (0:6) * 60, labels = 1:6)) %>% 
    group_by(minute) %>%    # evaluate the following grouped by new factor column
    # for each group, count the rows, subtracting 1 for starting instants, and
    # dividing by 10 to convert from tenths of seconds to secontds
    summarise(elapsed = (n() - n_distinct(Start)) / 10,
              pct_elapsed = elapsed / 60 * 100)    # convert to percent

## # A tibble: 6 × 3
##   minute elapsed pct_elapsed
##   <fctr>   <dbl>       <dbl>
## 1      1    42.8   71.333333
## 2      2    58.1   96.833333
## 3      3     1.0    1.666667
## 4      4    56.9   94.833333
## 5      5    40.2   67.000000
## 6      6    22.5   37.500000
df %>% mutate_all(funs(period_to_seconds(ms(.)))) %>%    # convert to seconds
    gather(var, val) %>%    # gather to long form
    # construct and rbind data.frame of breaks at minute changes
    bind_rows(expand.grid(var = c('Start', 'Stop'), 
                          val = seq(60, by = 60, length.out = floor(max(.$val)/60)))) %>% 
    arrange(val, desc(var)) %>%    # sort
    mutate(index = rep(seq(n()/2), each = 2)) %>%    # make indices for spreading
    spread(var, val) %>%    # spread back to wide form
    mutate(elapsed = Stop - Start) %>%    # calculate elapsed time for each row
    # add and group by factor of which minute each falls in
    group_by(minute = cut(Stop, seq(0, by = 60, length.out = ceiling(max(Stop) / 60 + 1)), 
                        labels = 1:6)) %>% 
    summarise(elapsed = sum(elapsed),    # calculate summaries
              pct_elapsed = elapsed / 60 * 100)

## # A tibble: 6 × 3
##   minute elapsed pct_elapsed
##   <fctr>   <dbl>       <dbl>
## 1      1    42.8   71.333333
## 2      2    58.2   97.000000
## 3      3     1.1    1.833333
## 4      4    56.9   94.833333
## 5      5    40.3   67.166667
## 6      6    22.6   37.666667