一组重复行的总和,如果不重复则加 1 并计算差值
Sum of a block of duplicated rows, if not duplicated add 1 and calculate difference
我需要解析几个具有以下结构的排序文件:
1_0.91 10
1_0.91 20
1_0.91 30
1_0.91 40
2_0.89 50
1_0.91 60
1_0.91 70
1_0.91 80
2_0.89 90
2_0.89 100
2_0.89 110
3_0.86 120
第一列是基因组中的特征,第二列是它们的位置。每个特征都与其他特征间隔开。我想找到每个功能的大小或每个功能的块。对于这个例子,我想要的输出如下:
1_0.91 10 40 30
2_0.89 50 51 1
1_0.91 60 80 20
2_0.89 90 110 20
3_0.86 120 121 1
要素 1_0.91 从 10 开始,位于位置 20、30 和 40。我想创建一个包含开始和结束的新列。在本例中,从 10 开始到 40 结束。然后在新列中输出它们的大小(结束减去开始,在本例中为 30)。有几个地方我每个功能只有一次。在我的示例中,2_0.89 位于特征块 1_0.91 之间。在这种情况下,我想将 1 添加到当前值并估计大小,在这种情况下,等于 1。
我尝试过使用 awk,但我对只出现一次的功能感到困惑。
这是我目前使用的。有点绕:
让我们调用第一个文件 file1.txt:
cat file1.txt | awk '!=prev{if (pline){print pline;}print;}{prev=;pline=[=12=];}END{print pline;}' > file2.txt
输出:
1_0.91 10
1_0.91 40
2_0.89 50
2_0.89 50
1_0.91 60
1_0.91 80
2_0.89 90
2_0.89 110
3_0.86 120
3_0.86 120
现在,我使用 sed 打印奇数行和偶数行,然后使用粘贴将文件放在一起:
paste <(cat file2.txt | sed 'n; d') <(cat file2.txt | sed '1d; n; d' ) | awk 'BEGIN{OFS="\t"} {print ,,}' > file3.txt
输出:
1_0.91 10 40
2_0.89 50 50
1_0.91 60 80
2_0.89 90 110
3_0.86 120 120
接下来,我估算每个特征的大小:
cat file3.txt | awk 'BEGIN{OFS="\t"} {print ,,,-}' > file4.txt
输出:
1_0.91 10 40 30
2_0.89 50 50 0
1_0.91 60 80 20
2_0.89 90 110 20
3_0.86 120 120 0
接下来,我用 1 替换第 4 列中的零:
cat file4.txt | awk 'BEGIN{OFS="\t"} { = ( == "0" ? 1 : ) } 1' > file5.txt
输出:
1_0.91 10 40 30
2_0.89 50 50 1
1_0.91 60 80 20
2_0.89 90 110 20
3_0.86 120 120 1
最后,我用awk修复了每个特性的结尾:
cat file5.txt | awk 'BEGIN{OFS="\t"} { = ( == ? +1 : ) } 1' > file6.txt
输出:
1_0.91 10 40 30
2_0.89 50 51 1
1_0.91 60 80 20
2_0.89 90 110 20
3_0.86 120 121 1
我想知道是否有更快更简单的方法来做到这一点。
谢谢。
假设:
- 具有相同特征(字段#1)的连续行按位置(字段#2)升序排序
- input/output 字段分隔符是
\t
- 位置(字段 #2)值始终为正整数(否则我们可以调整代码)
一个awk
想法:
awk '
function print_feature() {
if ( feature != "" )
print feature,min,max,(max-min)
}
BEGIN { FS=OFS="\t" }
!= feature { print_feature() # row contains a new/different feature, so print previous feature details
feature=
min=
max=min+1
next
}
{ max= } # row contains a repeated/duplicate feature
END { print_feature() } # flush last feature details to stdout
' feature.dat
这会生成:
1_0.91 10 40 30
2_0.89 50 51 1
1_0.91 60 80 20
2_0.89 90 110 20
3_0.86 120 121 1
我需要解析几个具有以下结构的排序文件:
1_0.91 10
1_0.91 20
1_0.91 30
1_0.91 40
2_0.89 50
1_0.91 60
1_0.91 70
1_0.91 80
2_0.89 90
2_0.89 100
2_0.89 110
3_0.86 120
第一列是基因组中的特征,第二列是它们的位置。每个特征都与其他特征间隔开。我想找到每个功能的大小或每个功能的块。对于这个例子,我想要的输出如下:
1_0.91 10 40 30
2_0.89 50 51 1
1_0.91 60 80 20
2_0.89 90 110 20
3_0.86 120 121 1
要素 1_0.91 从 10 开始,位于位置 20、30 和 40。我想创建一个包含开始和结束的新列。在本例中,从 10 开始到 40 结束。然后在新列中输出它们的大小(结束减去开始,在本例中为 30)。有几个地方我每个功能只有一次。在我的示例中,2_0.89 位于特征块 1_0.91 之间。在这种情况下,我想将 1 添加到当前值并估计大小,在这种情况下,等于 1。
我尝试过使用 awk,但我对只出现一次的功能感到困惑。
这是我目前使用的。有点绕: 让我们调用第一个文件 file1.txt:
cat file1.txt | awk '!=prev{if (pline){print pline;}print;}{prev=;pline=[=12=];}END{print pline;}' > file2.txt
输出:
1_0.91 10
1_0.91 40
2_0.89 50
2_0.89 50
1_0.91 60
1_0.91 80
2_0.89 90
2_0.89 110
3_0.86 120
3_0.86 120
现在,我使用 sed 打印奇数行和偶数行,然后使用粘贴将文件放在一起:
paste <(cat file2.txt | sed 'n; d') <(cat file2.txt | sed '1d; n; d' ) | awk 'BEGIN{OFS="\t"} {print ,,}' > file3.txt
输出:
1_0.91 10 40
2_0.89 50 50
1_0.91 60 80
2_0.89 90 110
3_0.86 120 120
接下来,我估算每个特征的大小:
cat file3.txt | awk 'BEGIN{OFS="\t"} {print ,,,-}' > file4.txt
输出:
1_0.91 10 40 30
2_0.89 50 50 0
1_0.91 60 80 20
2_0.89 90 110 20
3_0.86 120 120 0
接下来,我用 1 替换第 4 列中的零:
cat file4.txt | awk 'BEGIN{OFS="\t"} { = ( == "0" ? 1 : ) } 1' > file5.txt
输出:
1_0.91 10 40 30
2_0.89 50 50 1
1_0.91 60 80 20
2_0.89 90 110 20
3_0.86 120 120 1
最后,我用awk修复了每个特性的结尾:
cat file5.txt | awk 'BEGIN{OFS="\t"} { = ( == ? +1 : ) } 1' > file6.txt
输出:
1_0.91 10 40 30
2_0.89 50 51 1
1_0.91 60 80 20
2_0.89 90 110 20
3_0.86 120 121 1
我想知道是否有更快更简单的方法来做到这一点。 谢谢。
假设:
- 具有相同特征(字段#1)的连续行按位置(字段#2)升序排序
- input/output 字段分隔符是
\t
- 位置(字段 #2)值始终为正整数(否则我们可以调整代码)
一个awk
想法:
awk '
function print_feature() {
if ( feature != "" )
print feature,min,max,(max-min)
}
BEGIN { FS=OFS="\t" }
!= feature { print_feature() # row contains a new/different feature, so print previous feature details
feature=
min=
max=min+1
next
}
{ max= } # row contains a repeated/duplicate feature
END { print_feature() } # flush last feature details to stdout
' feature.dat
这会生成:
1_0.91 10 40 30
2_0.89 50 51 1
1_0.91 60 80 20
2_0.89 90 110 20
3_0.86 120 121 1