Pandas高速低内存计算技巧

参加大数据竞赛过程中,自己琢磨了一些pandas高速低内存计算的技巧,总结于此。

原则

(1)磨刀不误砍柴工。对于运算时间过长的程序,一定要花功夫优化处理,提高运行速度。
(2)不求尽善尽美,以解决问题为导向。没有必要花一个小时时间去优化一个本来需要30分钟运行完的程序。
(3)运算时间较长、内存耗用较大的程序,要先运行小比例试验,检查程序正确性并估算总运行时间和峰值内存耗用,有准确估计后再运行完整程序。
(4)运算时间较长、内存耗用较大的程序,要有跑马灯定量报时或定时报告机制,并打开资源监视器跟踪CPU和内存的使用,发现程序有问题或内存耗尽时及时中断。

高速计算技巧:

高速计算技巧一:使用groupby()方法分组并行运算,避免元素遍历

table_byline['Stop'] = table_byline.O_NEXTSTATIONNO.groupby(table_byline.O_TERMINALNO).diff()

groupyby可以直接用的优化过的高速运算方法有count()、sum()、prod()、mean()、median()、min()、max()、std()、var()、first()、last()。因为groupby按指定列元素分组后成为一个个小的Series或DataFrame,所以也可以使用各种Series或DataFrame的方法。还可以使用自定义的函数,即grouped.apply(func)或grouped.agg(func)。

高速计算技巧二:必须遍历时,使用apply()方法,避免使用循环

table_test['new']=np.nan
def func(df):
    i=df.ID
    ids=table_train.ID[table_train.ID1)
    idx=table_train.ID[table_train.ID>i].head(1)
    if len(ids)==0:
        y=table_train.发电量.loc[idx].iloc[0]
    elif len(idx)==0:
        y=table_train.发电量.loc[ids].iloc[0]
    else:
        ids=ids.iloc[0]
        idx=idx.iloc[0]
        ys=table_train.发电量.loc[ids]
        yx=table_train.发电量.loc[idx]
        y=yx+(ys-yx)/(ids-idx)*(i-idx)
    return y
table_test['new']=table_test.apply(func,axis=1)

在该程序示例中,如果for循环逐行遍历运行速度很慢。先把循环内容定义为函数func,再使用apply方法逐行遍历调用func,速度可按数量级提高。注意,虽然是逐行遍历,但需指定axis=1.

高速计算技巧三:必须循环时,使用层次化索引筛选数据,避免使用条件逻辑筛选

table_s=table_s.station_id.groupby([table_s.line,table_s.up,table_s.station_no]).min()
table_fine1['s_id']=np.nan
    for upj in [0,1]:
        s_lst=table_fine1.O_NEXTSTATIONNO[table_fine1.up==upj].drop_duplicates().tolist()
        for sk in s_lst:
            table_fine1['s_id'][(table_fine1.up==upj)&
            (table_fine1.O_NEXTSTATIONNO==sk)]=table_s.loc[line,upj,sk]

本例中,先把table_s转为层次化索引的Series,然后按索引值直接检索数据,这比采用形如df[(df.col1==a)&(df.col2==b)]这种条件逻辑筛选法程序更简洁,运行也更快一些。

高速计算技巧四:使用多CPU核心分块并行运算

对于可分块运行的数据运算任务,可使用多线程类编程,调用多个CPU核心并行工作提高速度。如果不会多线程编程,也可以简单的在Jupyter Notebook中打开多个页面,每个页面跑一个程序,只把每个程序中需要运行的数据块手动设置好,也可以达到调用多个CPU核心的目的。

低内存技巧

低内存技巧一:降精度读取数据

使用pd.read_csv()读取数据时,默认按64位精度读取数据,且有的数据读取为object类型,这些都极耗内存。可根据实际需要采用低位精度读取,并指定object类型为实际的类型或category类型,只读取需要处理的列。如

columns = ['O_LINENO','O_TERMINALNO','O_TIME','O_UP','O_NEXTSTATIONNO']
col_types = ['uint16','int32','category','int8','uint8']
columns_types = dict(zip(columns, col_types))
table_all = pd.read_csv(FOLDER + '\\' + 'table_all.csv',usecols=columns,dtype=columns_types)
table_all.O_TIME=pd.to_datetime(table_all.O_TIME)

低内存技巧二:使用gc.collect()及时回收不用的内存

import gc
gc.collect()

你可能感兴趣的:(机器学习)