Matrix awk距离矩阵

Matrix awk距离矩阵,matrix,awk,distance,Matrix,Awk,Distance,我想在工作上得到一些帮助,但我真的不知道如何去做。我必须从一个3列文本中创建一个距离矩阵,如下所示: AN51 AN50 88 AN52 AN50 167 AN52 AN51 125 AN53 AN50 81 AN53 AN51 93 AN53 AN52 170 AN54 AN50 120 AN54 AN51 119 AN54 AN52 117 AN54 AN53 66 输出必须是方形形状的“2d”矩阵 我试着从文件中读取$0,它最终读取了所有字段,但对齐方式不同。awk' awk ' {

我想在工作上得到一些帮助,但我真的不知道如何去做。我必须从一个3列文本中创建一个距离矩阵,如下所示:

AN51 AN50 88
AN52 AN50 167
AN52 AN51 125
AN53 AN50 81
AN53 AN51 93
AN53 AN52 170
AN54 AN50 120
AN54 AN51 119
AN54 AN52 117
AN54 AN53 66 
输出必须是方形形状的“2d”矩阵

我试着从文件中读取$0,它最终读取了所有字段,但对齐方式不同。

awk'
awk '
{ 
  matrix[$1,$2] = $3
  matrix[$2,$1] = $3 
} 
END { 
  printf("\tAN50\tAN51\tAN52\tAN53\n")
  for (n=0;n<4;n++) { 
    printf("AN5%d\t", n)
    for (m=0; m<4; m++) { 
      printf("%d\t", matrix["AN5"n,"AN5"m]) 
    } 
    printf("\n") 
  } 
}'
{ 矩阵[$1,$2]=$3 矩阵[$2,$1]=$3 } 结束{ printf(“\tAN50\tAN51\tAN52\tAN53\n”) 对于(n=0;n
awk'
{ 
矩阵[$1,$2]=$3
矩阵[$2,$1]=$3
} 
结束{
printf(“\tAN50\tAN51\tAN52\tAN53\n”)

对于(n=0;n来说,这是迈克尔·巴伯答案的一个更一般的版本,它通常适用于任意数量的列和行

awk '
BEGIN {
    OFS = "\t"
}
{
    matrix[$1,$2] = $3
    matrix[$2,$1] = $3
    names[$1] = $1
    names[$2] = $2
}
END {
    num = asort(names)
    for (i = 1; i <= num; i++) {
        printf("%s%s", OFS, names[i])
    }
    printf("\n")
    for (i = 1; i <= num; i++) {
        printf("%s", names[i])
        for (j = 1; j <= num; j++) {
            printf("%s%4d", OFS, matrix[names[i], names[j]])
        }
        printf("\n")
    }
}'
请注意,您的示例输入数据会产生我所展示的输出,其中包含完整的数据。还请注意,Michael的答案只输出您的示例输出中包含的不完整的数据

编辑:

这里有一个版本不需要
asort()
,应该可以在AWK的非GNU版本上使用:

awk '
BEGIN {
    OFS = "\t"
}
{
    matrix[$1,$2] = $3
    matrix[$2,$1] = $3
    names[$1] = $1
    names[$2] = $2
}
END {
    for (i in names) {
        printf("%s%s", OFS, i)
    }
    printf("\n")
    for (i in names) {
        printf("%s", i)
        for (j in names) {
            printf("%s%4d", OFS, matrix[i,j])
        }
        printf("\n")
    }
}'

它将以不可预测的顺序打印姓名。

这是迈克尔·巴伯答案的一个更一般的版本,它通常适用于任意数量的列和行

awk '
BEGIN {
    OFS = "\t"
}
{
    matrix[$1,$2] = $3
    matrix[$2,$1] = $3
    names[$1] = $1
    names[$2] = $2
}
END {
    num = asort(names)
    for (i = 1; i <= num; i++) {
        printf("%s%s", OFS, names[i])
    }
    printf("\n")
    for (i = 1; i <= num; i++) {
        printf("%s", names[i])
        for (j = 1; j <= num; j++) {
            printf("%s%4d", OFS, matrix[names[i], names[j]])
        }
        printf("\n")
    }
}'
请注意,您的示例输入数据会产生我所展示的输出,其中包含完整的数据。还请注意,Michael的答案只输出您的示例输出中包含的不完整的数据

编辑:

这里有一个版本不需要
asort()
,应该可以在AWK的非GNU版本上使用:

awk '
BEGIN {
    OFS = "\t"
}
{
    matrix[$1,$2] = $3
    matrix[$2,$1] = $3
    names[$1] = $1
    names[$2] = $2
}
END {
    for (i in names) {
        printf("%s%s", OFS, i)
    }
    printf("\n")
    for (i in names) {
        printf("%s", i)
        for (j in names) {
            printf("%s%4d", OFS, matrix[i,j])
        }
        printf("\n")
    }
}'

它将以不可预测的顺序打印名称。

唯一的问题是它现在写的是“从未定义过函数排序”@Jánosballázs:AWK的哪个版本?请注意,它应该是“asort”(带有“a”)。如果您的版本不包括
asort()
函数,那么您可以做的一件事就是更改行
num=asort(名称)
to
for(i in names){num++}
(因为您的
length()
函数可能不接受数组作为参数。这应该可以工作,但名称不会以可预测的顺序输出。不幸的是,
asort()
是特定于GNU AWK(
gawk
)的。janosbalázs:您需要做一些更改(不仅仅是我之前评论中的版本)。我会尽快发布另一个版本。唯一的问题是它现在写的是“函数排序从未定义”@JánosBalázs:AWK的哪个版本?请注意它应该是“asort”(带“a”)。如果你的版本不包括
asort()
函数,您可以做的一件事是将
num=asort(names)
行更改为
for(i in names){num++}
(因为您的
length()
函数可能不接受数组作为参数。这应该可行,但名称不会以可预测的顺序输出。不幸的是,
asort()
特定于GNU AWK(
gawk
)。@JánosBalázs:您需要做一些更改(不仅仅是我之前评论中的更改)。我会尽快发布另一个版本。