如何在 q 中将 table 从宽转向长

how to pivot table wide to long in q

我正在尝试编写一个函数来将我的表格从宽格式转换为长格式。 所以我在这条线上有一些东西:

tblwide:([]k1:`a`a`b`b`c`c;xx:1 2 3 4 5 6;yy:11 12 13 14 15 16);
wide2long:{[lhscolnames;rhscolname;varcolname;valuecolname] ?[tblwide;enlist(~:;(^:;rhscolname));0b;((lhscolnames),varcolname,valuecolname)!(eval lhscolnames;enlist rhscolname;rhscolname)] };
tbllong:raze wide2long[enlist `k1;;`index;`val] each (cols tblwide) except `k1;

这似乎有效。
现在当我想要有几个不会旋转的列时,调整代码:

tblwide:([]k1:`a`a`b`b`c`c;k2:`t`u`t`u`t`u;xx:1 2 3 4 5 6;yy:11 12 13 14 15 16)
wide2long:{[lhscolnames;rhscolname;varcolname;valuecolname] ?[tblwide;enlist(~:;(^:;rhscolname));0b;((lhscolnames),varcolname,valuecolname)!(eval lhscolnames;enlist rhscolname;rhscolname)] };
tbllong:raze wide2long[`k1`k2;;`index;`val] each (cols tblwide) except `k1`k2;

然后它不再有效。 q 似乎不喜欢 eval .

预期的结果是,如果我这边没记错的话是:

expected:([] k1:`a`a`b`b`c`c`a`a`b`b`c`c; k2:`t`u`t`u`t`u`t`u`t`u`t`u ; index:`xx`xx`xx`xx`xx`xx`yy`yy`yy`yy`yy`yy;val:1 2 3 4 5 6 11 12 13 14 15 16)

顺序不重要真的我可以稍后重新排序...

我完全接受其他 simpler/faster 解决方案,但仍然很乐意了解如何使用 eval.

解决此问题

我认为您根本不需要 eval。像这样的方法应该适用于这两种情况:

wide2long:{[lhscolnames;rhscolname;varcolname;valuecolname] ?[tblwide;enlist(~:;(^:;rhscolname));0b;(lhscolnames,varcolname,valuecolname)!lhscolnames,enlist[enlist rhscolname],rhscolname]};

q)raze wide2long[`k1`k2;;`index;`val] each (cols tblwide) except `k1`k2
k1 k2 index val
---------------
a  t  xx    1  
a  u  xx    2  
b  t  xx    3  
b  u  xx    4  
c  t  xx    5  
c  u  xx    6  
a  t  yy    11 
a  u  yy    12 
b  t  yy    13 
b  u  yy    14 
c  t  yy    15 
c  u  yy    16