CSV無可厚非的是一種良好的通用文件存儲方式,幾乎任何一款工具或者編程語言都能對其進行讀寫,可是當文件特別大的時候,CSV這種存儲方式就會變得十分緩慢且低效。本文將介紹幾種在Python中可以代替CSV這種格式的其餘文件格式,並對比每種文件存儲的時間與大小。python
先說結論,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來存儲數據dom
# 變量定義 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的保存方式很簡單,直接使用pandas自帶的to_csv()
方法便可工具
# 寫入 df.to_csv('./df_csv.csv', index=False) # 讀取 df = pd.read_csv('./df_csv.csv')
寫入時間花費:78 s性能
讀取時間花費:11.8 sui
所需存儲空間:1.3GB設計
pkl文件須要用到built-in
的pickle
包code
# 寫入 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是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文件能夠包含一系列相關對象,這些對象能夠做爲一個組或單個對象進行訪問。
這裏將使用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
pandas支持msgpack格式的對象序列化。他是一種輕量級可移植的二進制格式,同二進制的JSON相似,具備高效的空間利用率以及不錯的寫入(序列化)和讀取(反序列化)性能。
從0.25版本開始,不推薦使用msgpack格式,而且以後的版本也將刪除它。推薦使用pyarrow對pandas對象進行在線的轉換。
read_msgpack() (opens new window)僅在pandas的0.20.3版本及如下版本兼容。
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
Feather是一種可移植的文件格式,用於存儲內部使用Arrow IPC格式的Arrow表或數據幀(來自Python或R等語言)。Feather是在Arrow項目早期建立的,做爲Python和R的快速、語言無關的數據幀存儲概念的證實。
這裏須要使用到pyarrow
裏面的方法來進行操做
# 寫入 feather.write_feather(df, 'df_feather.feather') # 讀取 df = feather.read_feather('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
略慢一點,但空間上有着更大的優點。