I am trying to update a column in my table using the vector conditional function in kdb+ such that after each conditional is tested, the value outputted is based on the output value previous in the row above but same column. Suppose I have a table as such:
t:([] number:-100 100 600 -200 -400f);
t: update cumsum: sums[number] from t;
t: update signumcumsum: signum cumsum from t;
t: update role:1b from t;
number | cumsum | signumcumsum |
---|---|---|
-100 | -100 | -1 |
100 | 0 | 0 |
600 | 600 | +1 |
-200 | 400 | +1 |
-400 | 0 | 0 |
And now I would like to use a vector conditional to update each role such that each value is based on the previous value in the row above. My command is
t: update role: ?[(signumcumsum)=(prev signumcumsum);1^prev role;not 1^prev role] from t;
And I intend the table to look like this
number | cumsum | signumcumsum | role |
---|---|---|---|
-100 | -100 | -1 | 1b |
100 | 0 | 0 | 0b |
600 | 600 | +1 | 1b |
-200 | 400 | +1 | 1b |
-400 | 0 | 0 | 0b |
However the table outputted in the console is like this:
number | cumsum | signumcumsum | role |
---|---|---|---|
-100 | -100 | -1 | 1b |
100 | 0 | 0 | 1b |
600 | 600 | +1 | 1b |
-200 | 400 | +1 | 1b |
-400 | 0 | 0 | 1b |
Is there something wrong with my logic or how I am writing the code? Would much appreciate any corrections or advice.
Potentially there are 2 issues with your logic.
prev
on a Boolean list gives 0b
for the first element, not a null value. You are trying to fill a null value, but there are none.role
value is not carrying forward like you expect.I can get the expected output by fixing point 2. Here I used scan \
to continually modify the role
value, which starts as 1b
. This carries the previous role
value forward.
q)update role:{[role;signumcumsum;prevSCS]$[signumcumsum=prevSCS;role;not role]}\[1b;signumcumsum;prev[first signumcumsum;signumcumsum]] from t
number cumsum signumcumsum role
-------------------------------
-100 -100 -1 1
100 0 0 0
600 600 1 1
-200 400 1 1
-400 0 0 0
Note the use of prev[first signumcumsum;signumcumsum]
here which ensures the initial role
value is 1b
.