[英]Convert column to matrix format using awk
我有一個列格式的網格數據文件:
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
頂部20.5 21.5 22.5
表示y,側面值表示x,內部值表示相應的網格值。
我在這里找到了一個類似的問題將3列文件轉換為矩陣格式,但腳本在我的情況下不起作用。
腳本是
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
以下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
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";
}
}
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)
for lines尊重(NR-1)%3==1)
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 為您當前的輸入數據調整了我的舊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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.