我们正在监视 3 个进程 A、B 和 C,它们始终处于 X、Y 或 Z 级别。协议(protocol)会记录进程何时更改级别。
df = read.csv(tc <- textConnection('Time1,Process1,Level1
2013-01-09 18:00:34,A,X
2013-01-09 18:00:34,B,Y
2013-01-09 18:00:34,C,X
2013-01-09 22:00:59,A,Z
2013-01-10 00:10:38,A,X
2013-01-10 18:38:35,B,Z
2013-01-11 05:03:11,A,Z
2013-01-11 11:09:10,C,Y
2013-01-11 12:01:18,A,Off
2013-01-11 12:01:18,B,Off
2013-01-11 12:01:18,C,Off
'),header=TRUE)
close.connection(tc)
df$Time1 = as.POSIXct(df$Time1)
监控于2013-01-09 18:00:34开始,并于2013-01-11 12:01:18关闭。在2013-01-09 18:00:34和2013-01-09 22:00:59之间,进程A处于X级,在2013-01-09 22:00:59和2013-01-10 00:10之间: 38 进程 A 处于 Z 级。
出于图表目的,我们希望将每个午夜每个进程的最后一个和第一级状态插入到协议(protocol)中:
2013-01-09 23:59:59,A,Z
2013-01-10 00:00:00,A,Z
2013-01-10 23:59:59,A,X
2013-01-11 00:00:00,A,X
2013-01-09 23:59:59,B,Y
2013-01-10 00:00:00,B,Y
2013-01-10 23:59:59,B,Z
2013-01-11 00:00:00,B,Z
2013-01-09 23:59:59,C,X
2013-01-10 00:00:00,C,X
2013-01-10 23:59:59,C,X
2013-01-11 00:00:00,C,X
可以假设 23:59:59 到 00:00:00 之间日志中没有事件。最后,协议(protocol)将在插入后按 Time1 排序(我们可以自己计算)。非常感谢任何指导!
最佳答案
(+1) 相当复杂且有趣的任务。我想我已经有了答案。我将尝试在这里解释该方法。我希望这是有道理的。这里有两个棘手的地方。我的解决方案使用 data.table
.
First:
我发现首先构建您需要的输出的前两列更容易。这是在下面所示的代码的第一部分中完成的:
require(data.table)
dates <- unique(as.character(strptime(as.character(df$Time1), "%Y-%m-%d")))
dates <- dates[1:(length(dates)-1)]
dates <- strptime(paste(dates, "23:59:59"), "%Y-%m-%d %H:%M:%S")
dates <- sort(c(dates, dates+1))
Time <- rep(dates, length(levels(df$Process1)))
Process <- rep(levels(df$Process1), each=length(dates))
dt.out <- data.table(Time=as.POSIXct(Time), Process=Process)
# data.table outputs crazy values if not converted using as.POSIXct..?!
通过查看每行代码的作用应该很容易理解。我希望它可以扩展到其他场景。
Second:
第二位同样棘手,但可以使用 data.table
在一行中完成。 。我花了一段时间才弄清楚,但它太棒了!
dt <- data.table(df, key="Process1") # convert input data.frame to data.table
out <- dt.out[, dt[J(Process)]$Level1[max(which(dt[J(Process)]$Time1 < Time))],
by = c("Process", "Time")]
> out
Process Time V1
1: A 2013-01-09 23:59:59 Z
2: A 2013-01-10 00:00:00 Z
3: A 2013-01-10 23:59:59 X
4: A 2013-01-11 00:00:00 X
5: B 2013-01-09 23:59:59 Y
6: B 2013-01-10 00:00:00 Y
7: B 2013-01-10 23:59:59 Z
8: B 2013-01-11 00:00:00 Z
9: C 2013-01-09 23:59:59 X
10: C 2013-01-10 00:00:00 X
11: C 2013-01-10 23:59:59 X
12: C 2013-01-11 00:00:00 X
让我将这两行分成几部分来解释发生了什么。
在第一行,我们set key
对于 dt
如Process1
。这允许 VERY fast
按列过滤数据Process1
。即dt["A"]
相当于 df[df$Process1 == "A"]
,但前者的速度非常快。
在第二行中,发生了很多事情。我们已经创建了dt.out
需要输出的前两列。剩下的就是第三列。查看该行的最后一部分 by = c("Process", "Time")
。在这里,我们 split data.table dt.out
通过这两个变量。并到每一个分割data.table
,我们申请dt[J(Process)]$Level1[max(which(dt[J(Process)]$Time1 < Time))]
基本上挑选出 maximum index
从所有当前Time1
< Time
的值来自data.table
过滤条件 Process
并使用这个最大索引返回相应的 Levels1
值。
希望这有帮助。
关于r - 将午夜条目插入日志,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14336868/