6


3

ASCIIエンコーディングをintに変換し、Pythonで再び(すばやく)変換します

整数の文字列を文字列としてエンコードするファイル形式(fastq形式)があり、各整数はオフセット付きのASCIIコードで表されます。 残念ながら、一般的に使用されているエンコーディングは2つあります。1つはオフセット33、もう1つはオフセット64です。 通常、1つのオフセットから別のオフセットに変換するために、長さ80〜150の1億個の文字列があります。 この種のことを行うために思いつくことができる最も単純なコードは次のとおりです。

def phred64ToStdqual(qualin):
    return(''.join([chr(ord(x)-31) for x in qualin]))

これはうまく機能しますが、特に高速ではありません。 100万文字列の場合、私のマシンでは約4秒かかります。 翻訳を行うためにいくつかの辞書を使用するように変更した場合、約2秒に短縮できます。

ctoi = {}
itoc = {}
for i in xrange(127):
    itoc[i]=chr(i)
    ctoi[chr(i)]=i

def phred64ToStdqual2(qualin):
    return(''.join([itoc[ctoi[x]-31] for x in qualin]))

盲目的にcythonで実行すると、1秒未満になります。 + Cレベルでは、これは単にintへのキャスト、減算、charへのキャストのようです。 私はこれを書きませんでしたが、私はそれがかなり速いと推測しています。 これをPythonでコーディングする方法や、これを行うためのcythonバージョンをコーディングする方法などのヒントは非常に役立ちます。

ありがとう、

Sean

1 回答


4


urllib.quoteのコードを見ると、あなたがやっていることに似たことがあります。 それはように見えます:

_map = {}
def phred64ToStdqual2(qualin):
    if not _map:
        for i in range(31, 127):
            _map[chr(i)] = chr(i - 31)
    return ''.join(map(_map.__getitem__, qualin))

上記の関数は、マッピングが同じ長さでない場合に機能することに注意してください(urllib.quoteでは、 '%'→ '%25’を取る必要があります。

しかし実際には、すべての翻訳は同じ長さであるため、pythonにはこれを非常に迅速に行う関数があります:http://docs.python.org/library/string.html#string.maketrans[maketrans]およびhttp:// docs .python.org / library / string.html#string.translate [translate]。 あなたはおそらく以下よりも速くはなりません:

import string
_trans = None
def phred64ToStdqual4(qualin):
    global _trans
    if not _trans:
        _trans = string.maketrans(''.join(chr(i) for i in range(31, 127)), ''.join(chr(i) for i in range(127 - 31)))
    return qualin.translate(_trans)