【问题标题】:Convert a 3 column file to matrix format将 3 列文件转换为矩阵格式
【发布时间】:2017-05-26 09:13:16
【问题描述】:

我有一个文件格式,如下例所示,显示了包括他们自己在内的 5 个人之间的关系。

1   1   1.0
2   1   0.5
3   1   0.1
4   1   0.3
5   1   0.1
2   2   1.0
3   2   0.5
4   2   0.2
5   2   0.3
3   3   1.0
4   3   0.5
5   3   0.3
4   4   1.0
5   4   0.1
5   5   1.0

我想使用 AWK 将其转换为完整的矩阵格式。我需要像示例中那样对行和列进行数字排序。

    1   2   3   4   5
1   1.0 0.5 0.1 0.3 0.1
2   0.5 1.0 0.5 0.2 0.3
3   0.1 0.5 1.0 0.5 0.3
4   0.3 0.2 0.5 1.0 0.1
5   0.1 0.3 0.3 0.1 1.0

我遇到了以前的线程(如下),但输入文件的格式略有不同,我正在努力调整它。 http://www.unix.com/shell-programming-and-scripting/203483-how-rearrange-matrix-awk.html

我该如何进行这种转换?

【问题讨论】:

  • AE 的键是否代表您真实数据中的键?是否要求它们在输出中按字母顺序排序?
  • A 到 E 的实际值是数字(10 到 13 位),是的,它们需要按数字排序
  • 好的,这是有用的信息,所以它应该进入你的问题。 edit 也可能更新您的示例,因此使用数字而不是字母(它们显然不必包含这么多数字!)。
  • 排序数字会破坏你的字母顺序A B C D E,所以应该排序字母,而不是数字(以获得矩阵)
  • 在你上次编辑后,输入输出变得不可读

标签: awk


【解决方案1】:

我们开始吧,gawk 解决方案:

matrixize.awk 脚本:

#!/bin/awk -f
BEGIN { OFS="\t" }     # output field separator
{
    b[$1];             # accumulating unique indices
    if ($1 != $2) {   
        a[$2][$1] = $3 # set `diagonal` relation between different indices 
    } 
    a[$1][$2] = $3     # multidimensional array (reflects relation `one-to-many`)
}
END {
    asorti(b); h = "";  # sort unique indices
    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

输出:

    1   2   3   4   5
1   1.0 0.5 0.1 0.3 0.1
2   0.5 1.0 0.5 0.2 0.3
3   0.1 0.5 1.0 0.5 0.3
4   0.3 0.2 0.5 1.0 0.1
5   0.1 0.3 0.3 0.1 1.0

【讨论】:

  • 您好,谢谢。它运行了,但我似乎得到了与你所拥有的不同的 ID 顺序?输入文件是按您指定的制表符分隔的。 4 5 1 2 3 4 1.0 0.1 0.3 0.2 0.5 5 0.1 1.0 0.1 0.3 0.3 1 0.3 0.1 1.0 0.5 0.1 2 0.2 0.3 0.5 1.0 0.5 3 0.5 0.3 0.1 0.5 1.0
  • @roddy,我已经按原样使用了您问题的输入。而且我正在获得预期的输出(作为您想要的输出)。检查您的文件是否有前导空格/制表符(在第一列之前)
【解决方案2】:

由于上下三角形相同,将每个元素对复制到多维数组中的两个索引是否不够,例如:

parse.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"
  }
}

运行:

awk -f parse infile

输出:

1.0 0.5 0.1 0.3 0.1 
0.5 1.0 0.5 0.2 0.3 
0.1 0.5 1.0 0.5 0.3 
0.3 0.2 0.5 1.0 0.1 
0.1 0.3 0.3 0.1 1.0

注意,这假设最后一行包含最大的索引。

【讨论】:

  • 雷神,上下相同,我可以使用任何一种方法。我现在将在一个大文件(9,000 x 9,000)上测试它们,看看哪个更快。像往常一样感谢大家的帮助。
  • 在我的真实数据集上测试了代码后,它看起来需要将 id 的编号从 1 向上排列。
  • 嗨,在真实数据集上测试了代码后,看起来它需要从 1 开始的 id 编号。我的真实身份证从 8 位以上的数字开始,即 62243121 。我将如何重新编号第 1 列和第 2 列以从 1 开始,但确保第 1 列中相同 id 的重新编号与第 2 列中的相同?再次感谢,罗迪
  • @roddy:我没有满足你的要求。我认为您应该发布一个与您的实际数据更好的输入/输出对应的新问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-07-24
  • 1970-01-01
  • 1970-01-01
  • 2021-12-04
  • 2017-06-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多