CSV无可厚非的是一种良好的通用文件存储方式,几乎任何一款工具或者编程语言都能对其进行读写,但是当文件特别大的时候,CSV这种存储方式就会变得十分缓慢且低效。本文将介绍几种在Python中能够代替CSV这种格式的其他文件格式,并对比每种文件存储的时间与大小。

先说结论,parquet是最好的文件存储格式,具体对比见下文。

生成随机数据

导入依赖

import random
import string
import pickle
# 以下需要自行安装
import numpy as np
import pandas as pd
import tables
import pyarrow as pa
import pyarrow.feather as feather
import pyarrow.parquet as pq

生成随机数据

这里使用pandas的dataframe来存储数据

# 变量定义
row_num = int(1e7)
col_num = 5
str_len = 4
str_nunique = 10 # 字符串组合数量
# 生成随机数
int_matrix = np.random.randint(0, 100, size=(row_num, col_num))
df = pd.DataFrame(int_matrix, columns=['int_%d' % i for i in range(col_num)])
float_matrix = np.random.rand(row_num, col_num)
df = pd.concat(
(df, pd.DataFrame(float_matrix, columns=['float_%d' % i for i in range(col_num)])), axis=1)
str_list = [''.join(random.sample(string.ascii_letters, str_len))
for _ in range(str_nunique)]
for i in range(col_num):
sr = pd.Series(str_list*(row_num//str_nunique)
).sample(frac=1, random_state=i)
df['str_%d' % i] = sr print(df.info())

生成100w行数据,其中整型,浮点型和字符串各5列,数据大小在内存里大概为1GB+

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 10000000 entries, 0 to 9999999
Data columns (total 15 columns):
# Column Dtype
--- ------ -----
0 int_0 int64
1 int_1 int64
2 int_2 int64
3 int_3 int64
4 int_4 int64
5 float_0 float64
6 float_1 float64
7 float_2 float64
8 float_3 float64
9 float_4 float64
10 str_0 object
11 str_1 object
12 str_2 object
13 str_3 object
14 str_4 object
dtypes: float64(5), int64(5), object(5)
memory usage: 1.1+ GB

保存文件

csv

CSV的保存方式很简单,直接使用pandas自带的to_csv() 方法即可

# 写入
df.to_csv('./df_csv.csv', index=False)
# 读取
df = pd.read_csv('./df_csv.csv')

写入时间花费:78 s

读取时间花费:11.8 s

所需存储空间:1.3GB

pkl

pkl文件需要用到built-inpickle

# 写入
with open('./df_pkl.pkl', 'wb') as f:
pickle.dump(df, f)
# 读取
with open('./df_pkl.pkl', 'rb') as f:
df = pickle.load(f)

写入时间花费:2.89 s

读取时间花费:2.61 s

所需存储空间:858M

npy

npy是numpy自带的一种保存格式,唯一的缺点是只能保存numpy的格式,所以需要将pandas先转成numpy才行,为了公平,这里我们会算上转换的时间

# 写入
with open('./df_npy.npy', "wb") as f:
np.save(f, arr=df.values)
# 读取
with open('./df_npy.npy', "rb") as f:
df_array = np.load(f, allow_pickle=True)
df = pd.DataFrame(df_array)

写入时间花费:21 s

读取时间花费:14.8 s

所需存储空间:620M

hdf

层次数据格式(HDF)是自描述的,允许应用程序在没有外部信息的情况下解释文件的结构和内容。一个HDF文件可以包含一系列相关对象,这些对象可以作为一个组或单个对象进行访问。

这里将使用pandas自带的to_hdf()方法,该方法默认是用的HDF5格式

# 写入
df.to_hdf('df_hdf.h5', key='df')
# 读取
df = pd.read_hdf('df_hdf.h5', key='df')

写入时间花费:3.96 s

读取时间花费:4.13 s

所需存储空间:1.5G

已废弃 msgpack

pandas支持msgpack格式的对象序列化。他是一种轻量级可移植的二进制格式,同二进制的JSON类似,具有高效的空间利用率以及不错的写入(序列化)和读取(反序列化)性能。

从0.25版本开始,不推荐使用msgpack格式,并且之后的版本也将删除它。推荐使用pyarrow对pandas对象进行在线的转换。

read_msgpack() (opens new window)仅在pandas的0.20.3版本及以下版本兼容。

parquet

Apache Parquet为数据帧提供了分区的二进制柱状序列化。它的设计目的是使数据帧的读写效率,并使数据共享跨数据分析语言容易。Parquet可以使用多种压缩技术来尽可能地缩小文件大小,同时仍然保持良好的读取性能。

这里需要使用到pyarrow里面的方法来进行操作

# 写入
pq.write_table(pa.Table.from_pandas(df), 'df_parquet.parquet')
# 读取
df = pq.read_table('df_parquet.parquet').to_pandas()

写入时间花费:3.47 s

读取时间花费:1.85 s

所需存储空间:426M

feature

Feather是一种可移植的文件格式,用于存储内部使用Arrow IPC格式的Arrow表或数据帧(来自Python或R等语言)。Feather是在Arrow项目早期创建的,作为Python和R的快速、语言无关的数据帧存储概念的证明。

这里需要使用到pyarrow里面的方法来进行操作

# 写入
feather.write_feather(df, 'df_feather.feather')
# 读取

写入时间花费:1.9 s

读取时间花费:1.52 s

所需存储空间:715M

总结

对比表格

文件类型 读取时间(s) 写入时间(s) 存储空间(MB)
csv 78.00 11.80 1,300
pickle 2.89 2.61 858
npy 21.00 14.80 620
hdf 3.96 4.13 1,500
parquet 3.47 1.85 426
feature 1.90 1.52 715

时间对比

空间对比

可以看出parquet会是一个保存文件的最好选择,虽然时间上比feature略慢一点,但空间上有着更大的优势。

别再用CSV了,更高效的Python文件存储方案的更多相关文章

  1. 【数据处理】SQL Server高效大数据量存储方案SqlBulkCopy

    要求将Excel数据,大批量的导入到数据库中,尽量少的访问数据库,高性能的对数据库进行存储. 一个比较好的解决方案,就是采用SqlBulkCopy来处理存储数据. SqlBulkCopy存储大批量的数 ...

  2. 如何使代码审查更高效【摘自InfoQ】

      代码审查者在审查代码时有非常多的东西需要关注.一个团队需要明确对于自己的项目哪些点是重要的,并不断在审查中就这些点进行检查. 人工审查代码是十分昂贵的,因此尽可能地使用自动化方式进行审查,如:代码 ...

  3. LocalBroadcastManager—创建更高效、更安全的广播

    前言 在写Android应用时候,有时候或多或少的需要运用广播来解决某些需求,我们知道广播有一个特性,就是使用sendBroadcast(intent);发送广播时,手机内所有注册了Broadcast ...

  4. 这些小工具让你的Android 开发更高效

    在做Android 开发过程中,会遇到一些小的问题.尽管自己动手也能解决.可是有了一些小工具,解决这些问题就得心应手了,今天就为大家推荐一下Android 开发遇到的小工具,来让你的开发更高效. Vy ...

  5. Pull Request 工作流——更高效的管理代码

    目录 Pull Request 工作流--更高效的管理代码 1.问题 2.解决方案 3.Git分支流管理代码具体实施 3.1本地分支操作管理 3.1.1查看分支 3.1.2创建分支 3.1.3切换分支 ...

  6. CesiumLab V1.4 分类3dtiles生成(倾斜单体化、楼层房间交互)我记得我是写过一篇关于倾斜单体化的简书文章的,但是现在找不到了。不过找不到也好,就让他随风逝去吧,因为当时我写那篇文章的时候,就发现了cesium实际是有另一种更高效的单体化。就下面这个示例https://cesiumjs.org/Cesium/Build/Apps/Sandcastle/index.html?src=

    我记得我是写过一篇关于倾斜单体化的简书文章的,但是现在找不到了.不过找不到也好,就让他随风逝去吧,因为当时我写那篇文章的时候,就发现了cesium实际是有另一种更高效的单体化.就下面这个示例 http ...

  7. [源码解析]为什么mapPartition比map更高效

    [源码解析]为什么mapPartition比map更高效 目录 [源码解析]为什么mapPartition比map更高效 0x00 摘要 0x01 map vs mapPartition 1.1 ma ...

  8. 阿里面试:MySQL如何设计索引更高效?

    有情怀,有干货,微信搜索[三太子敖丙]关注这个不一样的程序员. 本文 GitHub https://github.com/JavaFamily 已收录,有一线大厂面试完整考点.资料以及我的系列文章. ...

  9. 想要更高效地找到信息,你需要掌握这些搜索技巧 (google or baidu)

    想要更高效地找到信息,你需要掌握这些搜索技巧 (google or baidu) 转载:https://tingtalk.me/search-tips/ 在大型局域网(互联网)的今天,你以为搜索是一门 ...

随机推荐

  1. Ubuntu创建图标

    起因 安装一些软件时,总是没有图标,导致无法固定到docky栏,所以极为不方便,所以需要自己创建图标. 操作 以创建微信图标为例 [Desktop Entry] Name=Wecaht #名字 Com ...

  2. Java线程池中的核心线程是如何被重复利用的?

    真的!讲得太清楚了!https://blog.csdn.net/MingHuang2017/article/details/79571529 真的是解惑了 本文所说的"核心线程". ...

  3. 官宣.NET 6 预览版4

    我们很高兴发布 .NET 6 Preview 4.我们现在大约完成了 .NET 6 发布的一半.现在是一个很好的时机,可以再次查看.NET6的完整范围.许多功能都接近最终形式,而其他功能将很快推出,因 ...

  4. runtime使用总结

    runtime这个东西,项目是很少用到的,但面试又避不可少,了解其内部的机制对底层的理解还是很有必要的. 1.动态添加属性 拓展类别属性的简单实现 a.定义字面量指针 static char dyna ...

  5. 5.Java流程控制

    所有的流程控制语句都可以相互嵌套.互不影响 一.用户交互Scanner Scanner对象 之前我们学的基本语法中我们并没有实现程序和人的交互,但是Java给我们提供了这样一个工具类,我们可以获取用户 ...

  6. k8s之deployment详解

    Deployment介绍 为了更好地解决服务编排的问题,k8s在V1.2版本开始,引入了deployment控制器,值得一提的是,这种控制器并不直接管理pod, 而是通过管理replicaset来间接 ...

  7. adb 记录ADB执行记录

    自动化测试需要获得当前的activity,来判断处于的页面是否正确: hierarchy view经常连不上真机,无法获得activity,所以直接用 adb命令来查看当前运行的 activity就可 ...

  8. EasyUI:combotree(树形下拉框)复选框选中父节点(子节点的状态也全部选中)输入框中只显示父节点的文本值

    参考: https://blog.csdn.net/weixin_43236850/article/details/100320564

  9. 警告: Runner org.junit.internal.runners.ErrorReportingRunner (used on class cn.star.MybatisTest)

    bug描述: 在Springboot整合Junit的时候编写测试类进行测试时, 出现以下错误: 十一月 28, 2019 2:53:48 下午 org.junit.vintage.engine.des ...

  10. C++第三十九篇 -- 研究一下Windows驱动开发(二)-- 驱动程序中重要的数据结构

    数据结构是计算机程序的核心,I/O管理器定义了一些数据结构,这些数据结构是编写驱动程序时所必须掌握的.驱动程序经常要创建和维护这些数据结构的实例. 一.驱动对象(DRIVER_OBJECT) 每个驱动 ...