计算子串中特定字符的数量

时间:2018-02-13 12:27:15

标签: r string awk

我有一个8040行的文件,有两列,第二列有可变长度的字符串,范围从30000到200000个字符(DNA序列)。 [以下是150个字符的样本]

X:100670000-101060000    TTCCCCAAACAGCAACTTTAAGGAGCAGCTTCCTTTATGATCCCTGATTGCCTCCCCTTTGTTCCCATAACAAGTAGTTTAAATTTTCTGTTAAAGTCCAAACCACATATTTACAATACCTCGCACC

根据第二列上每个字符串的长度,我想将每个字符串分成10个字符串(字符串长度的10%),计算每个字段的G和C的数量,然后得到G和C的百分比。

例如,如果我的第二列的第一个条目长度为39000个字符,则每个段的长度为3900个字符,代码将计算每个段中G和C的出现次数,添加它们,并除以39000在这种情况下,获得百分比。

我尝试在 AWK 中写这个,但它不起作用。我得到的输出是完整的字符串,而不是段:

awk '{
bp_length[$2]= length($2);
bin_size[$2]= bp_length[$2]*0.1;

for(i=1;i<=bp_length[$2];i+=bin_size[$2]){
print gsub("G", "G")"\t"gsub("C", "C")}

}'

我将此作为输出:

79060 76624

如果输出可以在包含10列的表中表示,并且每列代表每行的10个段,那么在 R 中解决此问题会更容易吗?

2 个答案:

答案 0 :(得分:4)

由于您尝试在awk进行此练习,我会给您一个awk计划

此示例显示拆分和计数正确完成:

awk '{l=length($2); binsize=int(l/10) + (l%10!=0)
       for(i=1;i<=l;i+=binsize) {
          str=substr($2,i,binsize)
          print str, gsub("G","",str), gsub("C","",str)
       }
     }' <file>

给我们输出

TTCCCCAAACAGC 1 6
AACTTTAAGGAGC 3 2
AGCTTCCTTTATG 2 3
ATCCCTGATTGCC 2 5
TCCCCTTTGTTCC 1 6
CATAACAAGTAGT 2 2
TTAAATTTTCTGT 1 1
TAAAGTCCAAACC 1 4
ACATATTTACAAT 0 2
ACCTCGCACC 1 6

所以,为了获得百分比:

awk '{ l=length($2); binsize=int(l/10) + (l%10!=0)
       printf "%-24s (length: %7d, binsize: %7d, lastbin: %7d)\n",$1,l,binsize,l%binsize
       j=1;
       for(i=1;i<=l;i+=binsize) {
         str=substr($2,i,binsize)
         printf "segment %0.3d : %6.3f (%%G) %6.3f (%%C)\n", j++,100*gsub("G","",str)/l, 100*gsub("C","",str)/l
       }
     }' <file>

,输出为:

X:100670000-101060000    (length:     127, binsize:      13, lastbin:      10)
segment 001 :  0.787 (%G)  4.724 (%C)
segment 002 :  2.362 (%G)  1.575 (%C)
segment 003 :  1.575 (%G)  2.362 (%C)
segment 004 :  1.575 (%G)  3.937 (%C)
segment 005 :  0.787 (%G)  4.724 (%C)
segment 006 :  1.575 (%G)  1.575 (%C)
segment 007 :  0.787 (%G)  0.787 (%C)
segment 008 :  0.787 (%G)  3.150 (%C)
segment 009 :  0.000 (%G)  1.575 (%C)
segment 010 :  0.787 (%G)  4.724 (%C)

答案 1 :(得分:2)

你可以这样做:

# string of length 39000
test <- paste(rep(LETTERS, 1500), collapse = "")

# divide string into 10 equal parts
test2 <- sapply(seq(1, nchar(test), nchar(test)/10), function(x) substr(test, x, x + nchar(test)/10 - 1))

# use str_count from stringr-package to count characters and calculate percentage
library(stringr)
(str_count(test2, "G") + str_count(test2, "C")) / nchar(test) * 100

编辑新请求:

if未向量化,因此您无法使用它来处理向量bins(在我的示例中为test2)。

相反,请将sapplyifelse结合使用。这样,它将遍历十个部分,并在str_count("N") < 10 percentNA的情况下输出计算。代码:

X <- sapply(test2, function(x) ifelse(str_count(x, c("N")) < .1*nchar(x), 
                                 (str_count(x, "G") + str_count(x, "C")) / nchar(x) * 100, NA))
names(X) <- seq_along(X)

> X
       1        2        3        4        5        6        7        8        9       10 
7.692308 7.692308 7.692308 7.692308 7.692308 7.692308 7.692308 7.692308 7.692308 7.692308