kdb+使用vector conditional更新列的行依赖逻辑异常问题咨询
问题根源
你这问题的核心是kdb+的update是向量式批量计算——所有行的计算都是基于原表的初始值,不是逐行更新后的结果。原代码里的prev role始终取的是初始化时全1b的列,根本不会跟着前一行的更新变,所以最后所有role还是全1b。
修正方案
要实现这种依赖上一行结果的逻辑,得用kdb+的迭代函数(比如scan或者over)来逐行处理,下面给两种可行的写法:
方法1:用scan生成role列
用scan来一步步算出每一行的role值,逻辑很简单:
- 第一行保持初始的
1b - 从第二行开始,如果当前
signumcumsum和上一行一样,就沿用前一行的role;不一样就翻转role值
// 先把signumcumsum列提出来 s: t[`signumcumsum] // 用scan迭代计算role数组 role: 1b, {(x; y) -> $[y = x[1]; x[0]; not x[0]]}/[1b; s[1:]; s[0:-1]] // 更新表的role列 t: update role: role from t
方法2:用over逐行更新表
通过over循环逐行修改表,每次都基于上一行的结果更新当前行:
// 从第二行开始循环更新 t: {[t;i] update role: $[t[i;`signumcumsum] = t[i-1;`signumcumsum]; t[i-1;`role]; not t[i-1;`role]] from t where i = i} over[t; 1 til count t]
验证结果
跑修正后的代码,表t的role列就会变成你要的:1b 0b 1b 1b 0b。
额外提醒
- kdb+的向量计算适合不依赖前后行的批量操作,但涉及行和行之间有依赖的逻辑,就得用
scan/over这类迭代函数。 - 优先选
scan的方案,比逐行over性能好很多,数据量大的时候差距更明显。
内容的提问来源于stack exchange,提问作者Lil_Phil
相关产品推荐
相关产品推荐

