如何解决KDB-时间函数结果成为后续行中函数的输入
我一直在与KDB一起从代表模型的细分功能的一组输入中创建时间数据。我面临的挑战是,对于一个特定的ID,有多个段,其中第一个段的时间结果的最后一个值成为下一个段的输入(但不总是)。
//Create sample table
t:([id:`AAA`AAA`AAA`BBB`CCC`CCC;seg:1 2 3 1 1 2];aa: 1500 0n 0n 40 900 0N;bb:150 200 30 40 10 15;cc: .40 .25 .35 .5 .35 .45; Fname:`Fx`Fy`Fy`Fy`Fz`Fz);
下面的简单虚拟函数返回5个数据周期,但实际上每个函数可以返回数千个数据点
//Dummy functions to generate temporal data
Fx:{[aa;bb;cc] (aa%bb)*(1-exp(neg cc*1+til 5))*100};
Fy:{[aa;bb;cc] (aa%cc)*(1*(1-exp(neg cc*1+til 5)))};
Fz:{[aa;bb;cc] (aa%bb)*(1-exp(neg cc*1+til 5))};
当我为每个函数运行结果时,我们可以看到在某些段上缺少aa的地方。 aa应该是前一段(即aa = 864.6647 for AAA seg 2
和aa= 74.36035f for CCC seg 2)
show update result:first[Call_Function]'[aa;bb;cc] by Call_Function from t
id seg| aa bb cc Fname result
-------| ----------------------------------------------------------------
AAA 1 | 1500 150 0.4 Fx 329.68 550.671 698.8058 798.1035 864.6647
AAA 2 | 200 0.25 Fy
AAA 3 | 30 0.35 Fy
BBB 1 | 40 40 0.5 Fy 31.47755 50.56964 62.14959 69.17318 73.4332
CCC 1 | 900 10 0.35 Fz 26.57807 45.30732 58.5056 67.80627 74.36035
CCC 2 | 15 0.45 Fz
我一直在尝试引用上一段prev(last(t[result])
,但是列表结果不是参考。同样,我知道/ (over)
迭代器会很有用,但实现起来一直没有成功。
我考虑将其分解为几个步骤(所有段1然后是2,然后依次类推),然后将它们全部附加到最终表中。同样,我想跟踪每个段的累积值和时间计数(时间)以传递给函数作为限制器,因此成功引用上一行具有多种用途。
最终,一旦填充完毕,我将对该表进行拆组,以将其输出到类似于下面的输出中,然后可以根据需要重新排序。
q)show ungroup t
id seg aa bb cc Fname result
------------------------------------
AAA 1 1500 150 0.4 Fx 329.68
AAA 1 1500 150 0.4 Fx 550.671
AAA 1 1500 150 0.4 Fx 698.8058
AAA 1 1500 150 0.4 Fx 798.1035
AAA 1 1500 150 0.4 Fx 864.6647
AAA 2 200 0.25 Fy
AAA 2 200 0.25 Fy
AAA 2 200 0.25 Fy
AAA 2 200 0.25 Fy
AAA 2 200 0.25 Fy
AAA 3 30 0.35 Fy
AAA 3 30 0.35 Fy
AAA 3 30 0.35 Fy
AAA 3 30 0.35 Fy
AAA 3 30 0.35 Fy
BBB 1 40 40 0.5 Fy 31.47755
BBB 1 40 40 0.5 Fy 50.56964
BBB 1 40 40 0.5 Fy 62.14959
BBB 1 40 40 0.5 Fy 69.17318
BBB 1 40 40 0.5 Fy 73.4332
解决方法
TL; DR我想以下是您想要的:
q)t:update result:count[t]#enlist`float$() from t; // table extended to already contain a results column
q)applyF:{[t] update result:first[Fname]'[aa;bb;cc] by Fname from t where not null aa,0=count each result} //applies each Fname function when needed
q)updateA:{[t]update aa:prev[last each result]^aa by id from t}; // updates column aa based on previous results
q)myUpd:updateA applyF ::; // helper function applying the two above
q)ungroup myUpd over t;
id seg aa bb cc Fname result
----------------------------------------
AAA 1 1500 150 0.4 Fx 329.68
AAA 1 1500 150 0.4 Fx 550.671
AAA 1 1500 150 0.4 Fx 698.8058
AAA 1 1500 150 0.4 Fx 798.1035
AAA 1 1500 150 0.4 Fx 864.6647
AAA 2 864.6647 200 0.25 Fy 765.0526
AAA 2 864.6647 200 0.25 Fy 1360.876
AAA 2 864.6647 200 0.25 Fy 1824.904
AAA 2 864.6647 200 0.25 Fy 2186.289
AAA 2 864.6647 200 0.25 Fy 2467.737
AAA 3 2467.737 30 0.35 Fy 2082.149
AAA 3 2467.737 30 0.35 Fy 3549.414
AAA 3 2467.737 30 0.35 Fy 4583.378
AAA 3 2467.737 30 0.35 Fy 5312.001
AAA 3 2467.737 30 0.35 Fy 5825.452
BBB 1 40 40 0.5 Fy 31.47755
BBB 1 40 40 0.5 Fy 50.56964
BBB 1 40 40 0.5 Fy 62.14959
BBB 1 40 40 0.5 Fy 69.17318
BBB 1 40 40 0.5 Fy 73.4332
CCC 1 900 10 0.35 Fz 26.57807
CCC 1 900 10 0.35 Fz 45.30732
CCC 1 900 10 0.35 Fz 58.5056
CCC 1 900 10 0.35 Fz 67.80627
CCC 1 900 10 0.35 Fz 74.36035
CCC 2 74.36035 15 0.45 Fz 1.796406
CCC 2 74.36035 15 0.45 Fz 2.941846
CCC 2 74.36035 15 0.45 Fz 3.67221
CCC 2 74.36035 15 0.45 Fz 4.137911
CCC 2 74.36035 15 0.45 Fz 4.434855
现在开始解释,希望不要太久。
在这里我要做几个假设:
- 仅
aa
列为空 - 对于未定义
result
的行,我们可以推迟对aa
的评估
为方便起见,我启动了t
,使其具有空白的result
列
q)t:update result:count[t]#enlist`float$() from t;
id seg| aa bb cc Fname result
-------| --------------------------
AAA 1 | 1500 150 0.4 Fx
AAA 2 | 200 0.25 Fy
AAA 3 | 30 0.35 Fy
BBB 1 | 40 40 0.5 Fy
CCC 1 | 900 10 0.35 Fz
CCC 2 | 15 0.45 Fz
并定义一个函数,该函数将为已定义result
且尚未计算的任何行计算aa
q)applyF:{[t] update result:first[Fname]'[aa;bb;cc] by Fname from t where not null aa};
现在生成结果就像调用函数一样简单
q)applyF t;
id seg| aa bb cc Fname result
-------| ---------------------------------------------------------------
AAA 1 | 1500 150 0.4 Fx 329.68 550.671 698.8058 798.1035 864.6647
AAA 2 | 200 0.25 Fy `float$()
AAA 3 | 30 0.35 Fy `float$()
BBB 1 | 40 40 0.5 Fy 31.47755 50.56964 62.14959 69.17318 73.4332
CCC 1 | 900 10 0.35 Fz 26.57807 45.30732 58.5056 67.80627 74.36035
CCC 2 | 15 0.45 Fz `float$()
要从aa
获取下一个result
值,您可以执行类似的操作
q)update aa:prev[last each result]^aa by id from applyF t;
id seg| aa bb cc Fname result
-------| -------------------------------------------------------------------
AAA 1 | 1500 150 0.4 Fx 329.68 550.671 698.8058 798.1035 864.6647
AAA 2 | 864.6647 200 0.25 Fy `float$()
AAA 3 | 30 0.35 Fy `float$()
BBB 1 | 40 40 0.5 Fy 31.47755 50.56964 62.14959 69.17318 73.4332
CCC 1 | 900 10 0.35 Fz 26.57807 45.30732 58.5056 67.80627 74.36035
CCC 2 | 74.36035 15 0.45 Fz `float$()
我们可以通过编写另一个用于更新aa
q)updateA:{[t]update aa:prev[last each result]^aa by id from t};
q)updateA applyF t
id seg| aa bb cc Fname result
-------| -------------------------------------------------------------------
AAA 1 | 1500 150 0.4 Fx 329.68 550.671 698.8058 798.1035 864.6647
AAA 2 | 864.6647 200 0.25 Fy `float$()
AAA 3 | 30 0.35 Fy `float$()
BBB 1 | 40 40 0.5 Fy 31.47755 50.56964 62.14959 69.17318 73.4332
CCC 1 | 900 10 0.35 Fz 26.57807 45.30732 58.5056 67.80627 74.36035
CCC 2 | 74.36035 15 0.45 Fz `float$()
现在要获得您想要的结果,我们将一遍又一遍地应用这些更新。您对over
迭代器的直觉在这里是正确的。此处的用法将应用更新,直到表停止更改(aka converge)
q)myUpd:updateA applyF ::; // both update functions combined into one or convenience
q)myUpd over t
id seg| aa bb cc Fname result
-------| --------------------------------------------------------------------
AAA 1 | 1500 150 0.4 Fx 329.68 550.671 698.8058 798.1035 864.6647
AAA 2 | 864.6647 200 0.25 Fy 765.0526 1360.876 1824.904 2186.289 2467.737
AAA 3 | 2467.737 30 0.35 Fy 2082.149 3549.414 4583.378 5312.001 5825.452
BBB 1 | 40 40 0.5 Fy 31.47755 50.56964 62.14959 69.17318 73.4332
CCC 1 | 900 10 0.35 Fz 26.57807 45.30732 58.5056 67.80627 74.36035
CCC 2 | 74.36035 15 0.45 Fz 1.796406 2.941846 3.67221 4.137911 4.434855
q)(myUpd myUpd myUpd t) ~ (myUpd over t)
1b
然后您可以将ungroup
应用于上述结果以获得所需的输出。
另一种使用over的方法:
q)update res:{z .@[y;0;{y^x};last x]}\[0n;flip(aa;bb;cc);Fname] from t
id seg| aa bb cc Fname res
-------| ----------------------------------------------------------------
AAA 1 | 1500 150 0.4 Fx 329.68 550.671 698.8058 798.1035 864.6647
AAA 2 | 200 0.25 Fy 765.0526 1360.876 1824.904 2186.289 2467.737
AAA 3 | 30 0.35 Fy 2082.149 3549.414 4583.378 5312.001 5825.452
BBB 1 | 40 40 0.5 Fy 31.47755 50.56964 62.14959 69.17318 73.4332
CCC 1 | 900 10 0.35 Fz 26.57807 45.30732 58.5056 67.80627 74.36035
CCC 2 | 15 0.45 Fz 1.796406 2.941846 3.67221 4.137911 4.434855
对于您的问题,我不清楚的是,是否允许“最后一个值”从一个ID溢出到另一个ID。如果不应该,您只需在我的解决方案中添加一个“按ID”
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。