使用Pandas和/或Numpy进行读/写操作的最快文件格式

c_d*_*vid 21 python numpy pandas

我已经使用非常大的DataFrame工作了一段时间,我一直在使用csv格式来存储输入数据和结果.我注意到大量时间用于读取和写入这些文件,例如,这会大大减慢批处理数据的速度.我想知道文件格式本身是否相关.是否有更快的读/写Pandas DataFrames和/或Numpy数组的首选文件格式?

Jef*_*eff 20

使用HDF5.节拍写平面文件.你可以查询.文件在这里

这是与SQL的性能比较.更新为显示SQL/HDF_fixed/HDF_table/CSV写入和读取perfs.

文档现在包含一个性能部分:

看到这里

  • 我不知道自 2014 年以来性能部分是否已被编辑,但现在那里的结果表明羽毛和泡菜比 HDF 更快。但我认为 HDF 有更广泛的采用? (2认同)
  • 链接已移至[https://pandas.pydata.org/pandas-docs/stable/io.html#performance-considerations](https://pandas.pydata.org/pandas-docs/stable/io.html #性能考虑因素) (2认同)

Ary*_*rog 9

为您的用例运行一些基准测试总是一个好主意.通过numpy存储原始结构我有很好的结果:

df.to_records().astype(mytype).tofile('mydata')
df = pd.DataFrame.from_records(np.fromfile('mydata', dtype=mytype))
Run Code Online (Sandbox Code Playgroud)

它非常快,占用磁盘空间更少.但是:您需要跟踪dtype以重新加载数据,它不能在架构之间移植,并且它不支持HDF5的高级功能.(numpy有一个更高级的二进制格式,旨在克服前两个限制,但我没有取得太大的成功让它工作.)

更新: 感谢您按下我的号码.我的基准测试表明HDF5确实赢了,至少在我的情况下.这是双方更快更小的磁盘上!这是我在数据帧中看到的大约280k行,7个浮点列和一个字符串索引:

In [15]: %timeit df.to_hdf('test_fixed.hdf', 'test', mode='w')
10 loops, best of 3: 172 ms per loop
In [17]: %timeit df.to_records().astype(mytype).tofile('raw_data')
1 loops, best of 3: 283 ms per loop
In [20]: %timeit pd.read_hdf('test_fixed.hdf', 'test')
10 loops, best of 3: 36.9 ms per loop
In [22]: %timeit pd.DataFrame.from_records(np.fromfile('raw_data', dtype=mytype))
10 loops, best of 3: 40.7 ms per loop
In [23]: ls -l raw_data test_fixed.hdf
-rw-r----- 1 altaurog altaurog 18167232 Apr  8 12:42 raw_data
-rw-r----- 1 altaurog altaurog 15537704 Apr  8 12:41 test_fixed.hdf
Run Code Online (Sandbox Code Playgroud)


rah*_*nri 6

HDF 确实是一个非常好的选择,您也可以使用 npy/npz 并有一些注意事项:

这是一个使用随机浮点数填充的 25k 行和 1000 列数据框的基准测试:

Saving to HDF took 0.49s
Saving to npy took 0.40s
Loading from HDF took 0.10s
Loading from npy took 0.061s
Run Code Online (Sandbox Code Playgroud)

如果不压缩数据,npy 的写入速度大约快 20%,读取速度大约快 40%。

用于生成上述输出的代码:

#!/usr/bin/python3

import pandas as pd
import random
import numpy as np
import time

start = time.time()
f = pd.DataFrame()
for i in range(1000):
  f['col_{}'.format(i)] = np.random.rand(25000)
print('Generating data took {}s'.format(time.time() - start))

start = time.time()
f.to_hdf('frame.hdf', 'main', format='fixed')
print('Saving to HDF took {}s'.format(time.time() - start))

start = time.time()
np.savez('frame.npz', f.index, f.values)
print('Saving to npy took {}s'.format(time.time() - start))

start = time.time()
pd.read_hdf('frame.hdf')
print('Loading from HDF took {}s'.format(time.time() - start))

start = time.time()
index, values = np.load('frame.npz')
pd.DataFrame(values, index=index)
print('Loading from npy took {}s'.format(time.time() - start))
Run Code Online (Sandbox Code Playgroud)


Raf*_*ini 6

最近,熊猫使用库作为后台添加了对拼花格式的支持pyarrow(由韦斯·麦金尼本人撰写,他一向对性能有痴迷)。

你只需要安装pyarrow库,并使用方法read_parquetto_parquet。对于较大的数据集(几百兆字节或更多),Parquet的读写速度要快得多,并且它还可以跟踪dtype元数据,因此在从磁盘进行读写时,您不会丢失数据类型信息。实际上,它可以更有效地存储HDF5性能不佳的某些数据类型(例如字符串和时间戳:HDF5没有用于这些数据类型的本机数据类型,因此它使用pickle对其进行序列化,这对于大型数据集来说很慢)。

Parquet也是一种柱状格式,可以很容易地完成两件事:

  • 快速过滤掉您不感兴趣的列。使用CSV,您必须实际读取整个文件,然后才能丢弃不需要的列。使用实木复合地板,您实际上只能读取您感兴趣的列。

  • 进行查询以筛选出行并仅读取您关心的内容。

最近另一个有趣的发展是Feather文件格式,它也是由Wes Mckinney开发的。它本质上只是arrow直接写入磁盘的未压缩格式,因此它的写入速度可能比Parquet格式更快。缺点是文件要大2-3倍。


art*_*oby 5

如果优先考虑速度,我会建议:

  • 羽毛 - 最快
  • parquet - 慢一点,但节省大量磁盘空间