如何在终端 Linux 中将列转换为行?但更复杂
How to transform column to row in Terminal Linux? But more complex
如何在终端 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 行和 (animal number
+SNP_Name
+Chr
+Position
) 的列。
谢谢。
这里的问题是数据量,我不想给出一个全部读入内存然后输出的方案
为此,我想依次解析和输出每个 SNP(rs
个数字)的数据,而不是依次为每个动物解析和输出数据。但是数据以错误的顺序提供给我们(按动物排序)。
所以我们要做的第一件事就是按照SNP(第一列)对数据进行排序。我还将同时删除 header 行,因为数据转换不需要它。
我假设数据存储在文件 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
脚本很长,所以将它放在自己的脚本文件中而不是作为 "one-liner":
是有意义的
FNR == 1 {
# at first line of input
rsid = ;
chr = ;
pos = ;
c = 0;
aid[c] = ; # animal ID
all[c++] = ; # allele
do_header = 1; # output header when done parsing this SNP
next;
}
rsid == {
# still reading animal ID/allele for this SNP
aid[c] = ;
all[c++] = ;
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 = ;
chr = ;
pos = ;
c = 0;
aid[c] = ;
all[c++] = ;
}
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");
}
对于给定的输入,这将生成具有以下内容的 tab-delimited 文件 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。没有例外。
如何在终端 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 行和 (animal number
+SNP_Name
+Chr
+Position
) 的列。
谢谢。
这里的问题是数据量,我不想给出一个全部读入内存然后输出的方案
为此,我想依次解析和输出每个 SNP(rs
个数字)的数据,而不是依次为每个动物解析和输出数据。但是数据以错误的顺序提供给我们(按动物排序)。
所以我们要做的第一件事就是按照SNP(第一列)对数据进行排序。我还将同时删除 header 行,因为数据转换不需要它。
我假设数据存储在文件 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
脚本很长,所以将它放在自己的脚本文件中而不是作为 "one-liner":
FNR == 1 {
# at first line of input
rsid = ;
chr = ;
pos = ;
c = 0;
aid[c] = ; # animal ID
all[c++] = ; # allele
do_header = 1; # output header when done parsing this SNP
next;
}
rsid == {
# still reading animal ID/allele for this SNP
aid[c] = ;
all[c++] = ;
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 = ;
chr = ;
pos = ;
c = 0;
aid[c] = ;
all[c++] = ;
}
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");
}
对于给定的输入,这将生成具有以下内容的 tab-delimited 文件 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。没有例外。