[英]How to reversibly store and load a Pandas dataframe to/from disk
現在我每次運行腳本時都會導入一個相當大的CSV
作為 dataframe 。 是否有一個好的解決方案可以讓 dataframe 在兩次運行之間始終可用,這樣我就不必花費所有時間等待腳本運行?
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 ),它為大型數據集提供非常快的訪問時間:
import pandas as pd
store = pd.HDFStore('store.h5')
store['df'] = df # save it
store['df'] # load it
食譜中討論了更高級的策略。
從 0.13 開始,還有msgpack可能更適合互操作性,作為 JSON 的更快替代品,或者如果您有 python 對象/文本重數據(請參閱此問題)。
雖然已經有一些答案,但我找到了一個很好的比較,他們嘗試了幾種方法來序列化 Pandas DataFrames: Efficiently Store Pandas DataFrames 。
他們比較:
在他們的實驗中,他們序列化了一個包含 1,000,000 行的 DataFrame,其中兩列分別測試:一列包含文本數據,另一列包含數字。 他們的免責聲明說:
您不應該相信以下內容可以概括為您的數據。 您應該查看自己的數據並自己運行基准測試
他們所引用的測試的源代碼可在線獲得。 由於這段代碼不能直接工作,我做了一些小改動,你可以在這里得到: serialize.py我得到了以下結果:
他們還提到,通過將文本數據轉換為分類數據,序列化速度要快得多。 在他們的測試中大約快 10 倍(另請參閱測試代碼)。
編輯:pickle 比 CSV 更高的時間可以通過使用的數據格式來解釋。 默認情況下, pickle
使用可打印的 ASCII 表示,從而生成更大的數據集。 然而,從圖中可以看出,使用較新的二進制數據格式(版本 2, pickle-p2
)的pickle-p2
加載時間要低得多。
其他一些參考:
numpy.fromfile
是最快的。如果我理解正確,您已經在使用pandas.read_csv()
但希望加快開發過程,這樣您就不必每次編輯腳本時都加載文件,對嗎? 我有幾點建議:
您可以使用pandas.read_csv(..., nrows=1000)
僅加載 CSV 文件的一部分以僅加載表的頂部位,同時進行開發
將 csv 轉換為HDF5 表
更新使用DataFrame.to_feather()
和pd.read_feather()
以pd.read_feather()
的 R 兼容羽毛二進制格式存儲數據(在我手中,在數字數據上比pandas.to_pickle()
略快,在字符串數據上快得多)。
您可能也對 stackoverflow 上的這個答案感興趣。
泡菜效果很好!
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
您可以使用羽毛格式文件。 它非常快。
df.to_feather('filename.ft')
Pandas DataFrames 有to_pickle
函數,這對於保存 DataFrame 很有用:
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 列 100 萬個點的數據幀的簡單基准。
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
pickle 協議格式:
協議版本 0 是原始的“人類可讀”協議,向后兼容早期版本的 Python。
協議版本 1 是一種舊的二進制格式,它也與早期版本的 Python 兼容。
協議版本 2 是在 Python 2.3 中引入的。 它提供了更有效的新型類酸洗。 有關協議 2 帶來的改進的信息,請參閱 PEP 307。
Python 3.0 中添加了協議版本 3。 它對字節對象有明確的支持,並且不能被 Python 2.x 取消。 這是默認協議,當需要兼容其他 Python 3 版本時推薦使用的協議。
Python 3.4 中添加了協議版本 4。 它增加了對超大對象的支持,酸洗更多種類的對象,以及一些數據格式優化。 有關協議 4 帶來的改進的信息,請參閱 PEP 3154。
另一個非常新鮮的to_pickle()
測試。
我總共有25 個.csv
文件需要處理,最終的dataframe
包含大約200 萬個項目。
(注意:除了加載 .csv 文件,我還操作一些數據並通過新列擴展數據框。)
瀏覽所有25 個.csv
文件並創建數據框大約需要14 sec
。
從pkl
文件加載整個數據幀需要不到1 sec
Arctic是 Pandas、numpy 和其他數字數據的高性能數據存儲。 它位於 MongoDB 之上。 對於 OP 來說可能有點矯枉過正,但值得一提的是其他在這篇文章中絆倒的人
import pickle
example_dict = {1:"6",2:"2",3:"g"}
pickle_out = open("dict.pickle","wb")
pickle.dump(example_dict, pickle_out)
pickle_out.close()
上面的代碼將保存pickle文件
pickle_in = open("dict.pickle","rb")
example_dict = pickle.load(pickle_in)
這兩行將打開保存的泡菜文件
總體轉移到 pyarrow/feather(來自 pandas/msgpack 的棄用警告)。 但是,我對 pyarrow 有一個挑戰,在規范中具有瞬態數據用 pyarrow 0.15.1 序列化不能用 0.16.0 ARROW-7961反序列化。 我正在使用序列化來使用 redis,因此必須使用二進制編碼。
我重新測試了各種選項(使用 jupyter notebook)
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 序列化表單時。 如果 pyarrow 反序列化失敗,則從緩存回退讀取到 pickle 時。
這里有很多很棒和足夠的答案,但我想發布一個我在 Kaggle 上使用的測試,其中大 df 由不同的 Pandas 兼容格式保存和讀取:
https://www.kaggle.com/pedrocouto39/fast-reading-w-pickle-feather-parquet-jay
我不是作者或作者的朋友,但是,當我讀到這個問題時,我認為在那里值得一提。
CSV:1 分鍾 42 秒泡菜:4.45 秒羽毛:4.35 秒鑲木地板:8.31 秒 Jay:8.12 毫秒或 0.0812 秒(極快!)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.