[英]Specific sorting to category by awk and bash
親愛的所有人,我有一個問題。
我有這樣的輸入:(第二列只是索引)
chr1 1 30
chr1 2 40.5
chr1 3 30.5
chr1 4 41
chr2 10 60
chr2 15 40.1
我想得到這個:
chr1 chr2
30 - 31 2 0
31 - 32 0 0
...
40 - 41 1 1 etc..
我需要將數據分類為每1組30到60。從輸入數據中,我計算出chr1的所有行,這些行包含在30-31類中,價格從$ 3起。 我有這段代碼,但是我不明白問題出在哪里:(循環有問題)
samtools view /home/filip/Desktop/AMrtin\ Hynek/54321Odfiltrovany.bam | awk '{ n=length($10); print $3,"\t",NR,"\t", gsub(/[GCCgcs]/,"",$10)/n;}' | awk '($3 <= 0.6 && $3 >= 0.3)' | awk '{print $1,"\t",$2,"\t",($3*100)}' > data.txt
for j in chr1 chr2 chr3 chr4 chr5 chr6 chr7 chr8 chr9 chr10 chr11 chr12 chr13 chr14 chr15 chr16 chr17 chr18 chr19 chr20 chr21 chr22
do
export $j
awk -v sop=$j '{if($1 == $sop) print $0}' data.txt |
awk '{d=int($3)
a[d]++
if (NR==1) {min=d}
min=(min>=d?d:min)
max=(max>d?max:d)}
END{for (i=min; i<=max; i++) print i, "-", i+1, a[i]+0}' ;
done
我通過幫助“ fedorqui”制作的部分代碼
首先,您可以使用:
for j in {1..22}; do
chrj="char$j"
# now you could use $chrj instead of $j in this loop
done
代替 :
for j in chr1 chr2 chr3 chr4 chr5 chr6 chr7 chr8 chr9 chr10 chr11 chr12 chr13 chr14 chr15 chr16 chr17 chr18 chr19 chr20 chr21 chr22 do # ... done
然后,您無需awk
和管道的調用倍增。 僅一個awk
就足夠了。
例如 :
... | awk '($3 <= 0.6 && $3 >= 0.3)' | awk '{print $1,"\\t",$2,"\\t",($3*100)}'
應該 :
awk '($3 <= 0.6 && $3 >= 0.3){print $1,"\t",$2,"\t",($3*100)}'
# or
awk '{if ($3 <= 0.6 && $3 >= 0.3){print $1,"\t",$2,"\t",($3*100)}}'
除此以外 :
export $j
這種export
的目的是什么?
我還沒有閱讀代碼中的所有內容,但目前必須進行許多優化!
使用awk
:
awk '
!($1 in chrs) { chr[++c] = $1 ; chrs[$1]++ }
{
val = int($3);
map[$1,val]++;
min = (NR==1?val:min>=val?val:min);
max = (max>val?max:val)
}
END {
printf "\t\t"
for (j=1; j<=c; j++) {
printf "%s%s", sep, chr[j]
sep = "\t"
}
print ""
for (i=min; i<=max; i++) {
printf "%d - %d\t", i, i+1
for (j=1; j<=c; j++) {
printf "\t%s", map[chr[j],i] + 0
}
print ""
}
}' file
chr1 chr2
30 - 31 2 0
31 - 32 0 0
32 - 33 0 0
...
38 - 39 0 0
39 - 40 0 0
40 - 41 1 1
41 - 42 1 0
42 - 43 0 0
...
59 - 60 0 0
60 - 61 0 1
chr
數組。 map
數組,該map
數組以其值作為計數的染色體和范圍處的索引之外,其余大部分都是您的代碼。 END
塊中,我們首先遍歷chr
數組並打印染色體 min
和max
變量創建一個循環,並從map
數組中打印值,該值在染色體和范圍處索引。 min
到max
所有數字。 如果您使用的是gawk,則應該可以使用。 有一個用於$ 1的過濾器,該過濾器應該處理您使用$ j進行的所有操作(除非您確實只需要chr1..chr22,在這種情況下仍然應該可以為其開發正則表達式)。
BEGIN {
for(i = 30; i <= 60; i++) {
rstring = i " - " i + 1;
rows[rstring] = 0;
}
}
$1 ~ /^chr[0-9][0-9]?$/ {
row = int($3) " - " int($3) + 1;
columns[$1] = 0;
rows[row] = 0;
data[row][$1] += 1;
rowwidth = length(row) > rowwidth ? length(row) : rowwidth;
colwidth = length($1) > colwidth ? length($1) : colwidth;
}
END {
rowheader = "%-" (rowwidth * 2) "s";
colheader = "%" colwidth "s\t";
dataformat = "%" int(colwidth / 2) "d\t";
asorti(columns, sortedcolumns);
asorti(rows, sortedrows);
printf rowheader, "";
for(c in sortedcolumns) printf "%s\t", sortedcolumns[c];
print "";
for(r in sortedrows) {
printf rowheader, sortedrows[r];
for(c in sortedcolumns)
printf dataformat, data[sortedrows[r]][sortedcolumns[c]];
print ""
}
}
使用gawk -f [scriptfile from above] < data.txt
運行它會產生類似以下內容:
chr1 chr2 30 - 31 2 0 31 - 32 0 0 . . . 39 - 40 0 0 40 - 41 1 1 41 - 42 1 0 42 - 43 0 0 . . . 59 - 60 0 0 60 - 61 0 1
如果要使用Perl,可以使用以下內容
perl -ane '
$h{$F[0]}{int $F[2]}++;
push @range, int $F[2];
}{
@range = sort @range;
print "\t\t", join "\t", sort { $a cmp $b } keys %h; print "\n";
for $i ($range[0] .. $range[-1]) {
print "$i - ", $i + 1, "\t\t";
print $h{$_}{$i} + 0, "\t" for sort { $a cmp $b } keys %h; print "\n"
}' file
輸出應該是這樣的
chr1 chr2
30 - 31 2 0
31 - 32 0 0
32 - 33 0 0
33 - 34 0 0
34 - 35 0 0
35 - 36 0 0
36 - 37 0 0
37 - 38 0 0
38 - 39 0 0
39 - 40 0 0
40 - 41 1 1
41 - 42 1 0
42 - 43 0 0
43 - 44 0 0
44 - 45 0 0
45 - 46 0 0
46 - 47 0 0
47 - 48 0 0
48 - 49 0 0
49 - 50 0 0
50 - 51 0 0
51 - 52 0 0
52 - 53 0 0
53 - 54 0 0
54 - 55 0 0
55 - 56 0 0
56 - 57 0 0
57 - 58 0 0
58 - 59 0 0
59 - 60 0 0
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.