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時, 內存會明顯被節省。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM