q/KDB - nprev function to get all the previous n elements - kdb

I am struggling to write a nprev function in KDB; xprev function returns the nth element but I need all the prev n elements relative to the current element.
q)t:([] i:1+til 26; s:.Q.a)
q)update xp:xprev[3;]s,p:prev s from t
Any help is greatly appreciated.

You can achieve the desired result by applying prev repeatedly and flipping the result
q)n:3
q)select flip 1_prev\[n;s] from t
s
-----
" "
"a "
"ba "
"cba"
"dcb"
"edc"
..
If n is much smaller than the rows count, this will be faster than some of the more straightforward solutions.

The xprev function basically looks like this :
xprev1:{y til[count y]-x} //readable xprev
We can tweak it to get all n elements
nprev:{y til[count y]-\:1+til x}
using nprev in the query
q)update np: nprev[3;s] , xp1:xprev1[3;s] , xp: xprev[3;s], p:prev[s] from t
i s np xp1 xp p
-------------------
1 a " "
2 b "a " a
3 c "ba " b
4 d "cba" a a c
5 e "dcb" b b d
6 f "edc" c c e
k equivalent of nprev
k)nprev:{$[0h>#y;'`rank;y(!#y)-\:1+!x]}
and similarly nnext would look like
k)nnext:{$[0h>#y;'`rank;y(!#y)+\:1+!x]}

Related

How do you add spaces in front of 'y' integers in a nested loop?

for x in range(1, 4):
print(x)
for y in range(5, 10):
print(y)
I tried adding " " + in front of y within print. Essentially,
print(" " + y)
I tried creating a string w that equals " " to add in front of y. Essentially,
w = " "
print(w + y)
I'd like the output to look like:
1
5
6
2
5
6
3
5
6
I'm exploring .join() at the moment to see if this method can provide a solution.
Thank you.
for x in range(1, 4):
print(x)
for y in range(5, 10):
w = " "
print(w + str(y)) or print(" " + str(y))
output:
1
5
6
2
5
6
Python string formatting is easy and clean in this case. You can see https://pyformat.info/ for a quick introduction.
Example with the most recent format function:
for x in range(1, 4):
print("{:d}".format(x))
for y in range(5, 10):
print("{:>3d}".format(y))
Short explanation:
{:d}: format the argument as a digit
{:>3d}: align right, make the string 3 characters long and format the argument as a digit

q - apply function on table rowwise

Given a table and a function
t:([] c1:1 2 3; c2:`a`b`c; c3:13:00 13:01 13:02)
f:{[int;sym;date]
symf:{$[x=`a;1;x=`b;2;3]};
datef:{$[x=13:00;1;x=13:01;2;3]};
r:int + symf[sym] + datef[date];
r
};
I noticed that when applying the function f onto columns of t, then the entire columns are passed into f and if they can be operated on atomically then the output will be of the same length as the inputs and a new column is produced. However in our example this wont work:
update newcol:f[c1;c2;c3] from t / 'type error
because the inner functions symf and datef cannot be applied to the entire column c2, c3, respectively.
If I dont want to change the function f at all, how can I apply it row by row and collect the values into a new column in t.
What's the most q style way to do this?
EDIT
If not changing f is really inconvenient one could workaround like so
f:{[arglist]
int:arglist 0;
sym:arglist 1;
date:arglist 2;
symf:{$[x=`a;1;x=`b;2;3]};
datef:{$[x=13:00;1;x=13:01;2;3]};
r:int + symf[sym] + datef[date];
r
};
f each (t`c1),'(t`c2),'(t`c3)
Still I would be interested how to get the same result when working with the original version of f
Thanks!
You can use each-both for this e.g.
q)update newcol:f'[c1;c2;c3] from t
c1 c2 c3 newcol
------------------
1 a 13:00 3
2 b 13:01 6
3 c 13:02 9
However you will likely get better performance by modifying f to be "vectorised" e.g.
q)f2
{[int;sym;date]
symf:3^(`a`b!1 2)sym;
datef:3^(13:00 13:01!1 2)date;
r:int + symf + datef;
r
}
q)update newcol:f2[c1;c2;c3] from t
c1 c2 c3 newcol
------------------
1 a 13:00 3
2 b 13:01 6
3 c 13:02 9
q)\ts:1000 update newcol:f2[c1;c2;c3] from t
4 1664
q)\ts:1000 update newcol:f'[c1;c2;c3] from t
8 1680
In general in KDB, if you can avoid using any form of each and stick to vector operations, you'll get much more efficiency

How does this kbd function work?

Would someone please explain the below function? How does the kdb utilize x here?
I changed the original function to "func" I know it uses the queries assigned in que to query both functions. The problem is I don't know how those x 0 and and x 0 1 work here. I know 0 is the index 1 and 1 is the index 2 and x is the parameter.
svcs:`TEST:1`TEST:2
que: (`$"select count sym from trades";`$"select sum size from trades")
{func[x 0;string x 1],x 0 1}each svcs cross que
x is being passed in as a two element list "each" time the function is called.
Forget about the func description for now and just add in some logging to see things more clearly:
q)svcs cross que
TEST:1 select count sym from trades
TEST:1 select sum size from trades
TEST:2 select count sym from trades
TEST:2 select sum size from trades
q){show enlist "x 0 is ",string x 0;show enlist "x 1 is ",string x 1;show raze "
x 0 1 is ",(string x 0)," & ", (string x 1)}each svcs cross que;
"x 0 is TEST:1"
"x 1 is select count sym from trades"
"x 0 1 is TEST:1 & select count sym from trades"
"x 0 is TEST:1"
"x 1 is select sum size from trades"
"x 0 1 is TEST:1 & select sum size from trades"
"x 0 is TEST:2"
"x 1 is select count sym from trades"
"x 0 1 is TEST:2 & select count sym from trades"
"x 0 is TEST:2"
"x 1 is select sum size from trades"
"x 0 1 is TEST:2 & select sum size from trades"
Or an individual example:
q)x:(`TEST:1;`$"select count sym from trades")
q)x 0
`TEST:1
q)x 1
`select count sym from trades
q)x 0 1
`TEST:1`select count sym from trades
x 0 1 indexes and retrieves both the first and second element (returning
You're right and x 0 or x 1 is the same as x[0] or x[1] (see the link below on indexing lists), except perhaps the problem is that it isn't obvious what x is.
Because of the adverb each the function is executed four times, once for each item in svcs cross que
See;
q)count svcs cross que
4
And then each item in svcs cross que has two items.
q)count each svcs cross que
2 2 2 2
So in the first execution, x is the first item of svcs cross que and so on.
q)first svcs cross que
`TEST:1`select count sym from trades
q)(first svcs cross que) 0
`TEST:1
q)(first svcs cross que) 1
`select count sym from trades
q)(first svcs cross que) 0 1
`TEST:1`select count sym from trades
Reference
http://code.kx.com/q4m3/6_Functions/#671-monadic-each
http://code.kx.com/q4m3/3_Lists/#34-indexing

Simplifying boolean algebra (XOR)

I know how to convert first and second term to the first term of the simplified expression, but I don't know how to convert the rest.
By simplifying, I can get rid of A_Bar in the third term and A in the fifth term and get =B*C_bar
How is it that B*C_bar + the fourth term = becomes XOR(B,C) ?
The two expressions are clearly the same. This can be easily proven by truth tables.
The first one is:
And the second one:
However, this does not fully answer your question.
B*C_bar + the fourth term = becomes XOR(B,C)
This is clearly true if A is true, since per definitionem, B XOR C = B_bar and C OR B and C_bar.
If A is false, these terms are always false and you cannot simplify these two to B XOR C! They are not equal!
Note: Tables generated with http://web.stanford.edu/class/cs103/tools/truth-table-tool/
Note2: ^= OR, ¬ = NOT, ∨ = AND
let play a game.
Let a=not(A), b=not(B) and c=not(C) and *=xor
Y = ab + (B*C)
Y = ab + Bc + bC
Y = ab(1) + Bc(1) + bC(1)
Y = ab(c+C) + Bc(a+A) + bC(a+A)
Y = abc + abC + Bca + BcA + bCa + bCA
Y = abc + abC + aBc + ABc + abC + AbC
Y = abc + abC + aBc + ABc + AbC
That is the first equ.

Crystal Reports Cross-tab with mix of Sum, Percentages and Computed values

Being new to crystal, I am unable to figure out how to compute rows 3 and 4 below.
Rows 1 and 2 are simple percentages of the sum of the data.
Row 3 is a computed value (see below.)
Row 4 is a sum of the data points (NOT a percentage as in row 1 and row 2)
Can someone give me some pointers on how to generate the display as below.
My data:
2010/01/01 A 10
2010/01/01 B 20
2010/01/01 C 30
2010/02/01 A 40
2010/02/01 B 50
2010/02/01 C 60
2010/03/01 A 70
2010/03/01 B 80
2010/03/01 C 90
I want to display
2010/01/01 2010/02/01 2010/03/01
========== ========== ==========
[ B/(A + B + C) ] 20/60 50/150 80/240 <=== percentage of sum
[ C/(A + B + C) ] 30/60 60/150 90/240 <=== percentage of sum
[ 1 - A/(A + B + C) ] 1 - 10/60 1 - 40/150 1 - 70/240 <=== computed
[ (A + B + C) ] 60 150 250 <=== sum
Assuming you are using a SQL data source, I suggest deriving each of the output rows' values (ie. [B/(A + B + C)], [C/(A + B + C)], [1 - A/(A + B + C)] and [(A + B + C)]) per date in the SQL query, then using Crystal's crosstab feature to pivot them into the output format desired.
Crystal's crosstabs aren't particularly suited to deriving different calculations on different rows of output.