3

我有事件日志,其中包含:开始时间、结束时间、类别 ID 和计数。它们涵盖了几个月。

我想随着时间的推移聚合它们,以便能够在给定的一天、一周、一个月内追踪直方图。所以我认为最好的方法是把时间段放在桶里。我觉得5分钟就好了。

例如,如果一个事件在下午 1.01 开始并在下午 1.07 结束,我想为其获取 2 条记录,因为它涵盖 2 个 5 分钟的时段(0-5 和 5-10)并复制其余的原始数据这些新记录(类别和计数)

如果我的输入日志 (x) 是这样的:

start / end / catid / count     
2012-11-17 15:05:02.0,  2012-11-17 15:12:52.0,  1, 2    
2012-11-17 15:07:13.0,  2012-11-17 15:17:47.0,  2, 10   
2012-11-17 15:11:00.0,  2012-11-17 15:12:33.0,  3, 5    
2012-11-17 15:12:01.0,  2012-11-17 15:20:00.0,  4, 1    

我正在尝试以这种方式在 5 分钟 (b) 内获取输出:

start / catid / count   
2012-11-17 15:05:00.0   1, 2    
2012-11-17 15:10:00.0   1, 2

2012-11-17 15:05:00.0   2, 10   
2012-11-17 15:10:00.0   2, 10
2012-11-17 15:15:00.0   2, 10

2012-11-17 15:10:00.0   3, 5

2012-11-17 15:10:00.0   4, 1
2012-11-17 15:15:00.0   4, 1

然后我可以轻松地将新数据框 (b) 聚合到我想要的时间段(小时、天、周、月)的类别 ID 上

我从 R 开始,我发现了很多关于如何存储时间值而不是时间段的解释。我看过 zoo 和 xts,但我找不到该怎么做。

希望这对你们中的一些人有意义。

编辑:

我稍微修改了 Ram 的建议,以使用四舍五入的结束时间而不是原始结束时间来正确计算块。(谢谢拉姆!)

mnslot=15 # size of the buckets/slot in minutes

#Round down the minutes of starttime to a mutliple of mnslot
st.str <- strptime(st, "%Y-%m-%d %H:%M:%S")
min_st <- as.numeric(format(st.str, "%M"))
roundedmins <- floor(min_st/mnslot) * mnslot
st.base <- strptime(st, "%Y-%m-%d %H")
rounded_start <- st.base + (roundedmins * 60)

#Round down the minutes of the endtime to a multiple of mnslot.
en.str <- strptime(en, "%Y-%m-%d %H:%M:%S")
min_en <- as.numeric(format(en.str, "%M"))
roundedmins <- floor(min_en/mnslot) * mnslot
en.base <- strptime(en, "%Y-%m-%d %H")
rounded_end<- en.base + (roundedmins * 60)

# calculate the number of blocks based on the rounded minutes of start and end
numblocks<- as.numeric(floor((rounded_end-rounded_start)/mnslot/60)+1)
# differenced of POSIXct values is in minutes
# but difference of POSIXlt seems to be in seconds , so have to divide by 60 as well

#Create REPLICATED Rows, depending on the size of the interval
replicated_cat = NULL
replicated_count = NULL
replicated_start =     NULL
for (n in 1:length(numblocks)){
  for (newrow in  1:numblocks[n]){
    replicated_start =   c(replicated_start, df$rounded_start[n]+(newrow-1)*300   )  
    replicated_cat = c(replicated_cat,    df$catid[n]) 
    replicated_count = c(replicated_count, df$count[n]) 
  }
}

#Change to readable format
POSIXT <- unix2POSIXct(replicated_start)

newdf <- data.frame(POSIXT, replicated_cat, replicated_count)
names(newdf) <- c("start", "CatId", "Count")
newdf

这会产生所需的输出。虽然有点慢:p

4

2 回答 2

2

这是一个完整的工作版本。它涉及您所追求的逐步数据操作。

#storing the original data as a csv
df <- read.csv("tsdata.csv")
st<-as.POSIXlt(df$start)
en<-as.POSIXlt(df$end)

#a utility function to convert formats
unix2POSIXct  <-  function (time)   structure(time, class = c("POSIXt", "POSIXct") )

#For each row, determine how many replications are needed
numdups <- as.numeric(floor((en-st)/5)+1)

st.str <- strptime(st, "%Y-%m-%d %H:%M:%S")
min_st <- as.numeric(format(st.str, "%M"))

#Round down the minutes of start to 5 minute starts. 0,5,10 etc...
roundedmins <- floor(min_st/5) * 5
st.base <- strptime(st, "%Y-%m-%d %H")
df$rounded_start <- st.base + (roundedmins * 60)


#Create REPLICATED Rows, depending on the size of the interval
replicated_cat = NULL
replicated_count = NULL
replicated_start =     NULL
for (n in 1:length(numdups)){
  for (newrow in  1:numdups[n]){
    replicated_start =   c(replicated_start, df$rounded_start[n]+(newrow-1)*300   )  
    replicated_cat = c(replicated_cat,    df$catid[n]) 
    replicated_count = c(replicated_count, df$count[n]) 
  }
}

#Change to readable format
POSIXT <- unix2POSIXct(replicated_start)

newdf <- data.frame(POSIXT, replicated_cat, replicated_count)
names(newdf) <- c("start", "CatId", "Count")
newdf

产生:

                start CatId Count
1 2012-11-17 15:05:00     1     2
2 2012-11-17 15:10:00     1     2
3 2012-11-17 15:05:00     2    10
4 2012-11-17 15:10:00     2    10
5 2012-11-17 15:15:00     2    10
6 2012-11-17 15:10:00     3     5
7 2012-11-17 15:10:00     4     1
8 2012-11-17 15:15:00     4     1
于 2013-01-18T01:42:15.267 回答
0

这不是一件容易的事......我也错过了整个问题的结构,所以我希望如果我限制自己概述基本方法是可以的,如果事情不清楚,你可以回来找我。首先(如果我是你)我会安装 ' lubridate ' 包,这使得玩弄日期/时间变得容易得多。然后也许尝试这样的事情:

z <- strptime("17/11/12 15:05:00.0", "%d/%m/%y %H:%M:%OS") 

这将定义您的起始时间点,如果应该由第一个 logs(x) 时间定义,那么有可用的分钟命令,例如

z <- strptime("17/11/12 15:05:02.0", "%d/%m/%y %H:%M:%OS")
minute(z)<-5;second(z)<-0.0 #I guess, you get the concept 

然后产生一个5分钟间隔的序列

z5s<-z+minutes(seq(0,100,5))

这将产生一个 20、5 分钟时间间隔的序列,在这里我不知道整个事情应该有多灵活。

最后,您可以使用例如模运算

z2<-z+minutes(2) 

z2 应该是结束时间,我只是在这里“手动”添加了 2 分钟来说明这个概念

(as.integer(z2-z))%%5 > 5 
FALSE

或者,如果您想查看仅涵盖了多少 5 分钟跨度, (as.integer(z2-z))%%5 或者您希望在 z5s POSIXlt 间隔中匹配/分配日志时间的任何其他功能。

希望这会有所帮助,即给你一些方向。

于 2013-01-17T22:50:07.853 回答