Python 将复杂数据读入numpy数组

Python 将复杂数据读入numpy数组,python,numpy,Python,Numpy,我需要将文本文件中的复数读入numpy数组。我的问题与此类似,但是,这里的解决方案是更改数据保存的格式。我没有这种奢侈,因为文本文件是由其他软件生成的,我无法更改。文本文件的示例如下所示: 25 + 0i 8.43818 + -4.94194i 4.46817 + -5.08305i 4.55764 + -3.02201i 2.69138 + -5.43104i -0.151334 + -4.83717i 1.98336 + -1.3339i 3.59002 + -0.932973i 1.427

我需要将文本文件中的复数读入numpy数组。我的问题与此类似,但是,这里的解决方案是更改数据保存的格式。我没有这种奢侈,因为文本文件是由其他软件生成的,我无法更改。文本文件的示例如下所示:

25 + 0i
8.43818 + -4.94194i
4.46817 + -5.08305i
4.55764 + -3.02201i
2.69138 + -5.43104i
-0.151334 + -4.83717i
1.98336 + -1.3339i
3.59002 + -0.932973i
1.42727 + -0.617317i
1.02005 + -1.14214i
-0.15564 + 2.74564i
我尝试了以下方法:

np.loadtxt('file.txt',delimiter='\n',dtype=np.complex128)
但是我得到了一个错误:

ValueError: complex() arg is a malformed string
我读过的帖子表明,这是某些行中的
+-
符号的问题,但是,即使删除了额外的
+
符号,我也会遇到同样的错误

然而,这里的解决方案是改变数据保存的格式

好消息,你不必这么做

numpy.loadtxt
可以接受任意一行,而不仅仅是一个文件对象

因此,您可以将文件对象包装在一个简单的生成器中,该生成器可以动态地转换行,并将其提供给
loadtxt
,每个人都会很高兴

像这样:

def transform_complex(line):
    # insert your code here

with open('file.txt', 'rb') as f:
    lines = map(transform_complex, f)
    arr = np.loadtxt(lines, dtype=np.complex128)
(如果您使用的是Python2.x,并且文件很大,那么您可能希望使用
itertools.imap
而不是
map

“在此处插入您的代码”部分,您根据有效的答案填写,但这不是一个可接受的解决方案,因为它需要修改文件。由于我在您的链接中没有看到这样的答案,我不确定这是什么,但例如,可能是这样的:

def transform_complex(line):
    return line.replace(b'+ -', b'- ')

在本地进行测试时,看起来您的输入实际上有三个错误

您可以使用
savetxt
测试输出的外观。例如:

>>> arr = np.array([1-2j])
>>> f = io.BytesIO()
>>> np.savetxt(f, arr)
>>> f.getvalue()
b' (1.000000000000000000e+00-2.000000000000000000e+00j)\n'
(在Python2.x中,您将看不到
b
前缀。)

并非所有这些差异都是相关的——你不必使用指数表示法,你不需要帕伦等——但看起来这三个是:

  • +
    周围不允许有复数空格
  • 虚单位必须是
    j
    ,而不是
    i
  • 不允许使用
    +-
因此:


@abarnert的回答很好,但是不要忘记,
loadtxt
有一个参数,
converters
, 它提供了一个钩子,用于自定义字段的处理方式。这里有一对 演示如何使用它处理此文件的示例

在第一个版本中,保留默认分隔符(空白), 所以有三列。
usecols
用于忽略中间的列(“+”)。转换器用于 将最后一列(第2列)转换为浮点值。它使用一个切片来丢弃 最后一个字符,即“i”。使用这些参数,
loadtxt
返回一个数组 具有浮点值的形状(11,2)。通过使用 键入
np.complex128
,数组将转换为浮点值数组 具有形状(11,1)。最后,使用
[:,0]
索引给出了复杂值的1D数组。 (可以使用调用
ravel
挤压
重塑

下一个版本将整行视为单个字段。以下函数 将文件中使用格式的字符串转换为复数:

In [36]: def to_complex(field):
   ....:     return complex(field.replace(' ', '').replace('+-', '-').replace('i', 'j'))
   ....: 
In [37]: loadtxt('file.txt', converters={0: to_complex}, dtype=np.complex128, delimiter=';')
Out[37]: 
array([ 25.000000+0.j      ,   8.438180-4.94194j ,   4.468170-5.08305j ,
         4.557640-3.02201j ,   2.691380-5.43104j ,  -0.151334-4.83717j ,
         1.983360-1.3339j  ,   3.590020-0.932973j,   1.427270-0.617317j,
         1.020050-1.14214j ,  -0.155640+2.74564j ])
例如

loadtxt
的调用将每一行视为一个字段,并使用 将每个字段转换为复数的转换器:

In [36]: def to_complex(field):
   ....:     return complex(field.replace(' ', '').replace('+-', '-').replace('i', 'j'))
   ....: 
In [37]: loadtxt('file.txt', converters={0: to_complex}, dtype=np.complex128, delimiter=';')
Out[37]: 
array([ 25.000000+0.j      ,   8.438180-4.94194j ,   4.468170-5.08305j ,
         4.557640-3.02201j ,   2.691380-5.43104j ,  -0.151334-4.83717j ,
         1.983360-1.3339j  ,   3.590020-0.932973j,   1.427270-0.617317j,
         1.020050-1.14214j ,  -0.155640+2.74564j ])
(分隔符设置为
;”
,但它可能是 不会出现在文件中。)

In [37]: loadtxt('file.txt', converters={0: to_complex}, dtype=np.complex128, delimiter=';')
Out[37]: 
array([ 25.000000+0.j      ,   8.438180-4.94194j ,   4.468170-5.08305j ,
         4.557640-3.02201j ,   2.691380-5.43104j ,  -0.151334-4.83717j ,
         1.983360-1.3339j  ,   3.590020-0.932973j,   1.427270-0.617317j,
         1.020050-1.14214j ,  -0.155640+2.74564j ])