Python处理大数据的技巧, 2022-06-21

(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只有两列,StkcdStknme,查看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

你可能感兴趣的:(Python处理大数据的技巧, 2022-06-21)