python - 编写 BIG pandas DataFrame 的最快方法
问题描述
我进行了一项测试,测试了 10 种写入方法和 10 种读取 DataFrame 的方法。我在这里找到了测试(我做了一些调整并将 Parquet 添加到列表中)最好的方法是:
df.to_feather('test.feather') :
39.34544535900204s
table=pyarrow.Table.from_pandas(df)
pq.write_table(table, "test_parquet_write_snappy_dict.parquet",
use_dictionary=True, version='2.0', compression='snappy') :
40.6873751259991s
table=pyarrow.Table.from_pandas(df, nthreads=4)
pq.write_table(table, "test_parquet_write_snappy_dict.parquet",
use_dictionary=True, version='2.0', compression='snappy') :
41.051620177000586s
为了写作
和
pd.read_hdf('test_fixed.hdf', 'test') :
1.5275615360005759
pd.read_feather('test.feather') :
20.635139821002667
pd.read_pickle('test.pkl') :
37.21131302599679
为阅读。
这是数据框:
sz = 50000000
df = pd.DataFrame({'A': randn(sz), 'B': randn(sz), 'C': randn(sz), 'D': randn(sz)})
我有两个问题。怎么read_hdf
比 read_feather 快 20 倍,to_hdf
甚至在前三个写测试中都没有?
第二个,40 秒对于我的需要来说仍然太慢了。有没有办法提高这个速度?通过使用不同的参数to_feather
或write_table
使用我不知道的功能/模块?
我不是要别人来找我,我可以自己做,我不想浪费任何人的时间。我正在寻找已经知道这个问题并且可以引导我以他知道的最快方式的人。
解决方案
这本身并不完全是一个答案,但这里有一个更彻底的基准,对像你这样的数据的各种方法......
import timeit
import numpy as np
import pandas as pd
from numpy.random import randn, randint
def generate_data(n):
df = pd.DataFrame(
{
"dt": randint(1_600_000_000, 1_700_000_000, size=n) * 1000,
"a": randn(n),
"b": randn(n),
"c": randn(n),
}
)
df.dt = pd.to_datetime(df.dt, unit="s")
df.set_index("dt", inplace=True)
return df
def benchmark(df, name, saver, loader):
verify(df, loader, saver)
save_timer = timeit.Timer(lambda: saver(df))
load_timer = timeit.Timer(lambda: loader().a.sum())
save_n, save_time = save_timer.autorange()
load_n, load_time = load_timer.autorange()
total_time = (load_time / load_n) + (save_time / save_n)
print(
f"{name:<15s} : "
f"{save_n / save_time:>20.3f} save/s : "
f"{load_n / load_time:>20.3f} load+sum/s : "
f"{1 / total_time: >20.3f} total speed"
)
def verify(df, loader, saver):
saver(df)
loaded = loader()
assert np.allclose(loaded.a.sum(), df.a.sum())
assert np.allclose(loaded.b.sum(), df.b.sum())
assert list(loaded.columns) == list(df.columns), loaded.columns
def save_feather(df):
df = df.reset_index()
df.to_feather("dummy.feather")
def load_feather():
df = pd.read_feather("dummy.feather")
df.set_index("dt", inplace=True)
return df
def main():
df = generate_data(5_000_000)
benchmark(df, "dummy", lambda df: None, lambda: df)
benchmark(df, "csv", lambda df: df.to_csv("dummy.csv"), lambda: pd.read_csv("dummy.csv", index_col="dt"))
benchmark(df, "hdf", lambda df: df.to_hdf("dummy.h5", "dummy"), lambda: pd.read_hdf("dummy.h5", "dummy"))
benchmark(df, "pickle", lambda df: df.to_pickle("dummy.pickle"), lambda: pd.read_pickle("dummy.pickle"))
benchmark(df, "feather", save_feather, load_feather)
benchmark(
df,
"parquet",
lambda df: df.to_parquet("dummy.parquet", allow_truncated_timestamps=True),
lambda: pd.read_parquet("dummy.parquet"),
)
if __name__ == "__main__":
main()
在我的盒子(Ryzen 7 3700X、SSD 磁盘、Windows 10、Python 3.8、最新的 Pandas 等)和一百万行的 DF(懒得等待 CSV 结果)上,我得到
dummy : 10475677.467 save/s : 186.737 load+sum/s : 186.734 total speed
csv : 0.185 save/s : 0.970 load+sum/s : 0.156 total speed
hdf : 18.289 save/s : 28.514 load+sum/s : 11.142 total speed
pickle : 14.058 save/s : 31.962 load+sum/s : 9.764 total speed
feather : 34.766 save/s : 41.436 load+sum/s : 18.904 total speed
parquet : 7.707 save/s : 19.603 load+sum/s : 5.532 total speed
所以 HDF5 绝对不会快几个数量级。
推荐阅读
- python - add a image with given coordination (lat, lon) on the cartopy map
- python-3.x - Aligning nifti files with different shape and q_offset values in header
- azure - Adding same resource in multiple resource groups
- c++ - 使用 MSVC 的模块中的访问冲突
- python - 将 PySpark Dataframe 列拆分为多个
- ios - Are there recommended ways for drawing 2d array in fast time?
- node.js - 在heroku中创建(克隆)相同的应用程序进行开发
- python - 无论 django 中的用户如何,都从数据库中获取最新对象
- php - PHP 中的空格错误,需要标识符
- arrays - 通过将它们合并为一个数组在同一页面上显示两个数组 - 反应原生