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

来源:互联网 发布:ubuntu安装monaco字体 编辑:程序博客网 时间:2024/05/21 15:51

本文来探索一下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 npfrom __future__ import print_functionimport 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 msWall time: 2.06 sCPU times: user 4 ms, sys: 156 ms, total: 160 msWall 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 msWall time: 269 msCPU times: user 0 ns, sys: 116 ms, total: 116 msWall 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 sWall time: 18.4 sCPU times: user 55.9 s, sys: 476 ms, total: 56.4 sWall time: 56.3 s(10000, 5000)[[ 90.  96.  38. ...,  67.  40.  79.] [ 40.  12.  71. ...,  64.  76.  15.]]
  • 读写1维和2维数组的文本文件

4.h5py.File()

import h5pytime0 = 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 picklewith 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 sWall time: 36.1 sCPU times: user 6.84 s, sys: 10.4 s, total: 17.2 sWall time: 17.2 s(10000, 5000)[[90 96 38 ..., 67 40 79] [40 12 71 ..., 64 76 15]]

结果统计

方法 文件格式 大小 写入耗时 读入耗时 需要处理类型? 需要处理形状? np.tofile() .bin 381.47MB 2.06 s 160 ms 是 是 np.save() .npy 381.47MB 269 ms 116 ms 否 否 np.savetxt() .txt 138.28MB 18.4 s 56.3 s 是 否 h5py.File() .h5 381.47MB 260ms 150ms 否 否 pickle.dump() .pkl 1.39GB 36.1 s 17.2 s 否 否

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

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

非对齐的 ndarray 数据存储

import h5pylist_a = [[1,2,3], [4,5], [77]]arr_a = np.asarray(list_a)arr_a
array([[1, 2, 3], [4, 5], [77]], dtype=object)
# 无法保存长度不同的 ndarrayf = 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() 非常强大呀,没办法,只好选择它了。

参考

  • python:numpy(文件存取)
  • HDF5在python上的使用
原创粉丝点击