在某些条件下将数据分组到kdb中

问题描述 投票:4回答:2

我有一个名为raw的主数据框,如下所示:

tab:([]date:2018.02.05 2018.02.05 2018.02.06 2018.02.06;time:01:30:25.000 02:30:45.000 04:15:15.000 02:15:15.000;vol:50 55 64 12; name:`A`B`B`A)

date           time         vol     name   
2018.02.05     1:30:25      50       A
2018.02.05     2:30:45      55       B
2018.02.06     4:15:15      64       B
2018.02.06     2:15:15      12       A

我需要根据以下条件创建一个新表:

在两个特定日期之间,我需要在两小时内找到名称B的累积vol为100的时间。

我认为应该运作的逻辑:按时间的升序排列数据。在(time [i]:time [i] + 2hrs)内添加所有vol by name =`B的时间。如果暨vol> 100,则返回时间间隔和相应的日期。继续i +1。我是kdb的新手,所以我在实施它时遇到了困难。

样本输出:

time1          time2         date1         date2
1:30:00        3:30:00       2018.02.05    2018.02.05
23:00:00       1:00:00       2018.02.05    2018.02.06

任何领导对此表示赞赏。谢谢

kdb
2个回答
1
投票

我相信使用aj可以解决您的问题

最初正如您所指出的那样,表格应按时间排序

`time xasc `tab;

然后,应使用总和创建卷的累积总和

tab:update cumvol:sums vol by name from tab

然后使用aj - 获取每次不在2小时内的卷的累积总和。

aj[`name`time;tab;select time:time+02:00,name,cumvol2:cumvol from tab]

然后我们可以做cumvol - cumvol2来获得每2小时的总体积

tab:select time, name, runningvol:cumvol-0^cumvol2 from 
aj[`name`time;tab;select time:time+02:00,name,cumvol2:cumvol from tab]

然后一个简单的select语句可以得到cumvol大于100的时间

select time,time+02:00 from tab where runningvol>100

可以添加到其中的改进是在aj中的第二个表上添加分组属性。对此的另一个改进是将日期和时间格式化为单个时间戳或日期时间。

有关函数aj和sums的更多信息可以在这里找到:

http://code.kx.com/q/ref/joins/#aj-aj0-asof-join

http://code.kx.com/q/ref/arith-integer/#sums


1
投票

您也可以使用window join wj1。给出示例表:

t:`time xasc ([]time:(1000?2018.02.05 2018.02.06)+1000?24:00:00;sym:1000?`A`B`C;vol:1000?10);

以下函数在相对于时间戳的2小时窗口中聚合vol,并传递表t,开始日期s,结束日期e和名称n

fw:{[t;s;e;n]
  r:@[;`sym;`p#]`sym`time xasc select from t where time.date within(s;e),sym=n;
  :select from wj1[r[`time]-/:02:00 00:00;`time;r;(r;(sum;`vol))] where vol>100;
 };

运行名称/ sym B给出:

q)fw[t;2018.02.05;2018.02.06;`B]
time                          sym vol
-------------------------------------
2018.02.05D18:12:39.000000000 B   104
2018.02.05D18:35:47.000000000 B   101
2018.02.05D18:40:17.000000000 B   102
...

它也可以修改为所有名称/ syms的所有结果:

fw1:{[t;s;e]
  r:@[;`sym;`p#]`sym`time xasc select from t where time.date within(s;e);
  :select from wj1[r[`time]-/:02:00 00:00;`sym`time;r;(r;(sum;`vol))] where vol>100;
 };

这次没有名字/ sym运行:

q)fw1[t;2018.02.05;2018.02.06]
time                          sym vol
-------------------------------------
2018.02.05D02:01:36.000000000 A   106
2018.02.05D02:52:23.000000000 A   103
2018.02.05D03:06:51.000000000 A   105
...

虽然这种方法的效率低于使用aj,但它仍然说明了如何通过窗口连接实现这一点。

© www.soinside.com 2019 - 2024. All rights reserved.