使用numpy.loadtxt加载复数

时间:2017-02-20 15:47:35

标签: python arrays numpy complex-numbers

我知道如果我想用numpy保存和加载复数数组,我可以使用这里描述的方法:How to save and load an array of complex numbers using numpy.savetxt?

但是,假设有人不知道这一点并使用numbers保存了他们的数组numpy.savetxt("numbers.txt",numbers,生成了一个包含

形式的条目的文件
(0.000000000000000000e+00+-2.691033635430225765e-02j)  .

在这种情况下

numbers_load = numpy.loadtxt("numbers.txt").view(complex)

意味着

会失败

ValueError: could not convert string to float: (0.000000000000000000e+00+-2.691033635430225765e-02j)  .

从这个文件中提取复数的简单方法是什么(不生成它的不同版本)?

5 个答案:

答案 0 :(得分:3)

您可以使用converters来处理自定义格式。阻止正确读取复杂值的唯一问题是+-中的1+-2j,将其替换为1-2j会起作用。

>>> numpy.savetxt('1.txt', numpy.array([2.3+4.5j, 6.7-0.89j]))

>>> numpy.loadtxt('1.txt', dtype=complex)  # <- doesn't work directly
ValueError: complex() arg is a malformed string

>>> numpy.loadtxt('1.txt', dtype=complex, converters={0: lambda s: complex(s.decode().replace('+-', '-'))})
array([ 2.3+4.5j ,  6.7-0.89j])

答案 1 :(得分:2)

在保存数组之前,您应该使用.view(float)将其转换为float的数组,然后.view(complex)float转换回{{} 1}}加载时的数字。

complex

答案 2 :(得分:1)

如果您无法修改文件,则可以在逐行读取字符串时对字符串进行转换。

import numpy as np
import re

# a regular expression that picks out the two components of the complex number
reg = re.compile('(-?\d.\d*e[+-]\d\d)\+(-?\d.\d*e[+-]\d\d)')
# a function that returns a properly formatted string
edit = lambda s: reg.search(s).expand(r'\1 \2')

with open("numbers.txt", 'r') as fobj:
    # calling map applies the edit function to each line of numbers.txt in turn
    numbers_load = np.loadtxt(map(edit, fobj))
print(numbers_load) # [ 0.         -0.02691034]
print(numbers_load.view('complex')) # [ 0.-0.02691034j]

答案 3 :(得分:0)

savetxt的文档讨论了复杂数组的fmt选项。

从1d数组开始:

In [17]: np.arange(5)+np.arange(5,0,-1)*1j
Out[17]: array([ 0.+5.j,  1.+4.j,  2.+3.j,  3.+2.j,  4.+1.j])
In [18]: arr = np.arange(5)+np.arange(5,0,-1)*1j

默认是写入数字,每行一个()个字符串。用loadtxt(或genfromtxt)读取它将是一个问题。它必须作为字符串加载,然后逐行转换。

In [19]: np.savetxt('test.txt',arr)
In [20]: cat test.txt
 (0.000000000000000000e+00+5.000000000000000000e+00j)
 (1.000000000000000000e+00+4.000000000000000000e+00j)
 (2.000000000000000000e+00+3.000000000000000000e+00j)
 (3.000000000000000000e+00+2.000000000000000000e+00j)
 (4.000000000000000000e+00+1.000000000000000000e+00j)

它说我可以指定实部和虚部的格式,在这种情况下,它将其保存为2列。使用loadtxt即可轻松阅读。

In [21]: np.savetxt('test.txt',arr, fmt='%f %f')
In [22]: cat test.txt
0.000000 5.000000
1.000000 4.000000
2.000000 3.000000
3.000000 2.000000
4.000000 1.000000

In [23]: np.loadtxt('test.txt')
Out[23]: 
array([[ 0.,  5.],
       [ 1.,  4.],
       [ 2.,  3.],
       [ 3.,  2.],
       [ 4.,  1.]])

In [25]: np.loadtxt('test.txt').view(complex)
Out[25]: 
array([[ 0.+5.j],
       [ 1.+4.j],
       [ 2.+3.j],
       [ 3.+2.j],
       [ 4.+1.j]])

对于2d复数数组,我需要为所有列指定fmt

In [28]: arr1=np.array((arr, arr*.1, arr+1))
In [29]: arr1
Out[29]: 
array([[ 0.0+5.j ,  1.0+4.j ,  2.0+3.j ,  3.0+2.j ,  4.0+1.j ],
       [ 0.0+0.5j,  0.1+0.4j,  0.2+0.3j,  0.3+0.2j,  0.4+0.1j],
       [ 1.0+5.j ,  2.0+4.j ,  3.0+3.j ,  4.0+2.j ,  5.0+1.j ]])

In [33]: np.savetxt('test.txt',arr1, fmt=['%f %f']*5)
In [34]: cat test.txt
0.000000 5.000000 1.000000 4.000000 2.000000 3.000000 3.000000 2.000000 4.000000 1.000000
0.000000 0.500000 0.100000 0.400000 0.200000 0.300000 0.300000 0.200000 0.400000 0.100000
1.000000 5.000000 2.000000 4.000000 3.000000 3.000000 4.000000 2.000000 5.000000 1.000000
In [35]: np.loadtxt('test.txt').view(complex)
Out[35]: 
array([[ 0.0+5.j ,  1.0+4.j ,  2.0+3.j ,  3.0+2.j ,  4.0+1.j ],
       [ 0.0+0.5j,  0.1+0.4j,  0.2+0.3j,  0.3+0.2j,  0.4+0.1j],
       [ 1.0+5.j ,  2.0+4.j ,  3.0+3.j ,  4.0+2.j ,  5.0+1.j ]])

文档显示包含所有列的长格式字符串,但显然字符串列表正常工作

In [36]: ['%f %f']*5
Out[36]: ['%f %f', '%f %f', '%f %f', '%f %f', '%f %f']

savetxt将该列表与分隔符连接以生成一个长格式字符串。

In [37]: np.savetxt('test.txt',arr1, fmt=['%f %f']*5, delimiter=',')
In [38]: cat test.txt
0.000000 5.000000,1.000000 4.000000,2.000000 3.000000,3.000000 2.000000,4.000000 1.000000
...

对于loadtxt,复杂零件和列之间的分隔符必须兼容:

In [39]: np.savetxt('test.txt',arr1, fmt=['%f %f']*5, delimiter='  ')
In [40]: cat test.txt
0.000000 5.000000  1.000000 4.000000  2.000000 3.000000  3.000000 2.000000  4.000000 1.000000
...

总而言之,如果save使用与加载兼容的格式,则保存/加载往返将是最简单的。

答案 4 :(得分:0)

指定类似的数据类型:

np.loadtxt("numbers.txt", dtype=np.complex_) 

为我工作。