使用awk转换数据矩阵

时间:2014-11-05 13:08:16

标签: matrix awk transpose

是否可以将以下数据矩阵输入转置到所需的输出?

f1  x1  1.2
f1  x2  2.2
f1  x3  0
f2  x1  1.1 
f2  x2  1.2
f2  x3  3.3
f3  x1  2.3
f3  x2  4.4
f3  x3  0.1

输出

    f1  f2  f3
x1  1.2 1.1 2.3
x2  2.2 1.2 4.4
x3  0   3.3 0.1

2 个答案:

答案 0 :(得分:1)

这可以是一种方式:

awk '{a[$1,$2]=$3; col[$1]; row[$2]}
    END {printf "%s", FS
            for (c in col) printf "%s%s", c, FS; print "";
            for (r in row) { 
                printf "%s%s", r, FS
                for (c in col) printf "%s%s", a[c,r], FS
                print ""
            }
        }' file

这是非常具有描述性的,但仍然是:

  • 将数据存储在数组a[col, row]
  • 存储cols和行的可能名称。

读取文件后,循环显示结果并打印。

对于给定的输入,它返回:

$ awk '{a[$1,$2]=$3; col[$1]; row[$2]} END {printf "%s", FS; for (c in col) printf "%s%s", c, FS; print ""; for (r in row) { printf "%s%s", r, FS; for (c in col) printf "%s%s", a[c,r], FS; print ""}}' a
f1 f2 f3 
x1 1.2 1.1 2.3 
x2 2.2 1.2 4.4 
x3 0 3.3 0.1 

答案 1 :(得分:0)

% cat mat.rix 
f1  x1  1.2
f1  x2  2.2
f1  x3  0
f2  x1  1.1 
f2  x2  1.2
f2  x3  3.3
f3  x1  2.3
f3  x2  4.4
f3  x3  0.1
% cat a.wk
{
  if(! row[$1]) { i=i+1; rowname[i]=$1; row[$1]=1 }
  if(! col[$2]) { j=j+1; colname[j]=$2; col[$2]=1 }
  if(c[$2])
     c[$2] = sprintf("%s%s%10.4f", c[$2], OFS, $3)
  else
     c[$2] = sprintf("%10.4f", $3)
}
END {
  printf "   "
  for(n=1;n<i+1;n++){ printf "%10s%s", rowname[n], OFS } ; print ""
  for(n=1;n<j+1;n++){ print colname[n], c[colname[n]] }}
% awk -f a.wk mat.rix 
           f1         f2         f3 
x1     1.2000     1.1000     2.3000
x2     2.2000     1.2000     4.4000
x3     0.0000     3.3000     0.1000
% 

附录

如果列名称的长度不同,该怎么办?

% cat aw.k
{
  if(! row[$1]) { i=i+1; rowname[i]=$1; row[$1]=1 }
  if(! col[$2]) { j=j+1; colname[j]=$2; col[$2]=1 }
  if(c[$2])
     c[$2] = sprintf("%s%s%10.4f", c[$2], OFS, $3)
  else
     c[$2] = sprintf("%10.4f", $3)
}
END {
  for(n=1;n<j+1;n++){l = length(colname[n]) ; if(l>lmax) lmax=l}
  format = sprintf("%%-%ds%%s%%s\n", lmax)
  for(n=1;n<lmax+1;n++) printf "."; printf OFS
  for(n=1;n<i+1;n++){ printf "%10s%s", rowname[n], OFS } ; print ""
  for(n=1;n<j+1;n++){ printf(format, colname[n], OFS, c[colname[n]])}
}
% awk -f aw.k mat.rix 
..         f1         f2         f3 
x1     1.2000     1.1000     2.3000
x2     2.2000     1.2000     4.4000
x3     0.0000     3.3000     0.1000
% 

使用%%

构建format时,请考虑使用sprintf