都 2021 年了,您还用 Pandas 处理大数据呐
Pandas 对大数据的处理并不咋地,本文介绍两个 Python 处理大数据的支持库,并对这三个 Python 数据处理支持库进行对比。
先说说大数据的概念。本文中的大数据指的是比你的电脑内存大的数据,并非动辄几个 T 的那种大数据,那些数据单机也处理不了,你看了也没啥用。
本文要介绍的两个支持库是 Dask 和 Vaex,这两个库已经推出有几年了,现在也比较成熟了。
Dask 主要是通过并行技术提高数据处理速度。
Vaex 号称可以每秒处理十亿行数据的统计操作,还支持可视化,还可以实现交互式数据探索。
这两个支持库与 Pandas 的 df 并不完全兼容,但语法也差不多,而且都支持最常见的数据处理操作,只不过 Dask 偏重于使用集群技术处理数据,而 Vaex 则偏重于在单机上处理大数据。
测试数据
随机生成两个 100 万行,1000 列的 CSV 文件,每个文件 18G,两个 36G,数据是 0-100 之间均匀分布的随机数。
import pandas as pd
import numpy as np
from os import path
n_rows = 1_000_000
n_cols = 1000
for i in range(1, 3):
filename = 'analysis_%d.csv' % i
file_path = path.join('csv_files', filename)
df = pd.DataFrame(np.random.uniform(0, 100, size=(n_rows, n_cols)), columns=['col%d' % i for i in range(n_cols)])
print('Saving', file_path)
df.to_csv(file_path, index=False)
df.head()
测试环境
- MacBook Pro,内存 32G
- 禁用虚拟内存,在测试时将硬盘空间填满,只使用实际内存。
测试内容
- 计算分位数
- 添加新列
- 过滤列值
- 按列分组汇总
- 可视化
测试效果
Pandas
读取不了 18G 的文件,直接玩儿完, Jupyter 内核泪崩。
Vaex
将两个 CSV 文件转为 HDF5 格式
import vaex
csv_files = glob.glob('csv_files/*.csv')
for i, csv_file in enumerate(csv_files, 1):
for j, dv in enumerate(vaex.from_csv(csv_file, chunk_size=5_000_000), 1):
print('Exporting %d %s to hdf5 part %d' % (i, csv_file, j))
dv.export_hdf5(f'hdf5_files/analysis_{i:02}_{j:02}.hdf5')
转换为 HDF5:不到 7 分钟,转换后,两个文件大小降低到 16G。
打开文件: dv = vaex.open('hdf5_files/*.hdf5')
,用时 20 分钟,如果转换为二进制文件会更快
显示 Head: dv.head()
,差一点就 20 分钟,莫名其妙!!!
计算分位数:quantile = dv.percentile_approx('col1', 10)
,秒出
添加新列:dv ['col1_binary'] = dv.col1> dv.percentile_approx('col1',10)
,秒出
过滤数据:dv = dv[dv.col2 > 10]
,秒出
分组汇总: group_res = dv.groupby(by=dv.col1_binary, agg={'col3_mean': vaex.agg.mean('col3')})
,秒出
可视化直方图:plot = dv.plot1d(dv.col3, what='count(*)', limits=[0, 100])
,秒出
汇总全部数据:suma = np.sum(dv.sum(dv.column_names))
,40 秒
Dask
转换为 HDF5:超过 12 分钟
import dask.dataframe as dd
ds = dd.read_csv('csv_files/*.csv')
ds.to_hdf('hdf5_files_dask/analysis_01_01.hdf5', key='table')
打开文件: 秒开,但这是因为没有使用 compute
,这个命令才要命
import dask.dataframe as dd
ds = dd.read_csv('csv_files/*.csv')
显示 Head: ds.head()
,9 秒
计算分位数:quantile = ds.col1.quantile(0.1).compute()
,此时用了 compute
,结果 Jupyter 内核崩了
添加新列:ds['col1_binary'] = ds.col1 > ds.col1.quantile(0.1)
,不支持分位数,无法测试
过滤数据:ds = ds[(ds.col2 > 10)]
,秒出
分组汇总:Dask 不支持分组汇总
可视化直方图:Dask 不支持可视化数据
汇总全部数据:Dask 不支持汇总全部数据
这也不支持,那也不支持,没啥可比的了
测试结论
- Vaex 要把 CSV 转为 HDF5 才能发挥优势,head 耗时那么长实在是令人费解,其它操作都很快。
- Dask 的优化主要是针对集群而非单机,如果你是单机就不推荐了
- Pandas 确实没法比,就不说了。
看完了这个测试,各位心里有点概念了吧,有兴趣的可以自己测试下。