【数据分析】【Python】多维数据高效操作、读取与储存-numpy、h5py实现

多维数据存储多维数据操作,是数据分析和机器学习的科研工作中最常遇见的问题。
常见的多维度数据有:真彩图、遥感影像图、医学影像图,最近比较火的深度图等等。

多维数据的特点:
  1. 数据量大,单个数据最少也是(1000,1000,10)这个量级的。
  2. 矩阵形式
在存储的时候,需要考虑多个方面的问题:
  1. 要对数据进行压缩。如果存储为常见的文本格式,单个数据动不动就是10多个G,绝对不行
  2. 存储以后,可以分片读取。否则想读取数据中的一小块数据,也要把所有的数据读取到内存中进行检索,这也是不行的
  3. 储存格式要通用。否则业务上游做好了数据,业务下游在使用的时候,会有很大的障碍
  4. 数据可以通过工具可视化查看。
  5. 库的安装使用方便。不要动不动就让科研工作者玩Hadoop,Spark好吧。。。
最优解决方案

针对上述问题,最优的解决方案是保存为HDF5格式。对应的Python库为h5py
HDF5官方地址:https://www.hdfgroup.org/solutions/hdf5/
h5py官方地址:https://www.h5py.org/

HDF5的优点
  1. Python库安装方便。Anaconda中已经集成了,装好Anaconda,你就有了h5py这个库
  2. 格式通用。也是Pytorch中推荐的多维数据保存格式,使用h5py读取的数据,直接就是numpy.ndarray
  3. 可视化。可以在官网下载HDF5的HDFViewer软件,直接打开文件进行查看。
  4. 数据压缩。按经验,一个保存为TXT格式需要2G空间的数据,使用HDF5只需要几十MB,节省了几十倍的空间
  5. 分片读取。不需要将数据全部读取到内存进行检索,直接可以使用切片操作读取,其他不需要的数据就不会被读取到内存

HDF5的常用操作,基于Python的h5py和numpy

数据拼接

首先回答第二个问题,如何拼接多维数据。

import numpy as np

# 创建(3, 1, 2)维度的矩阵
shape1 = (3, 1, 2)
a = np.zeros(shape1, dtype=np.int)
print(a.shape)  # (3, 1, 2)

# 创建(4, 1, 2)维度的矩阵
shape2 = (4, 1, 2)
b = np.ones(shape2, dtype=np.int)
print(b.shape)  # (4, 1, 2)

# 在第一个维度上拼接a和c
axis = 0  # axis指的是你想在第几个维度上进行拼接,因为numpy是0-base,所以第一个维度其实是0
c = np.concatenate((a, b), axis=axis)
print(c.shape)  # (7, 1, 2)
储存为HDF5格式
import h5py
with h5py.File("c.hdf5", 'w') as f:  # 写入的时候是‘w’
    f.create_dataset("a_data", data=a, compression="gzip", compression_opts=5)
    f.create_dataset("b_data", data=b, compression="gzip", compression_opts=5)
    f.create_dataset("c_data", data=c, compression="gzip", compression_opts=5)
# c_data:是HDF5文件中c数据储存的名字
# compression="gzip":是对数据进行压缩,压缩的方式一个gzip
# compression_opts=5:是压缩等级,压缩等级越高,压缩的越好,但是压缩消耗的CPU时间会增加
读取HDF5格式文件中的数据
with h5py.File("c.hdf5", 'r') as f:  # 读取的时候是‘r’
    print(f.keys())
    a_new = f.get("a_data")[:]
    b_new = f.get("b_data")[:]
    c_new = f.get("c_data")[:]

验证一下写入的数据和读取的数据是不是一样

print(a == a_new)
print(b == b_new)
print(c == c_new)

对比一下存储一个(5000, 5000)的数据,省多少空间,数据INT

import os
import numpy as np
data_5000_5000 = np.arange(0, 5000*5000, dtype=np.int).reshape(5000, 5000)
print(data_5000_5000)

[[ 0 1 2 … 4997 4998 4999]
[ 5000 5001 5002 … 9997 9998 9999]
[ 10000 10001 10002 … 14997 14998 14999]

[24985000 24985001 24985002 … 24989997 24989998 24989999]
[24990000 24990001 24990002 … 24994997 24994998 24994999]
[24995000 24995001 24995002 … 24999997 24999998 24999999]]

使用TXT
np.savetxt("data.txt", data_5000_5000)
print(os.path.getsize("data.txt") / 1024 / 1024)

596.0512161254883 MB

使用HDF5
with h5py.File("data.hdf5", 'w') as f:
    f.create_dataset("data", data=data_5000_5000, compression="gzip", compression_opts=5)

33.43095302581787 MB

结论

可以看到,使用TXT格式保存使用了596.05MB,使用HDF5格式保存使用了33.43MB

596.05 / 33.43

17.829793598564162
节省了大概17倍的空间

你可能感兴趣的:(数据分析)