python性能(3):大文件处理思路

上节初略小结一下处理大型文件的常规思路python性能(2):multiprocessing多个参数怎么用。Python借助Pandas处理表格文件很方便,但是涉及一下大的文件,比如需要处理单个70G(笔记本内存一般16G)的csv或者txt文件,显然不能够整个将其读取运存进行分析和运算,目前我的一般思路是读取时分块,运算时并行,写出时压缩。下一节:python性能(4):pandas和geopandas读写大文件加速

pandas分块读取

以大型csv为例,可以先预览一下文件表头,使用quicklook或者读取前若干行。

1
2
3
4
5
6
7
8
9
>>> import pandas as pd
>>> geotweets = 'F:/weibo2017/geo_weibo_2017.csv'
>>> df = pd.read_csv(geotweets, header=0, encoding = 'utf-8', nrows=100)
>>> df.columns
Index(['_id', 'Comment', 'Like', 'Transfer', 'Content', 'Co_oridinate1',
'Co_oridinate2', 'PubTime', 'Tools', 'ID', 'PicNumber', 'PicLink',
'PicAllLink'],
dtype='object')
>>> df.info() # 查看列的类型

可以分块读取并保存到本地,当然也可以逐部分进行操作最后再保存。大文件为避免有行错误添加on_bad_lines=’skip’(这里的分块chunks实际上应该是生成器)

1
2
3
4
5
6
7
8
9
10
11
12
chunksize=3000000  #设置分块的行数,并筛选列
set_cols = ['_id', 'Comment', 'Like', 'Transfer', 'Content', 'Co_oridinate1',
'Co_oridinate2', 'PubTime', 'ID']
chunks = pd.read_csv(geotweets,header=0,chunksize=chunksize,low_memory=False,
usecols=set_cols, on_bad_lines='skip', encoding = 'utf-8')
path_res_split = 'F:/weibo2017/Dataset/s1_split_chunks'
i = 0
for chunk in chunks:
outFileName = '{0}_{1}{2}'.format('chunk', i, '.csv')
path_outfile = os.path.join(path_res_split, outFileName)
chunk.to_csv(path_outfile, index=False)
i = i+1

这里的写出可能会很慢,建议替换成二进制读写

写出二进制/压缩

尤其是对于中间计算过程的文件或者是仅用作备份的文件,可以写出压缩的二进制文件如Parquet、Feature、ORC等大数据列存储格式,或者pkl、,空间更小且读写更快,具体在后续补充性能比较

有个bug是这里最好得记录下环境中pandas的版本,不同的版本保存的文件读写不一定能兼容。python性能(4):pandas和geopandas读写大文件加速

1
2
3
4
5
6
7
8
9
10
11

# 推荐以下方式
chunk.to_feather(outdir+"test.feather")
df = pd.read_feather(outdir+"test.feather")

chunk.to_parquet(outdir+"test.parquet",index=False)
df = pd.read_parquet(outdir+"test.parquet")

# pickle文件格式
chunk.to_pickle(outpklfile,compression={'method': 'gzip', 'compresslevel': 1, 'mtime': 1})
df = pd.read_pickle(outpklfile,compression={'method': 'gzip', 'compresslevel': 1, 'mtime': 1})

运算加速

高效处理的一些模块和函数+Python中的多进程并行

一方面内存足够的情况下,可以简单可以采用multiprocessing多进程,或者使用Dask dataframe,后续补充使用案例,Dask dataframe Doc

同时在操作运算的时候可以多考虑:

  1. 优先使用使用内置模块及内置函数
  2. 数据类型多使用numpy数组、内置的array,以及字典和元组
  3. 列表和元组、字典可以多使用列表推导式
  4. pandas优先使用apply函数等批量运算,避免直接逐行遍历