numpy savetxt:将矩阵保存为行

2 投票
2 回答
2160 浏览
提问于 2025-04-17 20:46

我正在使用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()

在这个情况下,我们获取了上下文数据 nmeta。我可以接受 n 被保存为一个 float 类型。

我做了一些基准测试来检查输入输出的成本。我把循环的 N 设置为 100,000,并计算了 6 次运行的平均时间:

  • 没有输入输出,只有计算:9.1 秒
  • 如上所述的代码:17.2 秒
  • 打开 'myfile.dat' 来在每次迭代时追加数据:30.6 秒

所以,输入输出的操作让运行时间翻倍,正如预期的那样,不停地打开和关闭文件是个糟糕的主意。

撰写回答