(2022.06.21 Tues)
收集整理了Python处理大量数据的方法,基于Pandas,Numpy等数据处理工具。
查看DataFrame占用的内存大小
用df的info
方法并指定memory_usage='deep'
参数,或使用df的memory_usage
方法,并指定deep=True
参数。
>> df = pandas.DataFrame([1,2,3])
>> df.info(memory_usage='deep')
RangeIndex: 3 entries, 0 to 2
Data columns (total 1 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 0 3 non-null int64
dtypes: int64(1)
memory usage: 152.0 bytes
>> df_1.memory_usage(deep=True)
Index 132
Stkcd 4095000
...
Eranb 520000
dtype: int64
读取部分数据
读取excel/csv文件的前n行、特定位置开始的前n行
在读取数据文件的方法中加入nrows
参数选择前n行数据读取。
>> df = pd.read_excel('tmpxxx.xls', nrows=200)
>> df.shape
(20, 41)
也可以跳过m行之后,读取从m行开始的n行
跳过前100行,读取10行,注意这里返回数据没有headers
>> df = pd.read_excel('tmpxxx.xls', skiprows=100, nrows=10)
>> df.columns # 以前一行的数据作为columns,而非整个excel的headers
Index(['1997', 123626, ...,103.5], dtype='object')
当然也可以在skiprows
选项中指定范围,保留headers,即保留列名
>> df = pd.read_excel('tmpxxx.xls', skiprows=range(1, 100), nrows=10)
可以指定skiprows
中需要忽略的行,用list或array导入即可。下面是随机
>> lines = 1500000
>> skiplines = np.random.choice(np.arange(1, lines), size=lines-1-1000000, replace=False)
>> skiplines = np.sort(skiplines)
>> train = pd.read_csv('../input/train.csv', skiprows=skiplines)
如果在这个指令中忽略nrows=10
指令,则读取跳过100行之后的所有数据。
指定读入的列
预先指定读入的列,缩小加载范围
>> columns = ['ip', 'click_time', 'is_attributed']
>> df = pd.read_excel('xxx.xls', usecols = columns)
指定/修改数据的读入类型/类型
不同的数据类型占用了不同大小的空间,对于尚未读取的数据,可以提前指定类型(dtype
);对于已经读入的数据,通过astype
方法修改成占空间更小的数据类型。
在读入数据之前,通过字典指定每列对应的数据类型,读入之后按照此类型显示数据。
>> dtypes = {
'ip' : 'uint32',
'app' : 'uint16',
'device' : 'uint16',
'os' : 'uint16',
'channel' : 'uint16',
'is_attributed' : 'uint8',
}
>> train = pd.read_csv('../input/train_sample.csv', dtype=dtypes)
通过改变数据类型减少空间的案例。修改DataFrame d
中的一列Sctcd
,注意到该列的数据都是1、2、0,而保存类型是object,果断改成uint8
,通过df.info(memory_usage='deep')
方法对比内存的使用情况。仅仅修改了一个列的类型,数据大小减小3MB。
>> d = pd.read_excel('xxx.xls')
>> d.info(memory_usage='deep')
RangeIndex: 65002 entries, 0 to 65001
Data columns (total 14 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
...
2 Sctcd 65002 non-null object
...
13 Eranb 60526 non-null object
dtypes: object(14)
memory usage: 42.8 MB
>> d['Sctcd'] = d['Sctcd'].astype('uint8')
>> d.info(memory_usage='deep')
RangeIndex: 65000 entries, 2 to 65001
Data columns (total 14 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
...
2 Sctcd 65000 non-null uint8
...
13 Eranb 60524 non-null object
dtypes: object(13), uint8(1)
memory usage: 39.3 MB
一个特殊而高效的案例是当某一列的值只有有限个,不管是int还是string格式,且该列unque值远小于列的长度,可以将该列转变为category
类,将节省大量空间。这么做当然也有代价,比如转换成category
类的数据将无法做max/min等运算,由数字转换成的category
也不能进行数值运算。这种转换对内存的节省效果显著,下面是对比。dcol
只有两列,Stkcd
和Stknme
,查看unique的个数与总长度,显示unique远小于总长度,分别转换为category
类型,内存节省超过90%!
>> dcol.info(memory_usage='deep')
RangeIndex: 65002 entries, 0 to 65001
Data columns (total 2 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Stkcd 65002 non-null object
1 Stknme 65002 non-null object
dtypes: object(2)
memory usage: 9.5 MB
>> dcol['Stkcd'] = dcol['Stkcd'].astype('category')
>> dcol['Stknme'] = dcol['Stknme'].astype('category')
>> dcol.info(memory_usage='deep')
RangeIndex: 65002 entries, 0 to 65001
Data columns (total 2 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Stkcd 65002 non-null category
1 Stknme 65002 non-null category
dtypes: category(2)
memory usage: 780.0 KB
分块读取大文件.csv
通过Pandas的read_csv
方法中的chunksize
选项指定读取的块大小,并迭代地对读取的块做运算。
>> chunks = 10000
>> data = pd.read_excel('xxx.xls', chunksize=chunks)
>> for chunk in data:
# process chunk
pass
清除不用的变量并回收内存
>> tmp = df.DataFrame(...)
>> del tmp
>> import gc
>> gc.collect()
16
Reference
1 https冒号//www点dataquest点io/blog/pandas-big-data/
2 CSDN - python 处理大量数据_如何用python处理大量数据
2 How to Work with BIG Datasets on 16G RAM (+Dask), on kaggle