根据列值重塑 table
reshaping table based on column values
我正在研究根据值重塑 table 创建新列的问题。
我使用的示例与此处讨论的问题相同:
所以我有一个 table:
df:([]ID:1+til 5;
Group:1 1 2 2 2;
V1:10 + 2 * til 5;
Type_v1:`t1`t2`t1`t1`t2;
V2:3 0N 0N 7 8;
Type_v2:`t2```t3`t3);
ID Group V1 Type_v1 V2 Type_v2
------------------------------
1 1 10 t1 3 t2
2 1 12 t2
3 2 14 t1
4 2 16 t1 7 t3
5 2 18 t2 8 t3
目标是将其转换为按组和类型获取值的总和。请注意创建的新列。基本上 Type_v1 和 Type_v2 中的所有类型都用于为结果 table.
创建列
# group v_1 type_1 v_2 type_2 v_3 type_3
#1: 1 10 t1 15 t2 NA <NA>
#2: 2 30 t1 18 t2 15 t3
我做了开头,但我无法转换 table 并创建新列。
当然,我也在尝试以动态方式创建所有列,因为手动输入 20k 列是不可能的。
df1:select Group, Value:V1, Type:Type_v1 from df;
df2:select Group, Value:V2, Type:Type_v2 from df;
tr:df1,df2;
tr:0!select sum Value by Group, Type from tr where Type <> ` ;
基本上我错过了相当于:
dcast(tmp, group ~ rowid(group), value.var = c("v", "type"))
感谢任何帮助和解释,
您遗漏的最后一块是枢轴:https://code.kx.com/q/kb/pivoting-tables/
q)P:exec distinct Type from tr
q)exec P#(Type!Value) by Group:Group from tr
Group| t1 t2 t3
-----| --------
1 | 10 15
2 | 30 18 15
它不能完全为您提供准确的输出,但枢轴是概念
您可以扩展 Terry 的枢轴以使用函数形式动态执行上述 select 部分。在此处查看更多详细信息:
https://code.kx.com/q/basics/funsql/
// Personally, I would try to stay clear of column names too similar to reserved keywords in kdb
df: `id`grpCol`v_1`typCol_1`v_2`typCol_2 xcol df;
{[df;n]
// dynamically create cols from 1 to n
cls:`$("v_";"typCol_"),\:/:string 1 + til n;
// functional form of select for each type/value col before joining together
df:(,/) {?[x;();0b;`grpCol`v`typCol!`grpCol,y]}[df] each cls;
// sum, then pivot
df:0!select sum v by grpCol, typCol from df where typCol <> `;
P:exec distinct typCol from df;
df:exec P#(typCol!v) by grpCol:grpCol from df;
// Type cols seem unnecessary but
// Can be done with another functional select
?[df;();0b;(`grpCol,raze P,'`$"typCol_",/:string 1 + til count P)!`grpCol,raze flip (P;enlist each P)]
}[df;2]
grpCol t1 typCol_1 t2 typCol_2 t3 typCol_3
1 10 t1 15 t2 0N t3
2 30 t1 18 t2 15 t3
编辑 - 下面更详细的细分:
cls:`$("v_";"typCol_") ,\:/: string 1 + til n;
为列动态创建符号列表,因为在使用函数形式时列名需要它们。我首先创建一个 v_ 和 typCol_ 列表,最多为 n.
,\:/:
-> 加入每个左迭代器和每个右迭代器
https://code.kx.com/q/ref/maps/#each-left-and-each-right
这允许我将左侧的每个项目(“v_”;“typCol_”)与右侧的每个项目连接起来。
同样可以用交叉实现,但你必须用翻转和剪切来重组列表
flip n cut `$("v_";"typCol_") cross string 1 + til n
(,/) {?[x;();0b;`grpCol`v`typCol!`grpCol,y]}[df] each cls;
(,/)
-> 这是与 join 一起使用的迭代器。它采用第一个 table,将其连接到第二个,然后将其连接到第三个,依此类推。
https://code.kx.com/q/ref/over/
{?[x;();0b;`grpCol`v`typCol!`grpCol,y]}[df] each cls
// functional select
?[table; where; by; columns]
?[x; (); 0b; `grpCol`v`typCol!`grpCol,y]
这将创建一个 table 的列表,cls 变量中的每个列对 1。请注意,我没有像这样 {[x;y]}
那样在函数中明确声明 x 或 y。这是因为 x y 和 z 可以隐式使用,所以这个函数有或没有都有效。
这里的重要部分是最后一个参数(列)。对于函数式select,它是一个字典,其中列名作为键,列是什么作为值
e.g. `grpCol`v`typCol!`grpCol`v_1`typCol_1
-> 这是重命名每个 v 和 typCol,使它们相同,然后用 (,/) 将它们连接在一起。
有一个有用的关键字可以帮助计算函数形式 -> parse
parse"select Group, Value:V1, Type:Type_v1 from df"
0 ?
1 `df
2 ()
3 0b
4 (`Group`Value`Type)!`Group`V1`Type_v1
P:exec distinct typCol from df;
df:exec P#(typCol!v) by grpCol:grpCol from df;
此处概述了旋转:https://code.kx.com/q/kb/pivoting-tables/
它有效地 flips/rotates 了 table 的一段。它采用来自 typCol 的不同类型作为列,并使用 v 列作为每个对应的 typCol
的行
?[table; where; by; columns]
?[df;();0b;(`grpCol,raze P,'`$"typCol_",/:string 1 + til count P)!`grpCol,raze flip (P;enlist each P)]
再次查看函数 select 中的最后一个参数,即列。这是动态生成后的样子:
(`grpCol`t1`typCol_1`t2`typCol_2`t3`typCol_3)!(`grpCol;`t1;enlist `t1;`t2;enlist `t2;`t3;enlist `t3)
这是一种获取类型列的 hacky 方法,我 select 每个 t1 t2 t3 都有一个 typeCol_1 _2 _3,
`t1 = (column) `t1
`typCol_1 = enlist `t1 -> the enlist here tells kdb I want the value `t1 rather than the column
我正在研究根据值重塑 table 创建新列的问题。
我使用的示例与此处讨论的问题相同:
所以我有一个 table:
df:([]ID:1+til 5;
Group:1 1 2 2 2;
V1:10 + 2 * til 5;
Type_v1:`t1`t2`t1`t1`t2;
V2:3 0N 0N 7 8;
Type_v2:`t2```t3`t3);
ID Group V1 Type_v1 V2 Type_v2
------------------------------
1 1 10 t1 3 t2
2 1 12 t2
3 2 14 t1
4 2 16 t1 7 t3
5 2 18 t2 8 t3
目标是将其转换为按组和类型获取值的总和。请注意创建的新列。基本上 Type_v1 和 Type_v2 中的所有类型都用于为结果 table.
创建列# group v_1 type_1 v_2 type_2 v_3 type_3
#1: 1 10 t1 15 t2 NA <NA>
#2: 2 30 t1 18 t2 15 t3
我做了开头,但我无法转换 table 并创建新列。 当然,我也在尝试以动态方式创建所有列,因为手动输入 20k 列是不可能的。
df1:select Group, Value:V1, Type:Type_v1 from df;
df2:select Group, Value:V2, Type:Type_v2 from df;
tr:df1,df2;
tr:0!select sum Value by Group, Type from tr where Type <> ` ;
基本上我错过了相当于:
dcast(tmp, group ~ rowid(group), value.var = c("v", "type"))
感谢任何帮助和解释,
您遗漏的最后一块是枢轴:https://code.kx.com/q/kb/pivoting-tables/
q)P:exec distinct Type from tr
q)exec P#(Type!Value) by Group:Group from tr
Group| t1 t2 t3
-----| --------
1 | 10 15
2 | 30 18 15
它不能完全为您提供准确的输出,但枢轴是概念
您可以扩展 Terry 的枢轴以使用函数形式动态执行上述 select 部分。在此处查看更多详细信息:
https://code.kx.com/q/basics/funsql/
// Personally, I would try to stay clear of column names too similar to reserved keywords in kdb
df: `id`grpCol`v_1`typCol_1`v_2`typCol_2 xcol df;
{[df;n]
// dynamically create cols from 1 to n
cls:`$("v_";"typCol_"),\:/:string 1 + til n;
// functional form of select for each type/value col before joining together
df:(,/) {?[x;();0b;`grpCol`v`typCol!`grpCol,y]}[df] each cls;
// sum, then pivot
df:0!select sum v by grpCol, typCol from df where typCol <> `;
P:exec distinct typCol from df;
df:exec P#(typCol!v) by grpCol:grpCol from df;
// Type cols seem unnecessary but
// Can be done with another functional select
?[df;();0b;(`grpCol,raze P,'`$"typCol_",/:string 1 + til count P)!`grpCol,raze flip (P;enlist each P)]
}[df;2]
grpCol t1 typCol_1 t2 typCol_2 t3 typCol_3
1 10 t1 15 t2 0N t3
2 30 t1 18 t2 15 t3
编辑 - 下面更详细的细分:
cls:`$("v_";"typCol_") ,\:/: string 1 + til n;
为列动态创建符号列表,因为在使用函数形式时列名需要它们。我首先创建一个 v_ 和 typCol_ 列表,最多为 n.
,\:/:
-> 加入每个左迭代器和每个右迭代器
https://code.kx.com/q/ref/maps/#each-left-and-each-right
这允许我将左侧的每个项目(“v_”;“typCol_”)与右侧的每个项目连接起来。
同样可以用交叉实现,但你必须用翻转和剪切来重组列表
flip n cut `$("v_";"typCol_") cross string 1 + til n
(,/) {?[x;();0b;`grpCol`v`typCol!`grpCol,y]}[df] each cls;
(,/)
-> 这是与 join 一起使用的迭代器。它采用第一个 table,将其连接到第二个,然后将其连接到第三个,依此类推。
https://code.kx.com/q/ref/over/
{?[x;();0b;`grpCol`v`typCol!`grpCol,y]}[df] each cls
// functional select
?[table; where; by; columns]
?[x; (); 0b; `grpCol`v`typCol!`grpCol,y]
这将创建一个 table 的列表,cls 变量中的每个列对 1。请注意,我没有像这样 {[x;y]}
那样在函数中明确声明 x 或 y。这是因为 x y 和 z 可以隐式使用,所以这个函数有或没有都有效。
这里的重要部分是最后一个参数(列)。对于函数式select,它是一个字典,其中列名作为键,列是什么作为值
e.g. `grpCol`v`typCol!`grpCol`v_1`typCol_1
-> 这是重命名每个 v 和 typCol,使它们相同,然后用 (,/) 将它们连接在一起。
有一个有用的关键字可以帮助计算函数形式 -> parse
parse"select Group, Value:V1, Type:Type_v1 from df"
0 ?
1 `df
2 ()
3 0b
4 (`Group`Value`Type)!`Group`V1`Type_v1
P:exec distinct typCol from df;
df:exec P#(typCol!v) by grpCol:grpCol from df;
此处概述了旋转:https://code.kx.com/q/kb/pivoting-tables/
它有效地 flips/rotates 了 table 的一段。它采用来自 typCol 的不同类型作为列,并使用 v 列作为每个对应的 typCol
的行?[table; where; by; columns]
?[df;();0b;(`grpCol,raze P,'`$"typCol_",/:string 1 + til count P)!`grpCol,raze flip (P;enlist each P)]
再次查看函数 select 中的最后一个参数,即列。这是动态生成后的样子:
(`grpCol`t1`typCol_1`t2`typCol_2`t3`typCol_3)!(`grpCol;`t1;enlist `t1;`t2;enlist `t2;`t3;enlist `t3)
这是一种获取类型列的 hacky 方法,我 select 每个 t1 t2 t3 都有一个 typeCol_1 _2 _3,
`t1 = (column) `t1
`typCol_1 = enlist `t1 -> the enlist here tells kdb I want the value `t1 rather than the column