说明
在数据科学领域,python应当是目前最为常用的开发语言。由于数据分析、机器学习大部分时间基本在处理数据集,对于一般大小的数据文件,采用pandas读取基本已经足够。但若一个数据集大小达到1G甚至10G,pandas读取就显得效率太低,变得不再实用。
那么有哪些应对大数据集的提速处理方式呢?本文从以下两个角度说明几种提供数据处理速度的方式:
- 相较pandas,python中提速方式
- 采用c++处理数据,实现提速
pandas read_csv
数据科学中,典型的结构化数据存储形式为csv格式,通常是用pandas来对其进行操作:
df_data = pd.read_csv(r'data/df_data.csv')
df_data.info()
一般情况下,我们所处理的单个csv文件大小不会超过100M。pandas基本可以较快地对其进行读取和操作。但当达到几个G的大小时,pandas直接处理就显得力不从心。速度慢是一方面,若文件太大,内存可能都无法读入全部的数据,比如下图所示:
下面说明几种提速方式,并给出相应的用法。
python 中的提速方式
pandas read_csv的chunksize
字段
chunks = pd.read_csv(r'data/df_data.csv', chunksize=5000)
df_data = pd.concat(chunks)
df_data.info()
可以看到,通过增加chunksize
字段,读取时间反而有所上升。这是由于chunksize
的大小影响了读取的速度,因此,要想通过这一字段提速,前提是能够选择合适大小的chunksize,否则反而对读取效率产生负面影响。
pandas read_csv的engine
字段
df_data = pd.read_csv(r'data/df_data.csv', engine='c')
df_data.info()
可以看到,通过将读取csv的后端引擎更改为C语言
,读取效率有明显提升。
dask dataframe
dask是由google主导开发的适用于大数据集的pandas替代方案。一直以来,spark在大数据分析领域占据主导领域,近年来,之前采用spark的用户也在开始切换到dask上来。另外,同时存在一些其他的处理方案,比如Ray和Vaex。在使用覆盖面上,dask是被使用最多的,。Ray是由Berkeley主导开发的,Vaex主要是由荷兰的程序员和数据科学家开发的。初看各家发展生态,dask应当是更胜一筹。
dask本身主要存在两点优势:
- 并行化:相较于pandas单核处理数据,dask可以进行多线程并行处理数据;
- delayed计算:dask采用一种lazy的方式,对数据进行处理。所谓的lazy计算,是以仅保存计算流程图的方式,记录计算目标的计算流程。但并不执行计算本身。只有需要获取计算目标结果时,通过
compute()
来执行整个计算流程,获得输出结果。
其用法如下:
import dask.dataframe as dd
data = dd.read_csv(r'data/output/df_data.csv')
df_data = data.compute()
df_data.info()
可以看到,相比于pandas直接读取,dask读取整个数据集所需时间降低了1/3,是提速表现最好的。
通过c++进行数据处理提速
前面我们看到,通过python处理一个数据集,将其保存到一个numpy array对象中,该对象大小达到9G。无法将其保存为dataframe对象写入到本地csv文件中,也无法通过numpy、pickle写入到本地。原因都是太占内存(MemoryError)。如果无法将其保存到本地,那么目标数据就无法持久化,也就降低了重复使用性。
既然无法直接通过python将该对象存储到本地文件中,此时想出了下面的解决办法:
- 先将numpy array对象转换为list对象,然后通过python将该list对象写入到本地txt。出乎意料的是,python将这么大的对象写入到txt的速度出奇的快,9个G大小的list对象,写入到本地txt完成所花时间不到30s;
with open(r'all_vals.txt', 'w', encoding="utf-8") as fp: for item in contents: fp.write("%s\n" % item)
- 通过c++将该txt文件准换为csv文件。c++本身作为基础编程语言,在效率上一直是其最大的优势:
将2个多G的txt文件重新写入到csv文件,所需时间为5分钟左右。整体而言,通过转换思路,并借助于python之外的开发语言,使我们的数据开发效率得到很大的提升。string file_name = "all_vals.txt"; string nfile_name = "all_vals.csv"; ifstream in(file_name); string line; ofstream textfile; textfile.open(nfile_name); const char* bom = "\xef\xbb\xbf"; // 写入csv,需要加上bom头,否则写入中文乱码 textfile << bom; while (getline(in, line)) // line中没有换行符 { string ss = line.substr(1,line.length() - 2); textfile << ss << endl; }
小结
- 在应对csv大数据集的读取上,采用dask能够显著提高效率,这也是最终我们采取的数据集处理方式
- 当涉及大数据集的读取写入时,可以采用c++来完成我们的数据准备工作。