现在,每次运行脚本时,我都会导入一个相当大的CSV作为数据框架。是否有一个好的解决方案来保持数据帧在运行之间不断可用,这样我就不必花费所有的时间等待脚本运行?
当前回答
如前所述,有不同的选项和文件格式(HDF5, JSON, CSV, parquet, SQL)来存储数据帧。然而,pickle不是一级公民(取决于你的设置),因为:
泡菜是一个潜在的安全隐患。形成pickle的Python文档:
警告pickle模块不安全 恶意构造的数据。对象接收的数据永远不能解pickle 不受信任或未经身份验证的源。
泡菜很慢。找到这里和这里的基准。
根据您的设置/使用情况,这两个限制都不适用,但我不建议将pickle作为pandas数据帧的默认持久性。
其他回答
这里有很多很棒和充分的答案,但我想发布一个我在Kaggle上使用的测试,这个测试用不同的pandas兼容格式保存和读取大df:
https://www.kaggle.com/pedrocouto39/fast-reading-w-pickle-feather-parquet-jay
我不是作者,也不是作者的朋友,然而,当我读到这个问题时,我觉得值得一提。
CSV: 1分42秒泡菜:4.45秒羽毛:4.35秒拼花:8.31秒杰伦:8.12毫秒 或者0.0812秒(超快的!)
Pyarrow跨版本兼容性
总的来说,pyarrow/feather(来自pandas/msgpack的弃用警告)。然而,我有一个挑战与pyarrow的瞬态在规范中的数据序列化pyarrow 0.15.1不能反序列化与0.16.0 ARROW-7961。我使用序列化使用redis,所以必须使用二进制编码。
我重新测试了各种选择(使用jupyter笔记本电脑)
import sys, pickle, zlib, warnings, io
class foocls:
def pyarrow(out): return pa.serialize(out).to_buffer().to_pybytes()
def msgpack(out): return out.to_msgpack()
def pickle(out): return pickle.dumps(out)
def feather(out): return out.to_feather(io.BytesIO())
def parquet(out): return out.to_parquet(io.BytesIO())
warnings.filterwarnings("ignore")
for c in foocls.__dict__.values():
sbreak = True
try:
c(out)
print(c.__name__, "before serialization", sys.getsizeof(out))
print(c.__name__, sys.getsizeof(c(out)))
%timeit -n 50 c(out)
print(c.__name__, "zlib", sys.getsizeof(zlib.compress(c(out))))
%timeit -n 50 zlib.compress(c(out))
except TypeError as e:
if "not callable" in str(e): sbreak = False
else: raise
except (ValueError) as e: print(c.__name__, "ERROR", e)
finally:
if sbreak: print("=+=" * 30)
warnings.filterwarnings("default")
对我的数据帧(在出jupyter变量)具有以下结果
pyarrow before serialization 533366
pyarrow 120805
1.03 ms ± 43.9 µs per loop (mean ± std. dev. of 7 runs, 50 loops each)
pyarrow zlib 20517
2.78 ms ± 81.8 µs per loop (mean ± std. dev. of 7 runs, 50 loops each)
=+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+=
msgpack before serialization 533366
msgpack 109039
1.74 ms ± 72.8 µs per loop (mean ± std. dev. of 7 runs, 50 loops each)
msgpack zlib 16639
3.05 ms ± 71.7 µs per loop (mean ± std. dev. of 7 runs, 50 loops each)
=+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+=
pickle before serialization 533366
pickle 142121
733 µs ± 38.3 µs per loop (mean ± std. dev. of 7 runs, 50 loops each)
pickle zlib 29477
3.81 ms ± 60.4 µs per loop (mean ± std. dev. of 7 runs, 50 loops each)
=+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+=
feather ERROR feather does not support serializing a non-default index for the index; you can .reset_index() to make the index into column(s)
=+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+=
parquet ERROR Nested column branch had multiple children: struct<x: double, y: double>
=+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+==+=
羽毛和拼花不适合我的数据框架。我将继续使用pyarrow。但是我会补充腌黄瓜(没有压缩)。写入缓存时,存储pyarrow和pickle序列化表单。如果pyarrow反序列化失败,则从缓存读取回退到pickle时。
如前所述,有不同的选项和文件格式(HDF5, JSON, CSV, parquet, SQL)来存储数据帧。然而,pickle不是一级公民(取决于你的设置),因为:
泡菜是一个潜在的安全隐患。形成pickle的Python文档:
警告pickle模块不安全 恶意构造的数据。对象接收的数据永远不能解pickle 不受信任或未经身份验证的源。
泡菜很慢。找到这里和这里的基准。
根据您的设置/使用情况,这两个限制都不适用,但我不建议将pickle作为pandas数据帧的默认持久性。
Numpy文件格式对于数字数据来说非常快
我更喜欢使用numpy文件,因为它们快速且易于使用。 下面是一个简单的基准测试,用于保存和加载一个包含100万个点的1列数据框架。
import numpy as np
import pandas as pd
num_dict = {'voltage': np.random.rand(1000000)}
num_df = pd.DataFrame(num_dict)
使用ipython的%%timeit魔法函数
%%timeit
with open('num.npy', 'wb') as np_file:
np.save(np_file, num_df)
输出为
100 loops, best of 3: 5.97 ms per loop
将数据加载回数据框架
%%timeit
with open('num.npy', 'rb') as np_file:
data = np.load(np_file)
data_df = pd.DataFrame(data)
输出为
100 loops, best of 3: 5.12 ms per loop
不坏!
CONS
如果您使用python 2保存numpy文件,然后尝试使用python 3打开,则会出现问题(反之亦然)。
https://docs.python.org/3/library/pickle.html
pickle协议格式如下:
协议版本0是原始的“人类可读”协议,并向后兼容Python的早期版本。
协议版本1是一种旧的二进制格式,它也与早期版本的Python兼容。
协议版本2是在Python 2.3中引入的。它提供了更有效的新样式类的pickle。有关协议2带来的改进,请参阅PEP 307。
协议版本3是在Python 3.0中添加的。它显式支持bytes对象,不能被Python 2.x解封。这是默认协议,也是在需要与其他Python 3版本兼容时的推荐协议。
协议版本4是在Python 3.4中添加的。它增加了对非常大的对象、pickle更多类型的对象以及一些数据格式优化的支持。有关协议4带来的改进的信息,请参阅PEP 3154。
推荐文章
- 证书验证失败:无法获得本地颁发者证书
- 当使用pip3安装包时,“Python中的ssl模块不可用”
- 无法切换Python与pyenv
- Python if not == vs if !=
- 确定每列中NA值的个数
- 如何从scikit-learn决策树中提取决策规则?
- 为什么在Mac OS X v10.9 (Mavericks)的终端中apt-get功能不起作用?
- 将旋转的xtick标签与各自的xtick对齐
- 为什么元组可以包含可变项?
- 如何合并字典的字典?
- 如何创建类属性?
- 如何结合多个条件子集数据帧使用“或”?
- 不区分大小写的“in”
- 在Python中获取迭代器中的元素个数
- 解析日期字符串并更改格式