我有一个列格式的网格化数据文件:
ifile.txt
x y value
20.5 20.5 -4.1
21.5 20.5 -6.2
22.5 20.5 0.0
20.5 21.5 1.2
21.5 21.5 4.3
22.5 21.5 6.0
20.5 22.5 7.0
21.5 22.5 10.4
22.5 22.5 16.7
我想将其转换为矩阵格式:
ofile.txt
20.5 21.5 22.5
20.5 -4.1 1.2 7.0
21.5 -6.2 4.3 10.4
22.5 0.0 6.0 16.7
top 20.5 21.5 22.5
表示y,side值表示x,内部值表示相应的网格值。
我在Convert a 3 column file to matrix format找到了一个类似的问题,但脚本在我的情况下不起作用。
脚本是
awk '{ h[$1,$2] = h[$2,$1] = $3 }
END {
for(i=1; i<=$1; i++) {
for(j=1; j<=$2; j++)
printf h[i,j] OFS
printf "\n"
}
}' ifile
答案 0 :(得分:6)
以下awk
脚本处理:
这是以这种方式完成的:
awk '
BEGIN{PROCINFO["sorted_in"] = "@ind_num_asc"}
(NR==1){next}
{row[$1]=1;col[$2]=1;val[$1" "$2]=$3}
END { printf "%8s",""; for (j in col) { printf "%8.3f",j }; printf "\n"
for (i in row) {
printf "%8.3f",i; for (j in col) { printf "%8.3f",val[i" "j] }; printf "\n"
}
}' <file>
它是如何运作的:
PROCINFO["sorted_in"] = "@ind_num_asc"
,声明所有数组都按索引进行数字排序。(NR==1){next}
:跳过第一行{row[$1]=1;col[$2]=1;val[$1" "$2]=$3}
,通过存储行和列索引及附带的值来处理该行。输出:
20.500 21.500 22.500
20.500 -4.100 1.200 7.000
21.500 -6.200 4.300 10.400
22.500 0.000 6.000 16.700
注意: PROCINFO
的使用是gawk
功能。
但是,如果你做了几个假设,你可以做得更短:
您可以使用以下简短版本:
sort -g <file> | awk '($1+0!=$1){next}
($1!=o)&&(NR!=1){printf "\n"}
{printf "%8.3f",$3; o=$1 }'
输出
-4.100 1.200 7.000
-6.200 4.300 10.400
0.000 6.000 16.700
或转置:
awk '(NR==1){next}
($2!=o)&&(NR!=2){printf "\n"}
{printf "%8.3f",$3; o=$2 }' <file>
此输出
-4.100 -6.200 0.000
1.200 4.300 6.000
7.000 10.400 16.700
答案 1 :(得分:4)
Perl解决方案:
#!/usr/bin/perl -an
$h{ $F[0] }{ $F[1] } = $F[2] unless 1 == $.;
END {
@s = sort { $a <=> $b } keys %h;
print ' ' x 5;
printf '%5.1f' x @s, @s;
print "\n";
for my $u (@s) {
print "$u ";
printf '%5.1f', $h{$u}{$_} for @s;
print "\n";
}
}
答案 2 :(得分:3)
awk
解决方案:
sort -n ifile.txt | awk 'BEGIN{header="\t"}NR>1{if((NR-1)%3==1){header=header sprintf("%4.1f\t",$1); matrix=matrix sprintf("%4.1f\t",$1)}matrix= matrix sprintf("%4.1f\t",$3); if((NR-1)%3==0 && NR!=10)matrix=matrix "\n"}END{print header; print matrix}';
20.5 21.5 22.5
20.5 -4.1 1.2 7.0
21.5 -6.2 4.3 10.4
22.5 0.0 6.0 16.7
解释:
sort -n ifile.txt
以数字方式对文件进行排序header="\t"
,并且会附加必要的信息,这要归功于header=header sprintf("%4.1f\t",$1)
关于(NR-1)%3==1)
的行1} LI>
matrix
变量构建矩阵的方式相同:matrix=matrix sprintf("%4.1f\t",$1)
将创建第一列,
matrix= matrix sprintf("%4.1f\t",$3)
将使用内容填充矩阵,然后if((NR-1)%3==0 &&
NR!=10)matrix=matrix "\n"
将添加足够的EOL 答案 3 :(得分:3)
根据您当前的输入数据调整了我原来的GNU awk
解决方案:
matrixize.awk
脚本:
#!/bin/awk -f
BEGIN { PROCINFO["sorted_in"]="@ind_num_asc"; OFS="\t" }
NR==1{ next }
{
b[$1]; # accumulating unique indices
($1 != $2)? a[$1][$2] = $3 : a[$2][$1] = $3; # set `diagonal` relation between different indices
}
END {
h = "";
for (i in b) {
h = h OFS i # form header columns
}
print h; # print header column values
for (i in b) {
row = i; # index column
# iterating through the row values (for each intersection point)
for (j in a[i]) {
row = row OFS a[i][j]
}
print row
}
}
用法:
awk -f matrixize.awk yourfile
输出:
20.5 21.5 22.5
20.5 -4.1 1.2 7.0
21.5 -6.2 4.3 10.4
22.5 0.0 6.0 16.7