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时, 内存会明显被节省。