• python数据处理中内存优化的一些tricks


    1、读入数据时,pandas默认int类型为int64,未采用最省类型方式读取,可通过以下方式优化内存

    1)数值型能用更低内存类型保存就转换为更低内存类型

       

     2) 将object类型转换为category类型

         category 类型在底层使用整型数值来表示该列的值,而不使用原值.Pandas用一个字典来构建这些整型数据到原数据的映射关系.当一列只包含有有限种值时,这种设计不错。当我们把一列转换为category类型时,pandas会用一种最省空间的int子类型来表示这一列,对于缺失值,category子类型会将缺失数据设为-1.如果某一列全都是唯一值,category类型将会占用更多内存,这是因为这样做不仅要存储全部的原始字符串数据,还要存储整型类别标识.

    代码如下:

    def reduce_mem_usage(df, verbose=True):

        numerics = ['int16', 'int32', 'int64', 'float16', 'float32', 'float64']

             cateics = ['object']

        start_mem = df.memory_usage().sum() / 1024**2

        for col in df.columns:

            col_type = df[col].dtypes

                       num_unique_values = len(df[col].unique())

                       num_total_values = len(df[col])

            if col_type in numerics:

                c_min = df[col].min()

                c_max = df[col].max()

                if str(col_type)[:3] == 'int':

                    if c_min > np.iinfo(np.int8).min and c_max < np.iinfo(np.int8).max:

                        df[col] = df[col].astype(np.int8)

                    elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max:

                        df[col] = df[col].astype(np.int16)

                    elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max:

                        df[col] = df[col].astype(np.int32)

                    elif c_min > np.iinfo(np.int64).min and c_max < np.iinfo(np.int64).max:

                        df[col] = df[col].astype(np.int64)

                else:

                    if c_min > np.finfo(np.float16).min and c_max < np.finfo(np.float16).max:

                        df[col] = df[col].astype(np.float16)

                    elif c_min > np.finfo(np.float32).min and c_max < np.finfo(np.float32).max:

                        df[col] = df[col].astype(np.float32)

                    else:

                        df[col] = df[col].astype(np.float64)

                       if (col_type in cateics) and (num_unique_values*1.0/num_total_values < 0.5):

                           df[col] = df[col].astype('category')

             end_mem = df.memory_usage().sum() / 1024**2

        if verbose:

            print('Mem. usage decreased to {:5.2f} Mb ({:.1f}% reduction)'.format(

                end_mem, 100 * (start_mem - end_mem) / start_mem))

        return df

    2、分批读入处理
          pandas.read_csv('',iterator = True, chunksize = 10000)
    分批处理数据:
    如取众数,即分批求类别次数后,再在外面整合求所有类别次数,得到次数最大类别
    如取平均值,记录分批长度及平均值,再在外面整合最终平均值
    如取中位数,即分批求类别次数后,再在外面整合求所有类别次数,排序后得到中间次数类别

    3、及时回收不需要的变量
    import gc
    del a
    gc.collect()

    4、pandas.read_csv 使用指定列,指定类型读取,指定时间读取,低内存消耗等等
    1) dtype:指定每列数据的数据类型,如{'a':np.float64,'b':np.int32}

    2) usecols:返回一个数据子集,这个参数可以加快加载速度并降低内存消耗

    3) low_memory:分块加载到内存,在低内存消耗解析,可能出现类型混淆。为避免类型混淆,需设置False,或者使用dtype参数指定类型。

    4) memory_map:
    如果使用文件在内存内,直接map文件使用.使用这种方式可以避免文件再次IO操作

    5) parse_dates:
    boolean.True -> 解析索引
    list of ints or names. e.g. If [1,2,3] -> 解析1,2,3列的值作为独立的日期列;
    list of lists. e.g.If [[1,3]] -> 合并1,3列作为一个日期列使用
    dict, e.g. {'foo':[1,3]} -> 将1,3列合并,并给合并后的列起名为"foo"

    5、谨防驻留字符串
    python会记录如字符串等不可改变的值(其每个值的大小依赖于实现方法)

    t = "abcdefghijklmnopqrstuvwxyz"
    p = "abcdefghijklmnopqrstuvwxyz"
    id(t)
    id(p)

    如果两个字符串拥有相同的ID或引用——他们是全等的

    如果你的程序创建了许多小的字符串,你的内存就会出现膨胀

    6、生成字符串时使用Format来代替"+"

    st = "{0}_{1}_{2}_{3}".format(a,b,c,d) #对内存更好,不创建临时变量
    st2 = a + '_' + b + '_' + c + '_' + d #在每个"+"时创建一个临时str, 这些都是驻留在内存中的

    当我们将某些字符串构造从"+" 变为使用format时, 内存会明显被节省。

  • 相关阅读:
    (jmeter笔记)jmeter远程启用服务器(分布式)
    (jmeter笔记)jmeter打印日志
    (jmeter笔记)Jmeter正则表达式提取器获取Response hearders
    css3实现好看的边框效果
    简单递归写侧边菜单栏
    css3的transform-origin配合scale,控制动画,实现各种hover效果
    浅谈jQuery的promise
    tips07-encodeURI()的使用
    weui 的使用方法
    git 合并分支的时候会遇到的问题
  • 原文地址:https://www.cnblogs.com/dudumiaomiao/p/12902718.html
Copyright © 2020-2023  润新知