Utsav
Utsav

Reputation: 5918

Replace infinities with nulls and then fill them using fills in q kdb

I was going through fills explanation and came across below example: i.e if there are infinities replace them with nulls and then fill them using fills.

q)fills {(x where x=0W):0N;x} 0N 2 3 0W 0N 7 0W
Output - 0N 2 3 3 3 7 7

I want to further expand this problem that if the first value in the output is Null then fill it with default value 1, for which I had written two versions of solution.

{(x where x=0N):1;x} fills {(x where x=0W):0N;x} 0N 2 3 0W 0N 20 30 0W
1^fills {(x where x=0W):0N;x} 0N 2 3 0W 0N 20 30 0W /- Output - 1 2 3 3 3 20 30 30

Which of the two is optimized version(I think it's 2nd one using fill)?
Any better/optimized version of it?

Upvotes: 1

Views: 1358

Answers (3)

Contango
Contango

Reputation: 80372

Convert null and +/- infinity to 0:

nanInfToZero:{[x] // Converts NaN and positive/negative infinity to zero.
    if [not 9h=type x;`"Error. Inputs should be 64-bit floats, cast with `float$x"];
    result: {[x] (x where x in (-0w,0w)):0n;x}[x];
    :0^result; 
};

if [not nanInfToZero[(0n 2 3)]~(0 2 3f); `"Incorrect"];
if [not nanInfToZero[(-0w 2 3)]~(0 2 3f); `"Incorrect"];
if [not nanInfToZero[(0w 2 3)]~(0 2 3f); `"Incorrect"];

Then use fills to fill forward.

Tested under Windows x64 and KDB v4.

Upvotes: -1

Sean O'Hagan
Sean O'Hagan

Reputation: 1697

Adding 1 to infinity transforms it to a null

q)0W 10 0N+1
0N 11 0N

To keep the orig values, and the nulls, lets subtract 1 from the resulting list

q)-1+0W 10 0N+1
0N 10 0N

Fills can accept two params (the starting digit as x if you give it two params)

q)fills 0N 10 20 0N 40
0N 10 20 20 40
q)fills[33;] 0N 10 20 0N 40
33 10 20 20 40

So putting it altogether for your requirements

q)fills[1;] -1+x+1
1 2 3 3 3 20 30 30 30 2 3 3 3 20 30 30 30 2 3 3 3 20 30 30 30 2 3 3 3 20 30 3..

HTH, Sean

Upvotes: 1

terrylynch
terrylynch

Reputation: 13657

You can always test the solutions by timing them for a large vector

q)\ts {(x where x=0N):1;x} fills {(x where x=0W):0N;x}10000000#0N 2 3 0W 0N 20 30 0W
196 553649552

q)\ts 1^fills {(x where x=0W):0N;x}10000000#0N 2 3 0W 0N 20 30 0W
190 553649216

For large vectors you should get a small improvement by only filling the first item with 1, assuming that's the only one you need defaulted to one

q)@[;0;1^]fills {(x where x=0W):0N;x}0N 2 3 0W 0N 20 30 0W
1 2 3 3 3 20 30 30

However, if you have a sequence of nulls in the beginning (not just one) then this won't help

q)@[;0;1^]fills {(x where x=0W):0N;x}0N 0N 2 3 0W 0N 20 30 0W
1 0N 2 3 3 3 20 30 30

In that case you're better off going with the 1^ on the entire vector

Upvotes: 1

Related Questions