Python:将 float 字符串解包为复数

标签 python arrays struct

我对编码相当陌生,我正在从二进制文件读取信号。数据被定向为两个 4 字节 float ,组成一个复数,这会重复最多 1500 个条目

我一直在使用 for 循环来提取数据并将复数附加到数组中

for x in range(dimX):
    for y in range(dimY):
        complexlist=[]
        #2 floats, each 4 bytes, is one complex number
        trace=stream.readBytes(8*dimZ)
        #Unpack as list of floats
        floatlist=struct.unpack("f"*2*dimZ,trace)
        for i in range(0,len(floatlist)-1,2):
            complexlist.append(complex(floatlist[i],floatlist[i+1]))        
        data[x][y]=np.array(complexlist)

其中 dimX 可能为数千,DimY 通常为 <30,dimZ 为 <1500

但是对于大文件来说这非常慢

有没有办法读取整个跟踪的缓冲区并直接解压为复数数组?

最佳答案

是的,有。您可以跳过 Python 复数类型的步骤,因为在内部,numpy 将 n 复数数组表示为 2n float 数组。

下面是 REPL 中的一个简单示例,说明其工作原理:

>>> import numpy as np
>>> a = np.array([1.,2.,3.,4.])
>>> a
array([ 1.,  2.,  3.,  4.])
>>> a.dtype
dtype('float64')
>>> a.dtype = complex
>>> a
array([ 1.+2.j,  3.+4.j])
>>> 

请注意,如果初始数组的 dtype 不是 float,则此方法不起作用。

>>> a = np.array([1,2,3,4])
>>> a
array([1, 2, 3, 4])
>>> a.dtype
dtype('int64')
>>> a.dtype = complex
>>> a
array([  4.94065646e-324 +9.88131292e-324j,
         1.48219694e-323 +1.97626258e-323j])
>>>

就你的情况而言。您想要的 dtype 是 np.dtype('complex64') 因为您的每个复数都是 64 位 (2*4*8)。

for x in range(dimX):
    for y in range(dimY):
        #2 floats, each 4 bytes, is one complex number
        trace=stream.readBytes(8*dimZ)
        a = np.frombuffer(trace,dtype=np.dtype('complex64'))
        data[x][y] = a

这应该会大大加快你的速度。以下是来自 REPL 的示例,介绍了 numpy.frombuffer() 的工作原理

>>> binary_string = struct.pack('2f', 1,2)
>>> binary_string
'\x00\x00\x80?\x00\x00\x00@'
>>> numpy.frombuffer(binary_string, dtype=np.dtype('complex64'))
array([ 1.+2.j], dtype=complex64)
>>> 

编辑:我不知道numpy.frombuffer()的存在。所以我创建了一个字符数组,然后更改数据类型以获得相同的效果。谢谢@wim

编辑2:

对于进一步的速度优化,您可能会通过使用列表理解而不是显式的 for 循环来获得性能提升。

for x in range(dimX):
    data[x] = [np.frombuffer(stream.readBytes(8*dimZ), dtype=np.dtype('complex64')) for y in range(dimY)]

还有一个级别:

data = [[np.frombuffer(stream.readBytes(8*dimZ), dtype=np.dtype('complex64'))
         for y in range(dimY)]
         for x in range(dimX)]

关于Python:将 float 字符串解包为复数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15244327/

相关文章:

python - Django channel 的负载尖峰保护

python - 使用 lambda 排序函数按每个元组组合值对字符串元组进行排序

arrays - 是否存在 Swift 数组分配不一致的原因(既不是引用也不是深层复制)?

c++ - 将结构转换为数组

c - 如何计算 C 结构中的填充

python - Google Cloud - 使用 python 连接到同一项目中的 postgresql 数据库

python - Python 中实例方法内部 self 的用法

arrays - 用整数 1 或 2 填充固定大小的数组以求和 X

java - 在 Java 中防止 NullPointerException

c - 为链表数组分配内存