2017-05-05 3 views
0

私は16の核からのゲノムデータを持っています。最初の列は核を表し、次の2つの列は足場(ゲノムのセクション)および足場の位置をそれぞれ表し、最後の2つの列はそれぞれヌクレオチドおよびカバレッジを表す。異なる核内で同じ足場と位置が存在し得る。この大規模なCSVファイルからデータをすばやく抽出するにはどうすればよいですか?

開始位置と終了位置(足場とそれぞれの位置)の入力を使用して、開始から終了までの範囲内の各ニュークリアのデータ(ヌクレオチドとカバレッジ)を示すcsvファイルを出力することになっています。私は16列(核ごとに1つ)を持ち、上から下にデータを表示することでこれを行うことを考えていました。一番左の領域はその範囲の参照ゲノムであり、足場ごとに辞書を作成してアクセスします。

私のコードでは、デフォルトのリストがあるので、キーは足場と場所を組み合わせたストリングです。データはリストの配列なので、各ニュークリアにデータを追加することができます同じ場所にあり、最後に各場所にはすべての核からのデータがあります。

もちろん、これは非常に遅いです。代わりに私はそれをどうやってやりますか?

コード:

#let's plan this 
#input is start and finish - when you hit first, add it and keep going until you hit next or larger 
#dictionary of arrays 
#loop through everything, output data for each nucleus 

import csv 
from collections import defaultdict 

inrange = 0 
start = 'scaffold_41,51335' 
end = 'scaffold_41|51457' 
locations = defaultdict(list) 
count = 0 

genome = defaultdict(lambda : defaultdict(dict)) 
scaffold = '' 
for line in open('Allpaths_SL1_corrected.fasta','r'): 
    if line[0]=='>': 
     scaffold = line[1:].rstrip() 
    else: 
     genome[scaffold] = line.rstrip() 
print('Genome dictionary done.') 

with open('automated.csv','rt') as read: 
    for line in csv.reader(read,delimiter=','): 
     if line[1] + ',' + line[2] == start: 
      inrange = 1 
     if inrange == 1: 
      locations[line[1] + ',' + line[2]].append([line[3],line[4]]) 
     if line[1] + ',' + line[2] == end: 
      inrange = 0 
     count += 1 
     if count%1000000 == 0: 
      print('Checkpoint '+str(count)+'!') 

with open('region.csv','w') as fp: 
    wr = csv.writer(fp,delimiter=',',lineterminator='\n') 
    for key in locations: 
     nuclei = [] 
     for i in range(0,16): 
      try: 
       nuclei.append(locations[key][i]) 
      except IndexError: 
       nuclei.append(['','']) 
     wr.writerow([genome[key[0:key.index(',')][int(key[key.index(',')+1:])-1],key,nuclei]) 
print('Done!') 

ファイル: https://drive.google.com/file/d/0Bz7WGValdVR-bTdOcmdfRXpUYUE/view?usp=sharing https://drive.google.com/file/d/0Bz7WGValdVR-aFdVVUtTbnI2WHM/view?usp=sharing

+2

あなたの質問を*あなたの問題の詳細から抽象化してください*。人がすぐに実行できる実際のデータセットと同じプロパティを持つ玩具データセットを作成します。あなたの分野に特有の専門用語を使用するほど、あなたの質問に掘り下げたい人が少なくなるでしょう。 –

+2

おそらくあなたが使用する必要がある[pandas.read_csv](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.read_csv.html)または[pandas.read_table](HTTP://pandas.pydata .org/pandas-docs/stable/generated/pandas.read_table.html)。あなたがデータセットを読んだら、パンダでそれを変換する方法がたくさんあります。 – Leonid

+0

同じファイルを何度もフィルタリングする必要がある場合は、各足場(ハッシュテーブル)の最初と最後のファイルを作成し、サブテーブルのみを検索してメモリに読み込むことをお勧めします。テーブルを作成するのは非常に長いプロセスですが、その後は検索が非常に高速になる可能性があります。 – rth

答えて

0

付属のサンプルcsvファイルが2GBを超えている(あなただけのコードの途中でCSV部分に焦点を当てました)および77,822,354行。これらのラインのうち、26,804,253ライン、つまり約1/3に絞られているようです。

一般的な提案として、あなたはで事をスピードアップすることができます:あなたは(ファイルの2/3)に興味を持っていないデータを処理しないでください

  1. 興味のあるデータを特定するのをスピードアップします。
  2. より遅くなる傾向がある何百万回も繰り返されることを避ける(各行をcsvとして処理し、文字列を再構成するなど)。 numpypandaspypy

あなたのデータはブロック指向なので、あなたができるようにあなたがブロックまたはラインにそれを破ることができたときにすべてのデータを読み込む

  • 避け(メモリがきついでしょう)
  • 使用高速化ツールFlipFlopタイプのオブジェクトを使用して、ブロック内にあるかどうかを検出します。

    あなたのCSVファイルの最初の列が数値、そうではなく、離れて行を分割して2つの列を再組み立てで、あなたはブロックの開始と終了を見つけるために、より高速のPython in演算子を使用することができます。

    start = ',scaffold_41,51335,' 
    end = ',scaffold_41,51457,' 
    
    class FlipFlop: 
        def __init__(self, start_pattern, end_pattern): 
         self.patterns = start_pattern, end_pattern 
         self.state = False 
        def __call__(self, st): 
         rtr=True if self.state else False 
         if self.patterns[self.state] in st: 
          self.state = not self.state 
         return self.state or rtr 
    
    lines_in_block=0  
    with open('automated.csv') as f: 
        ff=FlipFlop(start, end) 
        for lc, line in enumerate(f): 
         if ff(line): 
          lines_in_block+=1 
    
    print lines_in_block, lc 
    

    印刷物:

    PyPyでは約9秒、Python 2.7では46秒で実行されます。

    あなたはその後、元のcsvファイルを読み込む部分を取ると、あなたは一度に1つのブロックのデータに対処する必要があるので、発電機にそれを変えることができます。

    (確かに正しくない、私は全体的にあなたのファイルを理解しようと何時間を費やしていないので...):

    def csv_bloc(fn, start_pat, end_pat): 
        from itertools import ifilter 
        with open(fn) as csv_f: 
        ff=FlipFlop(start_pat, end_pat) 
        for block in ifilter(ff, csv_f): 
         yield block 
    

    それとも、あなたは1つの辞書にすべてのブロックを結合する必要がある場合:

    def csv_line(fn, start, end): 
        with open(fn) as csv_in: 
         ff=FlipFlop(start, end) 
         for line in csv_in: 
          if ff(line): 
           yield line.rstrip().split(",")    
    
    di={}    
    for row in csv_line('/tmp/automated.csv', start, end): 
        di.setdefault((row[2],row[3]), []).append([row[3],row[4]]) 
    

    PyPyの私の(古い)Macでは約1分、cPython 2.7では約3分で実行されます。

    最高

  • 関連する問題