Pandas: своеобразное падение производительности для переименования на месте после dropna

Я сообщил об этом как о проблеме навопросы панд, Тем временем я публикую это здесь в надежде сэкономить время других, если они столкнутся с похожими проблемами.

После профилирования процесса, который необходимо оптимизировать, я обнаружил, что переименование столбцов НЕ на месте повышает производительность (время выполнения) на x120. Профилирование указывает, что это связано со сборкой мусора (см. Ниже).

Кроме того, ожидаемая производительность восстанавливается, избегая метода dropna.

Следующий короткий пример демонстрирует коэффициент x12:

import pandas as pd
import numpy as np
Inplace = True
%%timeit
np.random.seed(0)
r,c = (7,3)
t = np.random.rand(r)
df1 = pd.DataFrame(np.random.rand(r,c), columns=range(c), index=t)
indx = np.random.choice(range(r),r/3, replace=False)
t[indx] = np.random.rand(len(indx))
df2 = pd.DataFrame(np.random.rand(r,c), columns=range(c), index=t)
df = (df1-df2).dropna()
## inplace rename:
df.rename(columns={col:'d{}'.format(col) for col in df.columns}, inplace=True)

100 циклов, лучшее из 3: 15,6 мс на цикл

первая строка вывода%%prun:

ncalls totaltime percall cumtime percall имя файла: lineno (функция)

1  0.018 0.018 0.018 0.018 {gc.collect}
Inplace = False
%%timeit
np.random.seed(0)
r,c = (7,3)
t = np.random.rand(r)
df1 = pd.DataFrame(np.random.rand(r,c), columns=range(c), index=t)
indx = np.random.choice(range(r),r/3, replace=False)
t[indx] = np.random.rand(len(indx))
df2 = pd.DataFrame(np.random.rand(r,c), columns=range(c), index=t)
df = (df1-df2).dropna()
## avoid inplace:
df = df.rename(columns={col:'d{}'.format(col) for col in df.columns})

1000 циклов, лучшее из 3: 1,24 мс на цикл

избегать дропна

Ожидаемая производительность восстанавливается, избегаяdropna метод:

%%timeit
np.random.seed(0)
r,c = (7,3)
t = np.random.rand(r)
df1 = pd.DataFrame(np.random.rand(r,c), columns=range(c), index=t)
indx = np.random.choice(range(r),r/3, replace=False)
t[indx] = np.random.rand(len(indx))
df2 = pd.DataFrame(np.random.rand(r,c), columns=range(c), index=t)
#no dropna:
df = (df1-df2)#.dropna()
## inplace rename:
df.rename(columns={col:'d{}'.format(col) for col in df.columns}, inplace=True)

1000 петель, лучшее из 3: 865 мкс на петлю

%%timeit
np.random.seed(0)
r,c = (7,3)
t = np.random.rand(r)
df1 = pd.DataFrame(np.random.rand(r,c), columns=range(c), index=t)
indx = np.random.choice(range(r),r/3, replace=False)
t[indx] = np.random.rand(len(indx))
df2 = pd.DataFrame(np.random.rand(r,c), columns=range(c), index=t)
## no dropna
df = (df1-df2)#.dropna()
## avoid inplace:
df = df.rename(columns={col:'d{}'.format(col) for col in df.columns})

1000 петель, лучшее из 3: 902 мкс на петлю

Ответы на вопрос(1)

Ваш ответ на вопрос