Answers:
df.to_pickle(file_name) # where to save it, usually as a .pkl
然后您可以使用以下方法将其加载回:
df = pd.read_pickle(file_name)
注意:在0.11.1 save
和之前,load
这样做是唯一的方法(现在已弃用它们,to_pickle
而read_pickle
分别赞成和)。
另一个流行的选择是使用HDF5(pytables),它为大型数据集提供了非常快速的访问时间:
store = HDFStore('store.h5')
store['df'] = df # save it
store['df'] # load it
食谱中讨论了更高级的策略。
从0.13开始,还有msgpack,它可能对于互操作性更好,作为JSON的更快替代品,或者如果您有python对象/文本繁重的数据(请参阅此问题)。
尽管已经有了一些答案,但是我发现它们之间进行了很好的比较,他们尝试了几种方法来序列化Pandas DataFrame:有效存储Pandas DataFrames。
他们比较:
在他们的实验中,他们使用分别测试的两列来序列化1,000,000行的DataFrame:一个带有文本数据,另一个带有数字。他们的免责声明说:
您不应相信以下内容会泛化您的数据。您应该查看自己的数据并自己运行基准测试
他们所参考的测试源代码可在线获得。由于此代码无法直接运行,因此我做了一些小的更改,您可以在此处进行更改:serialize.py, 我得到以下结果:
他们还提到,通过将文本数据转换为分类数据,序列化要快得多。在他们的测试中大约快10倍(另请参见测试代码)。
编辑:腌制时间比CSV更长,可以通过使用的数据格式来解释。默认情况下,pickle
使用可打印的ASCII表示形式,该表示形式会生成更大的数据集。从图中可以看出,使用较新的二进制数据格式(版本2 pickle-p2
)的pickle的加载时间要短得多。
其他一些参考:
numpy.fromfile
的速度最快。如果我理解正确,那么您已经在使用,pandas.read_csv()
但是想加快开发过程,这样就不必在每次编辑脚本时都加载文件,对吗?我有一些建议:
pandas.read_csv(..., nrows=1000)
在进行开发时,您只能加载CSV文件的一部分,而仅用于加载表的最高位
使用ipython进行交互式会话,以便在编辑和重新加载脚本时将pandas表保留在内存中。
将csv转换为HDF5表
更新了用法,DataFrame.to_feather()
并pd.read_feather()
以R兼容的羽毛二进制格式存储了数据,该格式超级快(在我手中,比pandas.to_pickle()
数字数据要快一些,而字符串数据要快得多)。
您可能也对stackoverflow上的这个答案感兴趣。
to_feather
在字符串数据上能很好地工作吗?我进行了基准测试to_pickle
,to_feature
在我的数字数据框和泡菜上快了约3倍。
泡菜很好!
import pandas as pd
df.to_pickle('123.pkl') #to save the dataframe, df to 123.pkl
df1 = pd.read_pickle('123.pkl') #to load 123.pkl back to the dataframe df
.pkl
@Andy Haydens答案中建议的扩展名。
熊猫数据框具有to_pickle
对保存数据框有用的功能:
import pandas as pd
a = pd.DataFrame({'A':[0,1,0,1,0],'B':[True, True, False, False, False]})
print a
# A B
# 0 0 True
# 1 1 True
# 2 0 False
# 3 1 False
# 4 0 False
a.to_pickle('my_file.pkl')
b = pd.read_pickle('my_file.pkl')
print b
# A B
# 0 0 True
# 1 1 True
# 2 0 False
# 3 1 False
# 4 0 False
我更喜欢使用numpy文件,因为它们快速且易于使用。这是一个简单的基准,用于保存和加载具有1百万点的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
不错!
如果您使用python 2保存numpy文件,然后尝试使用python 3打开(反之亦然),则会出现问题。
https://docs.python.org/3/library/pickle.html
泡菜协议格式:
协议版本0是原始的“人类可读”协议,并且与Python的早期版本向后兼容。
协议版本1是旧的二进制格式,也与Python的早期版本兼容。
协议版本2是在Python 2.3中引入的。它提供了新型类的更有效的酸洗。有关协议2带来的改进的信息,请参阅PEP 307。
协议版本3是在Python 3.0中添加的。它具有对字节对象的显式支持,并且不能被Python 2.x取消选择。这是默认协议,当需要与其他Python 3版本兼容时,建议使用该协议。
协议版本4是在Python 3.4中添加的。它增加了对超大型对象的支持,腌制更多种类的对象以及一些数据格式优化。有关协议4带来的改进的信息,请参阅PEP 3154。
总体上已经转向了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")
对于我的数据框具有以下结果(在out
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序列化表格。如果从pypy反序列化失败,则从缓存回退到泡菜。