Search code examples
kdb

Ungroup over more than one columns in a given table


The answer provided here was supposed to work for many columns, how to use ungroup with multiple composite columns in kdb

But it doesn't. For cases like:

tb:([] x: 0 1 10; y:(1 1; 2 2 2; enlist 3); z:("kk";"ttt"; enlist "j");w:("cc";"bbbb";enlist "a")
ungroup1: {[col;tbl] @[tbl where count each tbl col;col;:;raze tbl col]}

This will work:

q)ungroup1[`y;tb]
x  y z     w     
-----------------
0  1 "kk"  "cc"  
0  1 "kk"  "cc"  
1  2 "ttt" "bbbb"
1  2 "ttt" "bbbb"
1  2 "ttt" "bbbb"
10 3 ,"j"  ,"a" 
```q

Again based on single column, 

```q
q)ungroup1[`z;tb]
x  y     z w     
-----------------
0  1 1   k "cc"  
0  1 1   k "cc"  
1  2 2 2 t "bbbb"
1  2 2 2 t "bbbb"
1  2 2 2 t "bbbb"
10 ,3    j ,"a" 

This won't work (raises 'length):

ungroup1[`y`z;tb]

Desired result:

x y z w
------------
0 1 k "cc"
0 1 k "cc"
1 2 t "bbbb"
1 2 t "bbbb"
1 2 t "bbbb"
10 3 j ,"a"

May I hear some input from the experts please


Solution

  • Since ungroup is implemented as raze flip each t, you can copy that approach but exclude (and re-join) the columns you don't want to be ungrouped.

    q)raze{key[y]#flip[x _y],\:(x:(),x)#y}[`w]each tb
    x  y z w
    -------------
    0  1 k "cc"
    0  1 k "cc"
    1  2 t "bbbb"
    1  2 t "bbbb"
    1  2 t "bbbb"
    10 3 j ,"a"
    
    q)raze{key[y]#flip[x _y],\:(x:(),x)#y}[`y`w]each tb
    x  y     z w
    -----------------
    0  1 1   k "cc"
    0  1 1   k "cc"
    1  2 2 2 t "bbbb"
    1  2 2 2 t "bbbb"
    1  2 2 2 t "bbbb"
    10 ,3    j ,"a"
    

    Assumes that the columns you've chosen to ungroup are actually ungroup-able (aka have matching lengths)