Recosh
@Recosh
Программист студент

Как оптимизировать (векторизировать) функцию в pandas с обращением к предыдущей строке в dataframe?

Приветствую! Прошу помощи в оптимизации кода. Нужно в отдельную колонку поместить разницу с предыдущем значением. Но если значение отличается в соседней колонке от значения над ним, то считать как новое значение. Вот пример:
import pandas as pd
import numpy as np

data = {
    'ind': [1,1,1,1,2,2,2,3,3,3],
    'num': [3,6,8,10,2,5,8,3,4,12]
    }
df = pd.DataFrame(data).assign(numResult=None)
df

Даёт такую картинку:
-	ind	num	numResult
0	1	3	None
1	1	6	None
2	1	8	None
3	1	10	None
4	2	2	None
5	2	5	None
6	2	8	None
7	3	3	None
8	3	4	None
9	3	12	None


Перебором строк я получаю нужный результат:
beforeItem = None
result = []
for index, item in df.iterrows():
  if beforeItem is None:
    item.numResult = item.num
  elif item.ind != beforeItem.ind:
    item.numResult = item.num
  else:
    item.numResult = item.num - beforeItem.num

  result.append(item)
  beforeItem = item


df2 = pd.DataFrame(result)
df2

-	ind	num	numResult
0	1	3	3
1	1	6	3
2	1	8	2
3	1	10	2
4	2	2	2
5	2	5	3
6	2	8	3
7	3	3	3
8	3	4	1
9	3	12	8


А как эту функцию векторизировать через метод np.vectorize например, потому что через iterrows и перебор работает медленно при больших данных... Или может есть ещё какой метод?

Для удобства код выложил сюда: https://colab.research.google.com/drive/1pnIgoLA7j...
  • Вопрос задан
  • 166 просмотров
Решения вопроса 2
LazyTalent
@LazyTalent
Data Engineer, Freelancer
>>> import pandas as pd
>>> data = {'ind': [1,1,1,1,2,2,2,3,3,3], 'num': [3,6,8,10,2,5,8,3,4,12]}
>>> df = pd.DataFrame(data)
>>> df['numResult'] = (df['num'] - df['num'].shift(1)).where(df['ind']==df['ind'].shift(1), other=df['num'])
Ответ написан
Recosh
@Recosh Автор вопроса
Программист студент
А тем временем вопрос решил сам таким кодом:
def computeNumResult(ind, num, prevInd, prevNum):
  if not prevInd or ind != prevInd:
    result = num
  else:
    result = num - prevNum
  return result

dfShiftPeriods1 = df.shift(periods=1)
df.numResult = np.vectorize(computeNumResult)(df.ind, df.num, dfShiftPeriods1.ind, dfShiftPeriods1.num)
df

Правда пока в уме не укладывается, как оно работает XD
UPD: Уложилось)
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы