求助效應成功案例之--如何去掉匹配字符後的一連串

劉小澤寫於2020.7.13
名詞解釋:“求助效應”——來自花花
意爲:當自己有一個問題想要問別人,但還沒得到他人答覆時,自己就會在等待期間自行探索,最終先於他人,自行解答成功

前言

今天早上想要統計一下ChIPseeker的peaks註釋結果,但是table一下看到下面的情況,本來就只是想看看有多少個exon,不想看這麼詳細。所以我想把Exon之後的字符串(ENSMU* 去掉再重新統計【當然這個問題也存在與intron中】

簡單嘗試了一下,發現不能成功匹配正則表達式,於是想着問問花花吧

五分鐘後,花花沒回復。。。

當然,期間我自己進行了不情願的嘗試
本來以爲是一個小問題而已,就不想動腦了。但事實證明還得靠自己搜索試錯解決

嘗試第一次

我搜索的條件是:r remove character from a pattern

結果就立刻找到了答案:https://stackoverflow.com/questions/11776287/remove-pattern-from-string-with-gsub

以爲加上這個參數就會匹配到

> head(table(gsub("\\(ENSMUST*", "", p$annotation,perl = T)))

                                  3' UTR                        Distal Intergenic 
                                       2                                       34 
Exon 00000003310.6/19386, exon 20 of 29)  Exon 00000005066.8/26395, exon 2 of 11) 
                                       1                                        1 
 Exon 00000005066.8/26395, exon 3 of 11)  Exon 00000005066.8/26395, exon 7 of 11) 
                                       1                                        1 

但事實是,這個依然只是去掉了(ENSMUST這一小部分,後面的沒去掉。

因此,這個參數加不加都一樣

嘗試第二次

我重新思考了一下正則表達式真的寫對了嗎?

我的需求是:匹配(ENSMUST後面的一串字符,但是我之前寫的是:(ENSMUST*

在正則表達式中,有這麼幾條常用的規定:

因此,看到這裏大家想必都明白了,我的表達式沒寫對

(ENSMUST* 只是表示:匹配前一個T字母出現多次或0次,它匹配到的其實是:ENSMUSTTTTTTT這樣的

最後確定,我少了一個.。看來真的是對正則表達式生疏了

好至此匹配的問題解決

再回到ChIPseeker這裏

其實之前在寫:一起學習一遍ChIPseeker的使用 這一篇的時候就提到了:

可以在peak註釋之前就設置好,省的下面再刪減字符串

註釋結果中的分類有下游(Downstream,默認範圍3kb)但沒有上游,這是因爲Promoter定義爲了轉錄起始位點(TSS)的上下游區域,包含了上游;另外這個下游是是基因間區的一部分,更確切是指緊接着基因的下游;這裏的上游和下游其實都是基因間區,獨立出來是因爲和基因直接連接,是很近的區域=》近端基因間區

當然,基因間區還包含更遠的間區(Distal intergenic)=》遠端基因間區

最後,如何實現批量操作

很多生信操作的最終目的都是方便批量處理,這裏的peaks註釋也不例外

比如我們可以簡單看一個peak註釋文件的類型統計,但是如果有幾十個呢?

循環走起!

files=list.files(pattern = '*peakAnno*',path = '.', recursive = T,full.names = T)
for (filename in files){
  # filename=files[1]
  prefix=sapply(strsplit(filename, '_'), function(x) paste(x[2:4], collapse = '-'))
  cat(paste0('Peak types for ',prefix,'\n'))
  p=read.csv(filename,row.names = 1)
  cat(names(table(gsub("\\(ENSMUST.*", "", p$annotation))),'\n')
  cat(table(gsub("\\(ENSMUST.*", "", p$annotation)),'\n\n')
}

這樣可以看一眼,但還是感覺不如數據框更直觀,而且我們想給別人看,也是要發給他們表格。

下一個問題就是:如何變成數據框?

目的就是得到下圖:

這裏需要注意,不是每一個peak註釋結果的列數都是固定的,也就是說,有的結果可能只有3‘UTR peaks,有的可能5’和 3‘都有。這就給數據框組合帶來了困擾

這裏最好先按列合併,比如mergeleft_join都對列的合併有比較好的支持,而行合併可能問題多多

rm(list = ls())
options(stringsAsFactors = F)
require(stringr)
library(tidyverse)

# 新建一個空數據框
dat=data.frame(c("3' UTR","5' UTR","Distal Intergenic", "Downstream (<1kb)", 
               "Downstream (1-2kb)", "Downstream (2-3kb)", "Exon",  
               "Intron",  "Promoter (<=1kb)", "Promoter (1-2kb)", "Promoter (2-3kb)"))
colnames(dat)='type'

files=list.files(pattern = '*peakAnno*',path = '.', recursive = T,full.names = T)

# 一個循環,有匹配的就把數字填進去,沒有匹配就NA(left_join的功能)
for (n in 1:length(files)){
  # n=1
  # n=2
  prefix=sapply(strsplit(files[n], '_'), function(x) paste(x[2:4], collapse = '-'))
  # cat(paste0('Peak types for ',prefix,'\n'))
  p=read.csv(files[n],row.names = 1)
  # cat(names(table(gsub("\\(ENSMUST.*", "", p$annotation))),'\n')
  # cat(table(gsub("\\(ENSMUST.*", "", p$annotation)),'\n\n')
  pd=as.data.frame(table(gsub(" \\(ENSMUST.*", "", p$annotation)))
  colnames(pd)=c('type',prefix)
  pd$type=as.character(pd$type)
  dat=left_join(dat,pd,by='type')
}
                
# 最後轉置回來
final=as.data.frame(t(dat))
colnames(final)=final[1,]
final=final[-1,]

歡迎關注我們的公衆號~_~  
我們是兩個農轉生信的小碩,打造生信星球,想讓它成爲一個不拽術語、通俗易懂的生信知識平臺。需要幫助或提出意見請後臺留言或發送郵件到[email protected]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章