Replace middle row elements of nested list with new list elements Q kdb

Viewed 633

Hi so I have created the nested list/matrix:

 q)m:((1 2 3);(4 5 6);(7 8 9))
 q)m
 1 2 3
 4 5 6
 7 8 9

I have also identified the middle column in the list:

q)a:m[0;1],m[1;1],m[2;1]

I now want to replace the middle row (4 5 6) with a to finish with m looking like:

q)m
1 2 3
2 5 8
7 8 9 
5 Answers

You've already seen you can index into the matrix with syntax like m[0;1], where 0 refers to the first level of nesting and 1 refers to the second level

KDB also allows you to assign to an index of a list in a similar way e.g.

q)l:1 2 3 4
q)l[1]:20
q)l
1 20 3 4

So you can use something similar in this example:

q)m[1]:a
q)m
1 2 3
2 5 8
7 8 9

As an aside, KDB also allows you to leave out an index, in which case it will take all items from the corresponding level of nesting, e.g.

q)m[0]  /first level of nesting i.e. first row
1 2 3
q)m[;0] /second level of nesting i.e. first column
1 4 7

Hope that helps

Jonathon McMurray

AquaQ Analytics

You want to generalise for larger matrices (which must also be square) so your answer needs two parts:

  • how to construct a
  • how to insert it

for row/col x where x<count m.

The general expression you want is simply m[x;]:m[;x], because m[x;] denotes row x and m[;x] denotes column x.

See Q for Mortals 3.11.3 Two- and Three-Dimensional Matrices

You can make this a function of the index and the matrix:

q)show m:5 5#1_til 26
1  2  3  4  5 
6  7  8  9  10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25
q){y[x;]:y[;x];:y}[3;m]
1  2  3  4  5 
6  7  8  9  10
11 12 13 14 15
4  9  14 19 24
21 22 23 24 25

Just adding another approach for you.

q)m:8 cut til 64
q)0 0+\:til 8
0 1 2 3 4 5 6 7
0 1 2 3 4 5 6 7
q)(m)./:flip 0 0+\:til 8
0 9 18 27 36 45 54 63
q)@[m;4;:;(m)./:flip 0 0+\:til 8]
0  1  2  3  4  5  6  7 
8  9  10 11 12 13 14 15
16 17 18 19 20 21 22 23
24 25 26 27 28 29 30 31
0  9  18 27 36 45 54 63
40 41 42 43 44 45 46 47
48 49 50 51 52 53 54 55
56 57 58 59 60 61 62 63
q)

For fun, here it is in a function which takes the length&width of the matrix and replaces the 'middle' row with the diagonal values

q){n:x*x;m:x cut til n;@[m;x div 2;:;](m)./:flip 0 0+\:til x}8
0  1  2  3  4  5  6  7 
8  9  10 11 12 13 14 15
16 17 18 19 20 21 22 23
24 25 26 27 28 29 30 31
0  9  18 27 36 45 54 63
40 41 42 43 44 45 46 47
48 49 50 51 52 53 54 55
56 57 58 59 60 61 62 63
q){n:x*x;m:x cut til n;@[m;x div 2;:;](m)./:flip 0 0+\:til x}5
0  1  2  3  4 
5  6  7  8  9 
0  6  12 18 24
15 16 17 18 19
20 21 22 23 24
q){n:x*x;m:x cut til n;@[m;x div 2;:;](m)./:flip 0 0+\:til x}4
0  1  2  3 
4  5  6  7 
0  5  10 15
12 13 14 15
q)

Indexing in q can be straight forward and I believe a intermediate can be omitted:

q)m:((1 2 3);(4 5 6);(7 8 9))
q)m[1]:m[;1]
q)m
1 2 3
2 5 8
7 8 9
Related