1

我想得到一些工作方面的帮助,但我真的不知道如何去做。我必须从一个 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”矩阵

    AN50  AN51  AN52 AN53
AN50 0     88   167   81
AN51 88    0    125   93
AN52 167   125   0    170
AN53 81    93   170    0

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

4

2 回答 2

3
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") 
  } 
}'
于 2012-04-28T14:11:29.773 回答
3

这是 Michael Barber 答案的更通用版本,通常适用于任意数量的列和行。

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")
    }
}'

示例输出:

        AN50    AN51    AN52    AN53    AN54
AN50       0      88     167      81     120
AN51      88       0     125      93     119
AN52     167     125       0     170     117
AN53      81      93     170       0      66
AN54     120     119     117      66       0

请注意,您的示例输入数据会产生我显示的输出,其中包含完整的数据。另请注意,迈克尔的回答仅输出您的示例输出包含的不完整内容。

编辑:

这是一个不需要asort()并且应该在非 GNU 版本的 AWK 上工作的版本:

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")
    }
}'

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

于 2012-04-28T15:48:54.473 回答