簡體   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