0

如何在终端 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随相应等位基因发生变化。我该怎么做?但我将使用 55,000 次重复ID_animal。所以,我只想成为 55,000 行和(动物++ numberSNP_Name的列。ChrPosition

谢谢你。

4

1 回答 1

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。没有例外。

于 2016-07-13T12:51:41.593 回答