【问题标题】:Marking values from the previous N number of days in KDB based on criteria?根据标准在KDB中标记前N天的值?
【发布时间】:2019-11-25 00:12:57
【问题描述】:

初始表格

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)

【问题讨论】:

    标签: kdb


    【解决方案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
    

    【讨论】:

      【解决方案2】:

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

      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 值的那些。

      希望这会有所帮助。

      凯文

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多