(q/kdb+) Merge items in a list - kdb

I have a list of items and need to merge them into a single column
using the list
list:(1 2;3 4 5 7;0 1 3)
index value
0 1 2
1 3 4 5 7
2 0 1 3
my goal is
select from list2
value
1
2
3
4
5
7
0
1
3

'raze' function flattens out 1 level of the list.
q) raze (1 2;3 4 5 7;0 1 3)
q) 1 2 3 4 5 7 0 1 3
If you have list with multi level indexing then use 'over' adverb with raze:
q) (raze/)(1 2 3;(11 12;33 44);5 6)
To convert that to table column:
q) t:([]c:raze list)

ungroup would also work provided your table doesn't have multiple columns with different nesting (or strings)
q)ungroup ([]list)
list
----
1
2
3
4
5
7
0
1
3

If you just wanted your list to appear like that I would do the following.
1 cut raze list
I see that you have used a select statement, however if you want your column defined as this in your table do the following
a:raze list
tab:([] b:a)
Your output from this should look like this
q)tab
b
-
1
2
3
4
5
7
0
1
3
Overall, a more concise way to achieve what you want to do would be
select from ([]raze list)
To avoid any errors you should not call the column header 'value' as this is a protected keyword in kdb+ and when you try to reassign it as a column header kdb will through an assign error
`assign
Hope this helps

Related

Sum of each two elements using vector functions

How to get sum of eath two elements with the vector functions? I want the same result as:
{x+y}':[1 2 3 2 1]
Why this approach gives something different than first one?
sum':[1 2 3 2 1]
sum is not the same as {x+y}.
sum has rank 1 meaning it takes one input and sums the elements of that input.
It can sum an atom:
q)sum 1
1
a uniform list
q)sum 1 2
3
or a list of lists
q)sum(1 2;3 4)
4 6
{x+y} is rank 2 meaning it requires two inputs.
q){x+y}[1;2]
3
q){x+y}[1 2;3 4]
4 6
Giving it an atom, a single list, or a list of lists leads to projections
q){x+y}1
{x+y}[1]
q){x+y}1 2
{x+y}[1 2]
q){x+y}(1 2;3 4)
{x+y}[(1 2;3 4)]
Since each-prior (':) creates binary pairs from the input and attempts to apply a rank 2 function, it works as intended on your rank 2 function {x+y}.
But since sum is not rank 2 the each-prior doesn't generate pairs in the same way, it's equivalent to doing
q){x}':[1 2 3 2 1]
1 2 3 2 1
q){sum x}':[1 2 3 2 1]
1 2 3 2 1
You could force it to be rank 2:
q){sum(x;y)}':[1 2 3 2 1]
1 3 5 5 3
but this gives a different result since sum ignores nulls while + doesn't.
q)sum(0N;1)
1
q)0N+1
0N
Finally, an alternative way to achieve this using sum (and without using each-prior) is to shift the vector using prev and then sum
q){sum(prev x;x)}[1 2 3 2 1]
0N 3 5 5 3

How to update multiple tables in kdb

Say I have a list of tables. (sym1, sym2, sym3 etc)
How would I add a new column to each table called Sym containing the table name?
Thank you
You could use something like:
q){#[value x;`Sym;:;x]}each tables[]
+`a`b`c`Sym!(0 1 2 3 4;0 1 2 3 4;0 1 2 3 4;`sym1`sym1`sym1`sym1`sym1)
+`a`b`c`Sym!(0 1 2 3 4;0 1 2 3 4;0 1 2 3 4;`sym2`sym2`sym2`sym2`sym2)
+`a`b`c`Sym!(0 1 2 3 4;0 1 2 3 4;0 1 2 3 4;`sym3`sym3`sym3`sym3`sym3)
If you remove value from the first argument of #, this will update the tables in place.
Otherwise, since this returns a list, you can use indexing to return the table you want from the list:
q)({#[value x;`Sym;:;x]}each tables[])0
a b c Sym
----------
0 0 0 sym1
1 1 1 sym1
2 2 2 sym1
3 3 3 sym1
4 4 4 sym1
Hope this helps,
James
Another way to achieve this :
q){update Sym:x from x}each `sym1`sym2`sym3
q)raze (sym1;sym2;sym3)
p s Sym
----------------
2.08725 75 sym1
2.065687 6 sym1
2.058972 63 sym2
2.095509 62 sym2
2.036151 90 sym3
2.090895 63 sym3
If you are getting these tables (sym1,sym2,sym3) as the output of another function call like :
f each `s1`s2`s3
then I'll suggest updating the function to add the column Sym just before return these individual tables.
f:{
/some logic
update Sym:x from t
}
This will save an operation of adding a new column separately

How to implement combinations of a list

All
I need to get the combinations and permutations of a list.
A function have been implemented for permutations.
perm:{[N;l]$[N=1;l;raze .z.s[N-1;l]{x,/:y except x}\:l]}
However, I have no idea about combinations, just like this:
l: 1 2 3
comb[2;l]
1 2
1 3
2 3
l: 1 2 3 4
comb[3;l]
1 2 3
1 2 4
1 3 4
2 3 4
Thanks!
From your solution, you can do:
q)comb:{[N;l]$[N=1;l;raze .z.s[N-1;l]{x,/:y where y>max x}\:l]}
q)comb[2;1 2 3]
1 2
1 3
2 3
Another approach using over:
q)perm:{{raze x{x,/:y except x}\:y}[;y]/[x-1;y]}
q)comb:{{raze x{x,/:y where y>max x}\:y}[;y]/[x-1;y]}
One option is to use your permutation function like this:
q) comb:{[N;l] distinct asc each perm[N;l] }
q)l: 1 2 3 4
q) comb[3;l]
output:
1 2 3
1 2 4
1 3 4
2 3 4
Note: This will change the order of elements because of asc. So if your list should have (1 3 2) in answer, it will give (1 2 3).
To maintain order, use any other function/logic in place of asc to filter duplicate elements in sets (ex: (1 2 3) and (1 3 2) are duplicates).

find group of elements in matrix matlab

I have an array of elements E = [1 2 3 4 5 10] and matrix A of couples of elements
A=[ 1 2;
2 3;
3 1;
4 1;
4 3;
5 1]
You can read this matrix as
1 is similar (with a certain probability) to 2
2 is similar (with a certain probability) to 3
3 is similar (with a certain probability) to 1 etc...
I would like to know how many different groups of element are in the array E given the matrix A
In this case I have
1 group = 1 2 3
2 group = 1 3 4
3 group = 1 5
4 group = 10
so there are 4 different groups of elements in E
NOTE:
if 1 is similar to 2 (first row)
and if 5 is similar to 1 (sixth row)
5 is not similar to 2!!! (if it is not written anywhere)
so 1 2 5 don't belong to the same group
On the other hand
1 is similar to 2 (first row),
2 is similar to 3 (second row)
and 3 is similar to 1 (third row)
so 1 2 3 belong to the same group

Pass multiple arguments to a function within select

I'd like to calculate a new column which is a function of several columns using select.
My actual application will involve a grouping in the select so the columns entries which I will pass to the function will contain lists. But this simple example illustrates my question
t:([] a:1 2 3; b:10 20 30; c:5 6 7)
/ Pass one argument, using projection (set first two arguments to 1)
select s:{[x;y;z] x+y+z}[1;1;] each a from t
/ Pass two arguments using each-both (set first arg to 1)
select s:a {[x;y;z] x+y+z}[1;;]'b from t
Now, how can I pass three or more arguments?
Each' will work in general but it's best to use vector operations where possible. Here I use the . operator to apply our function, \t to time both methods. I store their results to r1/r2 to show they are the same:
q)t:([]a:til n;b:til n;c:til n:1200300)
q)\t r1:update d:{x+y+z}'[a;b;c] from t
289
q)\t r2:update d:{x+y+z} . (a;b;c) from t
20
q)r1~r2
1b
q)r2
a b c d
-----------
0 0 0 0
1 1 1 3
2 2 2 6
3 3 3 9
4 4 4 12
5 5 5 15
..
Cheers,
Ryan
The following form works in general
q)t:([]a:til 10;b:til 10;c:til 10)
q)select d:{x+y+z}'[a;b;c] from t
d
--
0
3
6
9
..