numpy savetxt:将矩阵保存为行
我正在使用numpy的 savetxt()
方法把一个矩阵的元素保存到文件里,想把它们作为一行输出(因为我需要按顺序打印很多数据)。这是我找到的方法:
import numpy as np
mat = np.array([[1,2,3],
[4,5,6],
[7,8,9]])
with open('myfile.dat','a') as handle:
np.savetxt(handle, mat.reshape(1,mat.size), fmt='%+.8e')
handle.close()
我有两个问题:
1) savetxt()
是不是最好的选择?我需要打印从1e5到1e7这么多数据……我不想因为输入输出速度慢而拖慢实际的计算。我在想每次都重新打开文件是不是个坏主意,速度上可能会受影响。
2) 理想情况下,我希望在每一行的开头打印一些上下文数据,这样我的输出可能看起来像这样:
(N foo mat):
...
6 -2.309 +1.000 +2.000 ...
7 -4.273 +1.000 +2.000 ...
8 -3.664 +1.000 +2.000 ...
...
我可以用 np.append()
来做到这一点,但这样第一个数字就不会以整数的形式打印出来。这样的操作能直接在 savetxt()
中实现吗?还是说我还是得用类似C语言的 fprintf()
呢?
2 个回答
0
Pandas有一个很不错的to_csv
方法:
import pandas as pd
import numpy as np
mat = np.array([[1,2,3],
[4,5,6],
[7,8,9]])
df = pd.DataFrame(data=mat.astype(np.float))
df.to_csv('myfile.dat', sep=' ', float_format='%+.8e', header=False)
默认情况下,它会把索引也写进去(index=True
),不过如果你想要不同的上下文数据,可以直接把这些数据加到你的数据框里,然后把index
设置为假(index=False
)。
$ cat myfile.dat
0 +1.00000000e+00 +2.00000000e+00 +3.00000000e+00
1 +4.00000000e+00 +5.00000000e+00 +6.00000000e+00
2 +7.00000000e+00 +8.00000000e+00 +9.00000000e+00
0
好的。我最初的代码只能在打印数组时使用一次。mat.reshape()
这个方法不仅仅是返回一个重新形状的矩阵,它还会直接改变原来的 mat
。这就意味着下次循环时,任何使用 linalg
的操作都会失败。
为了避免这个问题,我们需要对 mat
的一个副本进行重塑。我还添加了一个 tmp
变量来让代码更清晰。
import numpy as np
mat = np.array([[1,2,3],
[4,5,6],
[7,8,9]]) # initialize mat to see format
handle = open('myfile.dat', 'ab')
for n in range(N):
# perform linalg calculations on mat ...
meta = foo # based on current mat
tmp = np.hstack( ([[n]], [[meta]], (mat.copy()).reshape(1,mat.size)) )
np.savetxt(handle, tmp, fmt='%+.8e')
handle.close()
在这个情况下,我们获取了上下文数据 n
和 meta
。我可以接受 n
被保存为一个 float
类型。
我做了一些基准测试来检查输入输出的成本。我把循环的 N 设置为 100,000,并计算了 6 次运行的平均时间:
- 没有输入输出,只有计算:9.1 秒
- 如上所述的代码:17.2 秒
- 打开 'myfile.dat' 来在每次迭代时追加数据:30.6 秒
所以,输入输出的操作让运行时间翻倍,正如预期的那样,不停地打开和关闭文件是个糟糕的主意。