1

我有一个特定格式的二进制文件,感兴趣的人在这里描述。格式不是导入的东西。我可以读取这些数据并将其转换为我想要的形式,但问题是这些二进制文件中往往包含大量信息。如果我只是将字节作为读取返回,这非常快(不到 1 秒),但我无法对这些字节做任何有用的事情,它们需要首先转换为基因型,这就是看起来的代码放慢速度。

一系列字节到基因型的转换如下

        h = ['%02x' % ord(b) for b in currBytes]
        b = ''.join([bin(int(i, 16))[2:].zfill(8)[::-1] for i in h])[:nBits]
        genotypes = [b[i:i+2] for i in range(0, len(b), 2)]
        map = {'00': 0, '01': 1, '11': 2, '10': None}
        return  [map[i] for i in genotypes]

我希望有一种更快的方法来做到这一点?有任何想法吗?下面是python -m cProfile test.pytest.py 调用我为读取这些文件而编写的读取器对象的运行结果。

vlan1711:src davykavanagh$ python -m cProfile test.py
183, 593483, 108607389, 366, 368, 46
that took 93.6410450935
         86649088 function calls in 96.396 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    1.248    1.248    2.753    2.753 plinkReader.py:13(__init__)
        1    0.000    0.000    0.000    0.000 plinkReader.py:47(plinkReader)
        1    0.000    0.000    0.000    0.000 plinkReader.py:48(__init__)
        1    0.000    0.000    0.000    0.000 plinkReader.py:5(<module>)
        1    0.000    0.000    0.000    0.000 plinkReader.py:55(__iter__)
   593484   77.634    0.000   91.477    0.000 plinkReader.py:58(next)
        1    0.000    0.000    0.000    0.000 plinkReader.py:71(SNP)
   593483    1.123    0.000    1.504    0.000 plinkReader.py:75(__init__)
        1    0.000    0.000    0.000    0.000 plinkReader.py:8(plinkFiles)
        1    0.000    0.000    0.000    0.000 plinkReader.py:85(Person)
      183    0.000    0.000    0.001    0.000 plinkReader.py:89(__init__)
        1    2.166    2.166   96.396   96.396 test.py:5(<module>)
 27300218    5.909    0.000    5.909    0.000 {bin}
   593483    0.080    0.000    0.080    0.000 {len}
        1    0.000    0.000    0.000    0.000 {math.ceil}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
        2    0.000    0.000    0.000    0.000 {method 'format' of 'str' objects}
   593483    0.531    0.000    0.531    0.000 {method 'join' of 'str' objects}
   593485    0.588    0.000    0.588    0.000 {method 'read' of 'file' objects}
   593666    0.257    0.000    0.257    0.000 {method 'rsplit' of 'str' objects}
   593666    0.125    0.000    0.125    0.000 {method 'rstrip' of 'str' objects}
 27300218    4.098    0.000    4.098    0.000 {method 'zfill' of 'str' objects}
        3    0.000    0.000    0.000    0.000 {open}
 27300218    1.820    0.000    1.820    0.000 {ord}
   593483    0.817    0.000    0.817    0.000 {range}
        2    0.000    0.000    0.000    0.000 {time.time}
4

1 回答 1

1

您通过创建不需要的列表和大字符串来减慢速度。您只是在检查字节的位并将两位组转换为数字。这可以更简单地实现,例如通过以下代码:

def convert(currBytes, nBits):
  for byte in currBytes:
    for p in range(4):
      bits = (ord(byte) >> (p*2)) & 3
      yield None if bits == 1 else 1 if bits == 2 else 2 if bits == 3 else 0
      nBits -= 2
      if nBits <= 0:
        raise StopIteration()

如果你真的需要 alist最后,只需使用

list(convert(currBytes, nBits))

但我想在某些情况下您只想迭代结果:

for blurp in convert(currBytes, nBits):
  # handle your blurp (0, 1, 2, or None)
于 2014-02-07T14:03:38.920 回答