我知道如果我想用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) .
从这个文件中提取复数的简单方法是什么(不生成它的不同版本)?
答案 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_)
为我工作。