目錄
將 numpy 陣列存入檔案,有多種檔案型別可供選擇,對應地就有不同的方法來讀寫。
下面我將介紹讀寫 numpy 的三類檔案:
- txt 或者 csv 檔案
- npy 或者 npz 檔案
- hdf5 檔案
通過 numpy 讀寫 txt 或 csv 檔案
import numpy as np
a = np.array(range(20)).reshape((4, 5))
print(a)
# 字尾改為 .txt 一樣
filename = 'data/a.csv'
# 寫檔案
np.savetxt(filename, a, fmt='%d', delimiter=',')
# 讀檔案
b = np.loadtxt(filename, dtype=np.int32, delimiter=',')
print(b)
缺點:
- 只能儲存一維和二維 numpy 陣列,當 numpy 陣列
a
有多維時,需要將其a.reshape((a.shape[0], -1))
後才能用這種方式儲存。 - 不能追加儲存,即每次
np.savetxt()
都會覆蓋之前的內容。
通過 numpy 讀寫 npy 或 npz 檔案
讀寫 npy 檔案
import numpy as np
a = np.array(range(20)).reshape((2, 2, 5))
print(a)
filename = 'data/a.npy'
# 寫檔案
np.save(filename, a)
# 讀檔案
b = np.load(filename)
print(b)
print(b.shape)
優點:
- npy 檔案可以儲存任意維度的 numpy 陣列,不限於一維和二維;
- npy 儲存了 numpy 陣列的結構,儲存的時候是什麼 shape 和 dtype,取出來時就是什麼樣的 shape 和 dtype。
缺點:
- 只能儲存一個 numpy 陣列,每次儲存會覆蓋掉之前檔案中存在的內容(如果有的話)。
讀寫 npz 檔案
import numpy as np
a = np.array(range(20)).reshape((2, 2, 5))
b = np.array(range(20, 44)).reshape(2, 3 ,4)
print('a:\n', a)
print('b:\n', b)
filename = 'data/a.npz'
# 寫檔案, 如果不指定key,那麼預設key為'arr_0'、'arr_1',一直排下去。
np.savez(filename, a, b=b)
# 讀檔案
c = np.load(filename)
print('keys of NpzFile c:\n', c.keys())
print("c['arr_0']:\n", c['arr_0'])
print("c['b']:\n", c['b'])
優點:
- npy 檔案可以儲存任意維度的 numpy 陣列,不限於一維和二維;
- npy 儲存了 numpy 陣列的結構,儲存的時候是什麼 shape 和 dtype,取出來時就是什麼樣的 shape 和 dtype;
- 可以同時儲存多個 numpy 陣列;
- 可以指定儲存 numpy 陣列的 key,讀取的時候很方便,不會混亂。
缺點:
- 儲存多個 numpy 陣列時,只能同時儲存,即
np.savez(filename, a, b=b)
。每次儲存會覆蓋掉之前檔案中存在的內容(如果有的話)。
通過 h5py 讀寫 hdf5 檔案
優點:
- 不限 numpy 陣列維度,可以保持 numpy 陣列結構和資料型別;
- 適合 numpy 陣列很大的情況,檔案佔用空間小;
- 可以通過 key 來訪問 dataset(可以理解為 numpy.array),讀取的時候很方便,不會混亂。
- 可以不覆蓋原檔案中含有的內容。
簡單讀取
import numpy as np
import h5py
a = np.array(range(20)).reshape((2, 2, 5))
b = np.array(range(20)).reshape((1, 4, 5))
print(a)
print(b)
filename = 'data/data.h5'
# 寫檔案
h5f = h5py.File(filename, 'w')
h5f.create_dataset('a', data=a)
h5f.create_dataset('b', data=b)
h5f.close()
# 讀檔案
h5f = h5py.File(filename, 'r')
print(type(h5f))
# 通過切片得到numpy陣列
print(h5f['a'][:])
print(h5f['b'][:])
h5f.close()
通過切片賦值
import numpy as np
import h5py
a = np.array(range(20)).reshape((2, 2, 5))
print(a)
filename = 'data/a.h5'
# 寫檔案
h5f = h5py.File(filename, 'w')
# 當陣列a太大,需要切片進行操作時,可以不直接對h5f['a']進行初始化;
# 當之後不需要改變h5f['a']的shape時,可以省略maxshape引數
h5f.create_dataset('a', shape=(2, 2, 5), maxshape=(None, 2, 5), dtype=np.int32, compression='gzip')
for i in range(2):
# 採用切片的形式賦值
h5f['a'][i] = a[i]
h5f.close()
# 讀檔案
h5f = h5py.File(filename, 'r')
print(type(h5f))
print(h5f['a'])
# 通過切片得到numpy陣列
print(h5f['a'][:])
同一個 hdf5 檔案可以建立多個 dataset,讀取的時候按照 key 來即可。
總結
- csv 和 txt 只能用來存一維或二維 numpy 陣列;
- npy 用來存單個 numpy 陣列,npz 可以同時存多個 numpy 陣列,兩者都不限 numpy 維度,且都保持 numpy 陣列的 shape 和 dtype,寫檔案時若原檔案存在只能覆蓋原檔案內容;
- 當 numpy 陣列很大時,最好使用 hdf5 檔案,hdf5 檔案相對更小;
- 當 numpy 陣列很大時,對整個 numpy 陣列進行運算容易發生 MemoryError,那麼此時可以選擇對 numpy 陣列切片,將運算後的陣列儲存到 hdf5 檔案中,hdf5 檔案支援切片索引。
References
當Python遇上HDF5--效能優化實戰 -- 張玉騰
雜: PYTHON上資料儲存:推薦h5py -- Pony_s