別再用CSV了,更高效的Python文件存儲方案


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
import fastparquet as fp

生成隨機數據

這里使用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

csv + gz

基於自帶的壓縮方法,對保存的csv文件使用gzip算法進行壓縮

# 寫入
df.to_csv('./df_csv.csv.gz', index=False, compression='gzip')
# 讀取
df = pd.read_csv('./df_csv.csv.gz', compression='gzip')

寫入時間花費:259 s

讀取時間花費:22.8 s

所需存儲空間:508M

csv + zip

基於自帶的壓縮方法,對保存的csv文件使用zip算法進行壓縮

# 寫入
df.to_csv('./df_csv.csv.zip', index=False, compression='zip')
# 讀取
df = pd.read_csv('./df_csv.csv.zip', compression='zip')

寫入時間花費:177 s

讀取時間花費:20.7 s

所需存儲空間:511M

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')
# 讀取
df = feather.read_feather('df_feather.feather')

寫入時間花費:1.9 s

讀取時間花費:1.52 s

所需存儲空間:715M

總結

對比表格

文件類型 寫入時間(s) 讀取時間(s) 存儲空間(MB)
csv 78.00 11.80 1,300
csv+gz 259.00 22.80 508
csv+zip 177.00 20.70 511
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

時間對比

讀寫時間對比.jpg

空間對比

存儲空間對比.jpg

可以看出parquet會是一個保存文件的最好選擇,雖然時間上比feature略慢一點,但空間上有着更大的優勢。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM