How does this kbd function work? - kdb

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

Related

PostGIS make buffer on LINESTRING Z to have a POLYGON Z

I have several LINESTRING Z geometies in PostgreSQL and they look like
LINESTRING Z (1 2 1,1 1 4)
I want to make a buffer around this linestring so that i can have a POLYGON Z geometry for further export to dxf.
I tried this
select st_astext(st_buffer('LINESTRING Z (1 2 1,1 1 4)'::geometry, 2)) as geom;
and it gives me
POLYGON((3 1,2.96157056080646 0.609819355967741,2.84775906502257 0.23463313526
9818,2.66293922460509 -0.111140466039206,2.41421356237309 -0.414213562373096,2.
1111404660392 -0.662939224605091,1.76536686473018 -0.847759065022574,1.39018064
403226 -0.961570560806461,1 -1,0.609819355967745 -0.961570560806461,0.234633135
269822 -0.847759065022574,-0.111140466039202 -0.662939224605092,-0.414213562373
094 -0.414213562373096,-0.662939224605089 -0.111140466039207,-0.847759065022572
0.234633135269818,-0.96157056080646 0.609819355967739,-1 1,-1 2,-0.96157056080
646 2.39018064403226,-0.847759065022572 2.76536686473018,-0.662939224605089 3.1
1114046603921,-0.414213562373094 3.4142135623731,-0.111140466039203 3.662939224
60509,0.234633135269821 3.84775906502257,0.609819355967744 3.96157056080646,1 4
,1.39018064403226 3.96157056080646,1.76536686473018 3.84775906502257,2.11114046
60392 3.66293922460509,2.41421356237309 3.4142135623731,2.66293922460509 3.1111
4046603921,2.84775906502257 2.76536686473018,2.96157056080646 2.39018064403226,
3 2,3 1)) (1 row)
which is in 2D POLYGON not POLYGON Z
How can I make it 3D?
I'm not totally sure what you want to achieve, but did you take a look at ST_Force3D?
SELECT
ST_AsText(
ST_Force3D(
ST_Buffer('LINESTRING Z (1 2 1,1 1 4)'::GEOMETRY, 2)));
It will return a POLYGON Z geometry:
POLYGON Z ((3 1 0,2.96157056080646 0.609819355967741 0,2.84775906502257 0.234633135269818 0,2.66293922460509 -0.111140466039206 0,2.41421356237309 -0.414213562373096 0,2.1111404660392 -0.662939224605091 0,1.76536686473018 -0.847759065022574 0,1.39018064403226 -0.961570560806461 0,1 -1 0,0.609819355967745 -0.961570560806461 0,0.234633135269822 -0.847759065022574 0,-0.111140466039202 -0.662939224605092 0,-0.414213562373094 -0.414213562373096 0,-0.662939224605089 -0.111140466039207 0,-0.847759065022572 0.234633135269818 0,-0.96157056080646 0.609819355967739 0,-1 1 0,-1 2 0,-0.96157056080646 2.39018064403226 0,-0.847759065022572 2.76536686473018 0,-0.662939224605089 3.11114046603921 0,-0.414213562373094 3.4142135623731 0,-0.111140466039203 3.66293922460509 0,0.234633135269821 3.84775906502257 0,0.609819355967744 3.96157056080646 0,1 4 0,1.39018064403226 3.96157056080646 0,1.76536686473018 3.84775906502257 0,2.1111404660392 3.66293922460509 0,2.41421356237309 3.4142135623731 0,2.66293922460509 3.11114046603921 0,2.84775906502257 2.76536686473018 0,2.96157056080646 2.39018064403226 0,3 2 0,3 1 0))
The function ST_Buffer discards the Z dimension, as stated in the documentation:
... This function ignores the third dimension (z) and will always give a
2-d buffer even when presented with a 3d-geometry.
EDIT:
This query sort of creates a buffer with the average Z value of a given LINESTRING Z.
WITH j AS (
SELECT
ST_DumpPoints(
ST_Buffer('LINESTRING Z (1 2 1,1 1 4)'::GEOMETRY, 2)
) AS pt,
(SELECT AVG(z) AS avg_z
FROM (SELECT ST_Z((ST_DumpPoints('LINESTRING Z (1 2 1,1 1 4)'::GEOMETRY)).geom) AS z) AS z) AS lsz
)
SELECT ST_AsText(
ST_MakePolygon(ST_MakeLine(ST_MakePoint(ST_X((pt).geom),ST_Y((pt).geom),lsz))))
FROM j
GROUP BY lsz;
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
POLYGON Z ((3 1 2.5,2.96157056080646 0.609819355967741 2.5,2.84775906502257 0.234633135269818 2.5,2.66293922460509 -0.111140466039206 2.5,2.41421356237309 -0.414213562373096 2.5,2.1111404660392 -0.662939224605091 2.5,1.76536686473018 -0.847759065022574 2.5,1.39018064403226 -0.961570560806461 2.5,1 -1 2.5,0.609819355967745 -0.961570560806461 2.5,0.234633135269822 -0.847759065022574 2.5,-0.111140466039202 -0.662939224605092 2.5,-0.414213562373094 -0.414213562373096 2.5,-0.662939224605089 -0.111140466039207 2.5,-0.847759065022572 0.234633135269818 2.5,-0.96157056080646 0.609819355967739 2.5,-1 1 2.5,-1 2 2.5,-0.96157056080646 2.39018064403226 2.5,-0.847759065022572 2.76536686473018 2.5,-0.662939224605089 3.11114046603921 2.5,-0.414213562373094 3.4142135623731 2.5,-0.111140466039203 3.66293922460509 2.5,0.234633135269821 3.84775906502257 2.5,0.609819355967744 3.96157056080646 2.5,1 4 2.5,1.39018064403226 3.96157056080646 2.5,1.76536686473018 3.84775906502257 2.5,2.1111404660392 3.66293922460509 2.5,2.41421356237309 3.4142135623731 2.5,2.66293922460509 3.11114046603921 2.5,2.84775906502257 2.76536686473018 2.5,2.96157056080646 2.39018064403226 2.5,3 2 2.5,3 1 2.5))
(1 row)

Functions with pre millenium dates in q

I've built a function in q such that I can see how many Sunday's fall on the 1st of the month between two dates
\W 1 f3:{[sd;ed] count distinct `week$(sd + til 1 + ed - sd) where (`dd$distinct `week$sd + til 1 + ed - sd)=01}
How can I edit with to work with pre 2000 dates? Can I put a modulus around the negative dates? Or will that redender my function incorrect?
You can also try this:
q) f:{sum 1=mod[`date$a[1] + til 1+(-). a:(0;1<`dd$x)+`month$(y;x);7]}
q) f[2018.01.01;2018.12.31] / 2
q) f[1998.01.02;1999.12.31] / 4

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

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]}

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

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.