awk将一列转置为多个具有空值的未知列
awk to transpose one column into multiple unknown columns with empty values
您好,我希望能够将一列转置为未知数量的列,如下所示。
--Before
c1 c2 c3 typ val
----------
H2|f|1|AQ|2
H2|f|1|MP|1
H2|f|3|MX|1
H1|c|3|MP|1
H1|c|3|MX|1
--after desired
c1 c2 c3 AQ MP MX
---------
H2|f|1|2|1
H2|f|3|||1
H1|c|3||1|1
这是我的代码。它确实有效,但它会为 col1 col2 和 col3 的每个组合创建一行,即使这 3 列的特定组合没有关联值,如下所示。我可以简单地在最后删除空的,但我更担心这种方法的效率低下。
--output from my code with empty entries
c1 c2 c3 AQ MP MX
---------
H2|f|1|2|1
H2|c|1||
H2|c|3||
H1|c|1||
H1|f|1||
H1|f|3||
H2|f|3|||1
H1|c|3||1|1
awk -F\| '
NR>0 {
if(!( in ps)) { p[++types] = }; ps[]++
if(!( in es)) { e[++num1] = }; es[]++
if(!( in cs)) { c[++num2] = }; cs[]++
if(!( in ss)) { s[++num3] = }; ss[]++
map[,,,] =
}
END {
printf "%s;" ,"c1";
printf "%s;" ,"c2";
printf "%s;" ,"c3";
for(prc=1; prc<=types; prc++) {
printf "%s%s", sep, p[prc];
sep = ";"
}
print "";
sep = ";"
for(coun1=1; coun1<=num1; coun1++) {
for(coun2=1; coun2<=num2; coun2++) {
for(coun3=1; coun3<=num3; coun3++) {
printf "%s%s", sep, e[coun1]
printf "%s%s", sep, c[coun2]
printf "%s%s", sep, s[coun3]
for(val=0; val<=types; val++) {
printf "%s%s", sep, map[e[coun1],c[coun2],s[coun3], p[val]];
}
print ""
}
}
}
}' $workfile
像这样的东西会起作用
$ awk -F'|' 'NR<3 {ps[NR]=[=10=]}
NR>2 {k= FS FS ; h=; ks[k]; hs[h]; a[k,h]=}
END {split(ps[1],p," ");
printf "%s %s %s", p[1],p[2],p[3];
for(h in hs) printf " %s",h; print "\n"ps[2];
for(k in ks)
{printf "%s",k;
for(h in hs) printf "%s%s",FS,a[k,h]; print ""}}' file
c1 c2 c3 MP AQ MX
----------
H2|f|1|1|2|
H2|f|3|||1
H1|c|3|1||1
请注意,此方法不能保证列顺序,如果重要,则需要一些额外的簿记。此外,您的 header 字段分隔符与数据部分不匹配,似乎是一个需要处理的问题。
您好,我希望能够将一列转置为未知数量的列,如下所示。
--Before
c1 c2 c3 typ val
----------
H2|f|1|AQ|2
H2|f|1|MP|1
H2|f|3|MX|1
H1|c|3|MP|1
H1|c|3|MX|1
--after desired
c1 c2 c3 AQ MP MX
---------
H2|f|1|2|1
H2|f|3|||1
H1|c|3||1|1
这是我的代码。它确实有效,但它会为 col1 col2 和 col3 的每个组合创建一行,即使这 3 列的特定组合没有关联值,如下所示。我可以简单地在最后删除空的,但我更担心这种方法的效率低下。
--output from my code with empty entries
c1 c2 c3 AQ MP MX
---------
H2|f|1|2|1
H2|c|1||
H2|c|3||
H1|c|1||
H1|f|1||
H1|f|3||
H2|f|3|||1
H1|c|3||1|1
awk -F\| '
NR>0 {
if(!( in ps)) { p[++types] = }; ps[]++
if(!( in es)) { e[++num1] = }; es[]++
if(!( in cs)) { c[++num2] = }; cs[]++
if(!( in ss)) { s[++num3] = }; ss[]++
map[,,,] =
}
END {
printf "%s;" ,"c1";
printf "%s;" ,"c2";
printf "%s;" ,"c3";
for(prc=1; prc<=types; prc++) {
printf "%s%s", sep, p[prc];
sep = ";"
}
print "";
sep = ";"
for(coun1=1; coun1<=num1; coun1++) {
for(coun2=1; coun2<=num2; coun2++) {
for(coun3=1; coun3<=num3; coun3++) {
printf "%s%s", sep, e[coun1]
printf "%s%s", sep, c[coun2]
printf "%s%s", sep, s[coun3]
for(val=0; val<=types; val++) {
printf "%s%s", sep, map[e[coun1],c[coun2],s[coun3], p[val]];
}
print ""
}
}
}
}' $workfile
像这样的东西会起作用
$ awk -F'|' 'NR<3 {ps[NR]=[=10=]}
NR>2 {k= FS FS ; h=; ks[k]; hs[h]; a[k,h]=}
END {split(ps[1],p," ");
printf "%s %s %s", p[1],p[2],p[3];
for(h in hs) printf " %s",h; print "\n"ps[2];
for(k in ks)
{printf "%s",k;
for(h in hs) printf "%s%s",FS,a[k,h]; print ""}}' file
c1 c2 c3 MP AQ MX
----------
H2|f|1|1|2|
H2|f|3|||1
H1|c|3|1||1
请注意,此方法不能保证列顺序,如果重要,则需要一些额外的簿记。此外,您的 header 字段分隔符与数据部分不匹配,似乎是一个需要处理的问题。