繁体   English   中英

python - 将numpy数组保存到文件(尽可能小的大小)

[英]python - saving numpy array to a file (smallest size possible)

现在我有一个python程序构建一个相当大的2D numpy数组并使用numpy.savetxt将其保存为制表符分隔的文本文件。 numpy数组只包含浮点数。 然后,我在一个单独的C ++程序中一次读取一行文件。

我想要做的是找到一种方法来完成同样的任务,尽可能少地改变我的代码,这样我就可以减少我在两个程序之间传递的文件的大小。

我发现我可以使用numpy.savetxt保存为压缩的.gz文件而不是文本文件。 这将文件大小从大约2MB降低到大约100kB。

有一个更好的方法吗? 或许,我可以将二进制的numpy数组写入文件以节省空间吗? 如果是这样,我将如何做到这一点,以便我仍然可以将它读入C ++程序?

感谢您的帮助。 我很感激能得到的任何指导。

编辑:

有很多零(numpy数组中可能有70%的值是0.0000)我不知道我怎么能以某种方式利用它并生成一个我的c ++程序可以读取的小文件

除非你确定你不需要担心字节顺序等,最好使用numpy.savez ,如@ unutbu的回答和@jorgeca的评论中所述: numpy的tostring / fromstring ---我需要指定什么才能恢复阵列

如果结果大小不够小,那么总是有zlib (在python方面: import zlib ,在C ++方面,我确定存在一个实现)。

另一种方法是使用hdf5格式:虽然它不一定会减少磁盘上的文件大小,但它确实可以更快地保存/加载(这就是格式设计的大数据阵列)。 hdf5有python和C ++读/写hdf5

由于你有很多零,你只能写出表格中的非零元素(索引,数字)。

假设您有一个包含少量非零数字的数组:

In [5]: a = np.zeros((10, 10))

In [6]: a
Out[6]: 
array([[ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.]])

In [7]: a[3,1] = 2.0

In [8]: a[7,4] = 17.0

In [9]: a[9,0] = 1.5

首先,隔离有趣的数字及其指数:

In [11]: x, y = a.nonzero()

In [12]: zip(x,y)
Out[12]: [(3, 1), (7, 4), (9, 0)]

In [13]: nonzero = zip(x,y)

现在您只剩下少量数据元素。 最简单的方法是将它们写入文本文件:

In [17]: with open('numbers.txt', 'w+') as outf:
   ....:     for r, k in nonzero:
   ....:         outf.write('{:d} {:d} {:g}\n'.format(r, k, a[r,k]))
   ....:         

In [18]: cat numbers.txt
3 1 2
7 4 17
9 0 1.5

这也让您有机会了解数据。 在C ++程序中,您可以使用fscanf读取此数据。

但是您可以使用struct编写二进制数据来进一步减小大小:

In [17]: import struct

In [19]: c = struct.Struct('=IId')

In [20]: with open('numbers.bin', 'w+') as outf:
   ....:     for r, k in nonzero:
   ....:         outf.write(c.pack(r, k, a[r,k]))

Struct构造函数的参数意味着; 使用原生日期格式'='。 第一个和第二个数据元素是无符号整数“I”,第三个元素是双“d”。

在您的C ++程序中,这些数据可能最好作为二进制数据读入打包struct

编辑 :为2D阵列更新了答案。

numpy.ndarray.tofilenumpy.fromfile对于python的直接二进制输出/输入很有用。 std::ostream::write std::istream::read对于c ++中的二进制输出/输入很有用。

如果数据从一台机器传输到另一台机器,您应该注意字节顺序。

使用一个hdf5文件,它们通过h5py非常简单,你可以使用set compression一个标志。 请注意,hdf5还有一个c ++接口。

如果您不介意安装其他软件包(对于pythonc++ ),您可以使用[BSON][1] (二进制JSON)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM