如何在Terminal Linux中将列转换为行?但更复杂

时间:2016-07-12 10:38:38

标签: linux fedora google-genomics bigdata

如何在Terminal Linux中将列转换为行?但更复杂......以下是我的数据示例:

SNP_Name        ID_Animal        Allele        Chr        Position
rs01            215               AB            1            100
rs02            215               AA            2            200
rs03            215               BA            3            300
rs04            215               AA            4            400
rs01            300               AB            1            100
rs02            300               BB            2            200
rs03            300               AA            3            300
rs04            300               AB            4            400
rs01            666               BB            1            100
rs02            666               AA            2            200
rs03            666               AB            3            300
rs04            666               AB            4            400

我想将其转换为以下内容:

SNP_Name     Chr     Position   215(ID_animal)  300(ID_Animal) 666(ID_Animal)
rs01         1       100        AB              AB            BB
rs02         2       200        AA              BB            AA
rs03         3       300        BA              AA            AB
rs04         4       400        AA              AB            AB

ID_animal在具有相应等位基因的列中发生变化。我是怎么做到的 但是每ID_animal我将重复55,000次。所以,我希望列只有55,000行和(动物number + SNP_Name + Chr + Position)列。

谢谢。

1 个答案:

答案 0 :(得分:1)

这里的问题是数据量,我不想提供一个解决方案,将所有内容读入内存然后输出。

为此,我想依次解析并输出每个SNP(rs数字)的数据,而不是每个动物。但数据是以错误的顺序提供给我们的(按动物分类)。

因此,我们需要做的第一件事是按SNP(第一列)对数据进行排序。我还将同时删除标题行,因为数据转换不需要它。

我假设数据存储在文件data.in中:

$ sed '1d' data.in | sort -o data.tmp

我们现在有:

$ cat data.tmp
rs01            215               AB            1            100
rs01            300               AB            1            100
rs01            666               BB            1            100
rs02            215               AA            2            200
rs02            300               BB            2            200
rs02            666               AA            2            200
rs03            215               BA            3            300
rs03            300               AA            3            300
rs03            666               AB            3            300
rs04            215               AA            4            400
rs04            300               AB            4            400
rs04            666               AB            4            400

然后我运行以下命令来产生结果:

$ awk -f script.awk data.tmp >data.new

awk脚本很长,因此将它放在自己的脚本文件中而不是“单行”中是有意义的:

FNR == 1    {
    # at first line of input

    rsid        = $1;
    chr         = $4;
    pos         = $5;

    c           = 0;
    aid[c]      = $2; # animal ID
    all[c++]    = $3; # allele

    do_header   = 1;  # output header when done parsing this SNP

    next;
}

rsid == $1 {
    # still reading animal ID/allele for this SNP
    aid[c]      = $2;
    all[c++]    = $3;
    next;
}

{
    if (do_header) {
        # output header

        printf("SNP_name\tChr\tPosition\t");
        for (c in aid) {
            printf("%d\t", aid[c]);
        }
        printf("\n");

        do_header = 0;
    }

    # output line with data from previous SNP    
    printf("%s\t%d\t%d\t", rsid, chr, pos);
    for (c in all) {
        printf("%s\t", all[c]);
    }
    printf("\n");

    # store data for this SNP
    rsid        = $1;
    chr         = $4;
    pos         = $5;

    c           = 0;
    aid[c]      = $2;
    all[c++]    = $3;
}

END {
    # output line for last SNP

    printf("%s\t%d\t%d\t", rsid, chr, pos);
    for (c in all) {
        printf("%s\t", all[c]);
    }
    printf("\n");
}

对于给定的输入,这会生成带有以下内容的制表符分隔文件data.new

SNP_name    Chr Position    215 300 666
rs01    1   100 AB  AB  BB
rs02    2   200 AA  BB  AA
rs03    3   300 BA  AA  AB
rs04    4   400 AA  AB  AB

注意:此要求对所有动物进行基因分型以获得完全相同的SNP。每个SNP都需要相同的动物ID。没有例外。