Python+不同的数据存储方式比较

本文来探索一下python中提供的各种数据保存格式的性能如何。主要以一个 ndarray 格式的数据进行处理分析。包括下面几种方式:

  • .bin格式, np.tofile() 和 np.fromfile()
  • .npy格式,np.save() 和 np.load()
  • .txt 或者 .csv格式,np.savetxt() 和 np.loadtxt()
  • .h5 格式,h5py.File(,’r’ 或者 ‘w’)
  • .pkl 格式, pickle.dump()和pickle.load()
import numpy as np
from __future__ import print_function
import time
a = np.random.randint(0, 100, size=(10000, 5000))
print(a.dtype, a.shape)
print(a[:2])
int64 (10000, 5000)
[[90 96 38 ..., 67 40 79]
 [40 12 71 ..., 64 76 15]]

1. np.tofile() 和 np.fromfile()

%time a.tofile('data/a.bin')
%time b = np.fromfile('data/a.bin', dtype=np.int64)
print(b.shape)
print(b[:2])
CPU times: user 4 ms, sys: 392 ms, total: 396 ms
Wall time: 2.06 s
CPU times: user 4 ms, sys: 156 ms, total: 160 ms
Wall time: 160 ms
(50000000,)
[90 96]
  • 读入数据的时候要正确设置 dtype 参数

  • 读入的数据是一维的,还需要经过 reshape 处理。

2. np.save()和np.load()

%time np.save('data/a.npy', a)
%time b = np.load('data/a.npy')
print(b.shape)
print(b[:2])
CPU times: user 0 ns, sys: 272 ms, total: 272 ms
Wall time: 269 ms
CPU times: user 0 ns, sys: 116 ms, total: 116 ms
Wall time: 116 ms
(10000, 5000)
[[90 96 38 ..., 67 40 79]
 [40 12 71 ..., 64 76 15]]
  • NumPy专用的二进制格式保存数据,它们会自动处理元素类型和形状等信息.

使用 np.savez() 保存多个矩阵至一个文件中:

a = np.asarray([[1,2], [3,4]])
b = np.asarray([0,1])
np.savez('data.npz', X=a, y=b)
# 导入
data = np.load('data.npz')
a = data['X']
b = data['y']

3. np.savetxt()和np.loadtxt()

%time np.savetxt('data/a.txt', a, fmt='%d', delimiter=',')  # 设置以整数形式存储,以逗号隔开
%time b = np.loadtxt('data/a.txt', delimiter=',')
print(b.shape)
print(b[:2])
CPU times: user 18.4 s, sys: 60 ms, total: 18.5 s
Wall time: 18.4 s
CPU times: user 55.9 s, sys: 476 ms, total: 56.4 s
Wall time: 56.3 s
(10000, 5000)
[[ 90.  96.  38. ...,  67.  40.  79.]
 [ 40.  12.  71. ...,  64.  76.  15.]]
  • 读写1维和2维数组的文本文件

4.h5py.File()

import h5py

time0 = time.time()
f = h5py.File('data/a.h5','w')   #创建一个h5文件,文件指针是f  
f['data'] = a                    #将数据写入文件的主键data下面  
f.close()                        #关闭文件  
print('saving time %.2fs' % (time.time() - time0))
time cost 0.26s
time0 = time.time()
f = h5py.File('data/a.h5','r')   #打开h5文件  
# print f.keys()                      #可以查看所有的主键  
b = f['data'][:]                    #取出主键为data的所有的键值  
f.close()  
print('loading time %.2fs' % (time.time() - time0))
print(b.shape)
print(b[:2])
loading time 0.15s
(10000, 5000)
[[90 96 38 ..., 67 40 79]
 [40 12 71 ..., 64 76 15]]

5.pickle.dump()和pickle.load()

import pickle
with open('data/a.pkl', 'wb') as outp:
    %time pickle.dump(a, outp)

with open('data/a.pkl', 'rb') as inp:
    %time b = pickle.load(inp)

print(b.shape)
print(b[:2])
CPU times: user 30.1 s, sys: 5.92 s, total: 36.1 s
Wall time: 36.1 s
CPU times: user 6.84 s, sys: 10.4 s, total: 17.2 s
Wall time: 17.2 s
(10000, 5000)
[[90 96 38 ..., 67 40 79]
 [40 12 71 ..., 64 76 15]]

结果统计

方法文件格式大小写入耗时读入耗时需要处理类型?需要处理形状?
np.tofile().bin381.47MB2.06 s160 ms
np.save().npy381.47MB269 ms116 ms
np.savetxt().txt138.28MB18.4 s56.3 s
h5py.File().h5381.47MB260ms150ms
pickle.dump().pkl1.39GB36.1 s17.2 s

需要说明的是,第一次导入数据后在一段时间内会保存在缓存中,这时候再次导入会非常非常快。所以在训练神经网络的时候,使用 np.load() 的方式导入数据,除了第一个 epoch 速度会慢一些,后面读取数据的速度非常快。

  • 总体上最优的方法是使用 np.save() 和 h5py.File(, ‘r’ or ‘w’);np.savez() 可以存储多个值, 而 h5py 提供字典的方式存储更是非常方便。
  • txt 和 csv 文本文件占用的空间是最少的,但是耗时非常大
  • np.tofile() 方法要处理数据的类型和形状,很烦,可以放弃了
  • pickle() 的 .pkl 文件非常非常占空间,而且巨慢,直接放弃!!

非对齐的 ndarray 数据存储

import h5py

list_a = [[1,2,3], [4,5], [77]]
arr_a = np.asarray(list_a)
arr_a
array([[1, 2, 3], [4, 5], [77]], dtype=object)
# 无法保存长度不同的 ndarray
f = h5py.File('data/arr_a.h5', 'w')
f['arr_a'] = arr_a  # 报错,每个元素都是 Object。
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-7-0a946c2e9c3c> in <module>()
      1 f = h5py.File('data/arr_a.h5', 'w')
----> 2 f['arr_a'] = arr_a  # 报错, 无法保存长度不同的 ndarray
... 
TypeError: Object dtype dtype('O') has no native HDF5 equivalent
np.save('data/arr_a.npy', arr_a)
b = np.load('data/arr_a.npy')
print(b)
[[1, 2, 3] [4, 5] [77]]

通过上面的比较,我们可以看到 np.save() 非常强大呀,没办法,只好选择它了。

参考

  • 23
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值