1. 程式人生 > >演算法(二)蓄水池抽樣演算法快速隨機抽取reads

演算法(二)蓄水池抽樣演算法快速隨機抽取reads

原創:hxj7

關鍵詞:蓄水池演算法;

fastq檔案往往都很大,出於測試目的,我們經常要從fastq檔案中隨機抽取reads,生成一個小一點的fastq檔案,以加快測試效率。假設我們要從一個包含大約100M reads的fastq檔案中隨機抽取1M reads,該怎麼辦呢?

我們將問題簡單化:假設我們要從一個txt檔案中(不知道總共多少行)隨機抽取M行(fastq檔案的處理與之類似,只不過fastq檔案是壓縮過的,且其一條記錄由4行組成),比較容易想到的是如下辦法(虛擬碼): 在這裡插入圖片描述

該方法有一個很大的缺點,就是需要讀取檔案兩遍。一般來說,I/O操作是很耗時的,所以該方法效率不高,當檔案很大時,慢得驚人。

如果只要讀取一次檔案就好了,比如下面這樣(虛擬碼): 在這裡插入圖片描述

該方法把檔案整個讀入記憶體,的確減少了程式讀取檔案的總次數。但是,當檔案很大時,該方法消耗的記憶體就太大了(想像一下把一個8G的txt檔案整個載入到記憶體時的糟糕情況)。所以,不光要減少讀取檔案的次數,還要消耗較少的記憶體才好!

蓄水池抽樣演算法(Reservoir Sampling)就可以較好地解決上述問題,虛擬碼如下: 在這裡插入圖片描述

蓄水池抽樣方法只需讀取檔案一次,且消耗的記憶體只有M行大小,而不是整個檔案。所以,程式執行的效率會大大提高。

蓄水池抽樣演算法適用於大資料隨機抽樣,其關鍵在於證明其抽樣的步驟是等概率的。其實證明方法也不難,只需運用歸納法即可,具體證明過程可參照

wiki。值得注意的是,lh3大神的seqtk工具集就實現了該演算法,只需運用seqtk sample命令。

今天的分享就到這裡,謝謝大家!

公眾號:生信了 在這裡插入圖片描述