Выполнил Бибик Денис, ММП.
Оптимизация кода для препроцессинга данных
import pandas as pd
import numpy as np
Часть 1.Корректировка данных, слайд 13
num_elenments = 3000000
measures = [str(np.random.choice(range(100, 200))) + '/' + str(np.random.choice(range(80, 100)))
for i in range(num_elenments)]
df_ = pd.DataFrame(measures, columns = ['Давление'])
df_.head()
Давление | |
---|---|
0 | 195/87 |
1 | 116/93 |
2 | 146/91 |
3 | 172/84 |
4 | 147/98 |
Перед каждым экспирементом будем копировать датасет
df = df_.copy()
%%time
#Оригинальный код
tmp = df['Давление'].str.split('/')
df['в.давл.'] = tmp.apply(lambda x: x[0])
df['н.давл.'] = tmp.apply(lambda x: x[1])
CPU times: user 8.89 s, sys: 588 ms, total: 9.48 s Wall time: 9.47 s
df = df_.copy()
%%time
#Попробуем избавится от apply
tmp = df['Давление'].str.split('/').str
df['в.давл.'] = tmp.get(0)
df['н.давл.'] = tmp.get(1)
CPU times: user 8.88 s, sys: 644 ms, total: 9.52 s Wall time: 9.44 s
df = df_.copy()
%%time
#Теперь импользуем встроенную параметр expand
df[['в.давл.', 'н.давл.']] = df['Давление'].str.split('/', expand=True)
CPU times: user 4.82 s, sys: 164 ms, total: 4.99 s Wall time: 4.99 s
Ускорение почти в два раза
df = df_.copy()
%%time
#Попробуем такой вариант, он не будет работать если будут ошибки в формате
st = '/'.join(df['Давление'])
df[['в.давл.', 'н.давл.']] = pd.DataFrame(np.array(st.split('/')).reshape(-1, 2))
CPU times: user 963 ms, sys: 164 ms, total: 1.13 s Wall time: 1.13 s
Ускоорение в 8 раз
Часть 2. Заполнение данных, слайд 19
num_elements = 5000000
train_len = int(0.75 * num_elements)
num_nan = 300000
df_ = pd.DataFrame(np.random.choice(a = range(60, 100), size = (num_elements, 1)), columns = ['площадь'])
df_['data'] = ['train'] * train_len + ['test'] * (num_elements - train_len)
nan_positions = np.random.choice(num_elements, num_nan, replace=False)
df_.loc[nan_positions, 'площадь'] = np.nan
df_.head()
площадь | data | |
---|---|---|
0 | 72.0 | train |
1 | 73.0 | train |
2 | 93.0 | train |
3 | 69.0 | train |
4 | 80.0 | train |
df = df_.copy()
%%time
#Оригинальный код
df.loc[df['data'] == 'train', 'площадь'] =\
df[df['data'] == 'train']['площадь'].fillna(df[df['data'] == 'train']['площадь'].mean())
df.loc[df['data'] == 'test', 'площадь'] =\
df[df['data'] == 'test']['площадь'].fillna(df[df['data'] == 'test']['площадь'].mean())
CPU times: user 2.58 s, sys: 132 ms, total: 2.71 s Wall time: 2.71 s
df = df_.copy()
%%time
#Используем transform
gb = df.groupby('data')
df['площадь'] = gb.transform(lambda x: x.fillna(x.mean()))
CPU times: user 849 ms, sys: 304 ms, total: 1.15 s Wall time: 1.15 s
Ускорение более чем в два раза
df = df_.copy()
Разберемся что сколько времени занимает в коде выше
%%time
gb = df.groupby('data')
iterate = list(gb)
del iterate
CPU times: user 417 ms, sys: 120 ms, total: 537 ms Wall time: 536 ms
%%time
m = gb.mean()
CPU times: user 37.6 ms, sys: 15.9 ms, total: 53.6 ms Wall time: 52.4 ms
%%time
df['площадь'] = gb.transform(lambda x: x.fillna(0))
CPU times: user 628 ms, sys: 240 ms, total: 868 ms Wall time: 867 ms
Получается что transform занимает значимую часть времени
df = df_.copy()
%%time
gb = df.groupby('data')
mean = gb.mean()
for gn, x in gb:
x['площадь'].fillna(mean.loc[gn])
CPU times: user 709 ms, sys: 188 ms, total: 897 ms Wall time: 895 ms
Ускорили еще на 250 мс