根据条件在KDB中标记前N天的值?

时间:2019-07-16 09:31:48

标签: kdb

初始表

company time         value  
-------------------------
a       00:00:15.000  100
a       00:00:30.000  100
b       00:01:00.000  100
a       00:01:10.000  100
a       00:01:15.000  100
a       00:01:20.000  300
a       00:01:25.000  100
b       00:01:30.000  400
a       00:01:50.000  100
a       00:02:00.000  100
a       00:00:03.000  200

t = 1小时。

对于每一行,我想回顾t时间。

属于t的条目将形成一个时间窗口。我想得到max(time window) - min (time window) / number of events)

例如,如果现在是12:00,并且总共有五个事件,12:00, 11:50, 11:40, 11:30, 10:30,其中四个事件落在t的窗口中,即12:00, 11:50, 11:40, 11:30 ,结果将为12:00 - 11:30 / 4

此外,该窗口应只考虑具有相同值和公司名称的行。

结果表

company time         value   x
--------------------------------
a       00:00:15.000  100    0 (First event A).
a       00:00:30.000  100    15 (30 - 15 / 2 events).
b       00:01:00.000  100    0 (First event of company B).
a       00:01:10.000  100    55/3 = 18.33 (1:10 - 0:15 / 3 events).
a       00:01:15.000  100    60/4 = 15 (1:15 - 0:15 / 4 events).
a       00:01:20.000  300    0 (Different value).
a       00:01:25.000  100    55/4 = 13.75 (01:25 - 0:30 / 4 events).
b       00:01:30.000  400    0 (Different value and company).
a       00:01:50.000  100    40/4 = 10 (01:50 - 01:10 / 4 events). 
a       00:02:00.000  100    50/5 = 10 (02:00 - 01:10 / 5 events).
a       00:03:00.000  200    0 (Different value).

任何帮助将不胜感激。如果有帮助,我问了一个类似的问题,该问题非常出色:Sum values from the previous N number of days in KDB?

表格查询

([] company:`a`a`b`a`a`a`a`b`a`a`a; time: 00:00:15.000 00:00:30.000 00:01:00.000 00:01:10.000 00:01:15.000 00:01:20.000 00:01:25.000 00:01:30.000 00:01:50.000 00:02:00.000 00:03:00.000; v: 100 100 100 100 100 300 100 400 100 100 200)

2 个答案:

答案 0 :(得分:4)

您可能希望使用以下内容;

q)update x:((time-time[time binr time-01:00:00])%60000)%count each v where each time within/:flip(time-01:00:00;time) by company,v from t
company time         v   x
---------------------------------
a       00:15:00.000 100 0
a       00:30:00.000 100 7.5
b       01:00:00.000 100 0
a       01:10:00.000 100 18.33333
a       01:15:00.000 100 15
a       01:20:00.000 300 0
a       01:25:00.000 100 13.75
b       01:30:00.000 400 0
a       01:50:00.000 100 10
a       02:00:00.000 100 10
a       03:00:00.000 200 0

它使用time binr time-01:00:00来获取每次前1小时的最短时间的索引。

然后(time-time[time binr time-01:00:00])%60000以分钟为单位给出每个时间的各自时间范围(即时间-分钟时间)。

count each v where each time within/:flip(time-01:00:00;time)给出此范围内的行数。

将两者相除并实现by company,v只会将它们全部应用于具有相同companyv值的那些。

希望这会有所帮助。

凯文

答案 1 :(得分:1)

如果您的表按时间排序,则以下解决方案将为您提供所需的结果。如果尚未使用xasc,您还可以按时间排序表格。

我还修改了表格,使时间具有不同的小时值。

 q) t:([] company:`a`a`b`a`a`a`a`b`a`a`a; time: 00:15:00.000 00:30:00.000 01:00:00.000 01:10:00.000 01:15:00.000 01:20:00.000 01:25:00.000 01:30:00.000 01:50:00.000 02:00:00.000 03:00:00.000; v: 100 100 100 100 100 300 100 400 100 100 200)

 q) f:{(`int$x-x i) % 60000*1+til[count x]-i:x binr x-01:00:00}

 q) update res:f time by company,v from t
Output
company time         v   res       
---------------------------------
a       00:15:00.000 100 0       
a       00:30:00.000 100 7.5     
b       01:00:00.000 100 0       
a       01:10:00.000 100 18.33333
a       01:15:00.000 100 15      
a       01:20:00.000 300 0       
a       01:25:00.000 100 13.75   
b       01:30:00.000 400 0       
a       01:50:00.000 100 10      
a       02:00:00.000 100 10      
a       03:00:00.000 200 0 

您可以修改函数f来更改时间窗口值。或更改f接受它作为输入参数。

说明:

我们将公司的时间向量,值传递给函数f。它从每个时间值中减去1小时,然后使用binr从输入时间向量中获取1小时窗口范围内第一次输入的索引。

q) i:x binr x-01:00:00
q) 0 0 0 0 1 2 2

之后,它将使用输出的索引来计算总计数。在这里,我将计数乘以60000,因为时差以毫秒为单位,因为它会将其强制转换为int

q) 60000*1+til[count x]-i
q) 60000 120000 180000 240000 240000 240000 300000

然后,我们最后减去每个值的最小和最大时间,然后将它们除以上述计数。由于时间向量是有序的(升序),因此可以将输入时间向量用作最大值和最小值,它们位于i所指的索引处。

q) (`int$x-x i) % 60000*1+til[count x]-i