[英]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.tofile
和numpy.fromfile
對於python的直接二進制輸出/輸入很有用。 std::ostream::write
std::istream::read
對於c ++中的二進制輸出/輸入很有用。
如果數據從一台機器傳輸到另一台機器,您應該注意字節順序。
使用一個hdf5文件,它們通過h5py非常簡單,你可以使用set compression一個標志。 請注意,hdf5還有一個c ++接口。
如果您不介意安裝其他軟件包(對於python
和c++
),您可以使用[BSON][1]
(二進制JSON)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.