KDB-市场数据表中的折叠列

KDB-市场数据表中的折叠列,kdb,Kdb,我有一个包含订购价格和数量数据的市场数据表,用于一系列市场供应商和符号,例如 b:([]symbol:();provider:();px1:();px2:();px3:();qty1:();qty2:();qty3:()) 其中,px1在数量qty1的账面价值最高,px2次优价格等。然后,样本数据可能是 `EURUSD;`EBS;1.1;1.2;1.3;1000000;2000000;4000000 我想将px[n]和qty[n]列折叠成单个列,格式如下 rb:([]symbol:();pr

我有一个包含订购价格和数量数据的市场数据表,用于一系列市场供应商和符号,例如

b:([]symbol:();provider:();px1:();px2:();px3:();qty1:();qty2:();qty3:())
其中,px1在数量qty1的账面价值最高,px2次优价格等。然后,样本数据可能是

`EURUSD;`EBS;1.1;1.2;1.3;1000000;2000000;4000000
我想将px[n]和qty[n]列折叠成单个列,格式如下

rb:([]symbol:();provider:();px:();qty:())
然后读取样本数据

EURUSD, EBS, 1.1, 1000000
EURUSD, EBS, 1.2, 2000000
EURUSD, EBS, 1.3, 4000000
实现这一目标的最佳方法是什么?作为一个新手,我一直在思考如何使用字典

q)px:book `px1`px2`px3
q)qty:book `qty1`qty2`qty3
q)d:`px`qty!(px;qty)
q)flip d
px  qty
-----------
1.1 1000000
1.2 2000000
1.3 4000000

。。。但是我相信还有更好的方法。

如果不能重新构造原始表定义,可以使用以下方法

q)b
symbol provider px1 px2 px3 qty1    qty2    qty3
---------------------------------------------------
EURUSD EBS      1.1 1.2 1.3 1000000 2000000 4000000
EURUSD ECS      1.1 1.2 1.3 1000000 2000000 4000000
q)ungroup {rm _x,'flip enlist[y]!enlist flip x rm:cols[x]where cols[x] like string[y],"*" }/[b;\`px\`qty]

symbol provider px  qty
---------------------------
EURUSD EBS      1.1 1000000
EURUSD EBS      1.2 2000000
EURUSD EBS      1.3 4000000
EURUSD ECS      1.1 1000000
EURUSD ECS      1.2 2000000
EURUSD ECS      1.3 4000000

Connor的答案可能是最规范的,但是
ungroup
仍然是表上的迭代,根据定义,它比直接列表操作慢。在许多情况下,迭代是不可避免的,但在这里,您可以直接从输入表的列表构建结果表,如下所示:

flip `symbol`provider`px`qty!(
                (3*cb)#b`symbol; 
                (3*cb:count[b])#b`provider; 
                (b[`px1],b[`px2],b`px3); 
                (b[`qty1],b[`qty2],b`qty3)) 
这里,结果表的前两列
symbol
provider
重复三次,
px
列是
px1
px2
px3
的串联,与
quantity
相同

当然,这种方法不会产生与
ungroup
相同的行顺序,但有趣的是,它的运行速度快了约40倍(对于1m行,大约40ms,ungroup大约1600ms)

如果需要保留记录的顺序,我们可以对其进行编号,然后进行排序:

`a`b _ `a`b xasc flip `a`b`symbol`provider`px`qty!(
    (3*cb)#til[cb]; 
    raze cb#/:(til 3); 
    (3*cb)#b`symbol; 
    (3*cb:count[b])#b`provider; 
    (b[`px1],b[`px2],b`px3); 
    (b[`qty1],b[`qty2],b`qty3)) 

这里的
a
b
列提供了用于排序的索引,稍后将从结果中删除。此方法在1m行上的运行时间约为180ms,因此仍然比ungroup方法快9倍。当然,排序的存在会使该算法比线性算法更差,但它仍有很大的余量,可以更快地达到大约100万行(不幸的是,现在无法测试)

使用
flip
ungroup
完成排序的一种方法:

q)b:([]symbol:`eurjpy`eurusd;provider:2#`ebs;px1:10+2?.1;px2:11+2?.1;px3:12+2?.1;qty1:100+2?10;qty2:100+2?10;qty3:100+2?10)

symbol provider px1      px2      px3      qty1 qty2 qty3
---------------------------------------------------------
eurjpy ebs      10.05641 11.04464 12.02366 109  103  107
eurusd ebs      10.01925 11.08214 12.07947 104  104  102

q)ungroup select symbol, provider, px:flip (px1;px2;px3) , qty:flip (qty1;qty2;qty3)  from b
symbol provider px       qty
----------------------------
eurjpy ebs      10.05641 109
eurjpy ebs      11.04464 103
eurjpy ebs      12.02366 107
eurusd ebs      10.01925 104
eurusd ebs      11.08214 104
eurusd ebs      12.07947 102

您可以使用
raze flip b[`px1`px2`px3]
来维护价格和数量列的顺序,并使用
(`symbol`provider#b)在count[x]#3