Kdb 如何在q中将表格从宽转长

Kdb 如何在q中将表格从宽转长,kdb,Kdb,我正在尝试编写一个函数,将我的表从宽格式转换为长格式。 所以我有一些关于这方面的东西: 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)!(

我正在尝试编写一个函数,将我的表从宽格式转换为长格式。 所以我有一些关于这方面的东西:

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)
订单并不重要,我可以以后再重新订购


我完全愿意接受其他更简单/更快的解决方案,但仍然很乐意了解如何使用
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 

我认为您根本不需要
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 

非常感谢Terry,“这很有效”。我可以请你对这篇文章发表评论吗!lhscolnames,enlist[enlist rhscolname],rhscolname我对此有点迷茫(我不知道如何在这个上下文中调查这3个术语的类型和值)。我的理解是,我们需要一本将键映射到列表的词典。然后lhscolnames包含列的名称,而rhscolname包含列的值,然后enlist enlist我根本不懂。。。(我使用parse和trial-and-error构建了这个东西的一半)您正在试图找到它的函数形式(特别是字典):
d:last parse“选择k1,k2,index:`xx,val:xx from tblwide where not null xx”
。生成键很简单:
key[d]~lhscolnames、varcolname、valuecolname
。这些值比较复杂,因为对于索引列,您试图指定单词“xx”,而不是列“xx”。您可以通过登记“xx”来避免这种歧义。需要额外的登记来阻止kdb将两个符号列表追加到一个统一列表中。因此,
value[d]~lhscolnames,enlist[enlist rhscolname],rhscolname
我想我明白了。谢谢你的解释。非常感谢特里,“它很有效”。我可以请你对这篇文章发表评论吗!lhscolnames,enlist[enlist rhscolname],rhscolname我对此有点迷茫(我不知道如何在这个上下文中调查这3个术语的类型和值)。我的理解是,我们需要一本将键映射到列表的词典。然后lhscolnames包含列的名称,而rhscolname包含列的值,然后enlist enlist我根本不懂。。。(我使用parse和trial-and-error构建了这个东西的一半)您正在试图找到它的函数形式(特别是字典):
d:last parse“选择k1,k2,index:`xx,val:xx from tblwide where not null xx”
。生成键很简单:
key[d]~lhscolnames、varcolname、valuecolname
。这些值比较复杂,因为对于索引列,您试图指定单词“xx”,而不是列“xx”。您可以通过登记“xx”来避免这种歧义。需要额外的登记来阻止kdb将两个符号列表追加到一个统一列表中。因此,
value[d]~lhscolnames,enlist[enlist rhscolname],rhscolname
我想我明白了。谢谢你的解释。