Скользящая сумма панд для умножения значений отдельно - PullRequest
0 голосов
/ 22 октября 2019

У меня есть следующий фрейм данных:

a = pd.DataFrame({'unit': [2, 2, 3, 3, 3, 4, 4, 4, 5], 
                 'date': [1, 2, 1, 2, 3, 1, 2, 3, 1], 
                 'revenue': [1, 1, 3, 5, 7, 6, 6, 2, 9]})

Pandas RollingSum с окном = 2:

a['rolled_sum'] = a.rolling(2, on='date').sum().shift(+1)['revenue']

вычисляет эту сумму строка за строкой:

 adunit   date  revenue  rolled_sum
0   2       1       1       NaN
1   2       2       1       NaN
2   3       1       3       2.0
3   3       2       5       4.0
4   3       3       7       8.0
5   4       1       6       12.0
6   4       2       6       13.0
7   4       3       2       12.0
8   5       1       9       8.0

Я бы хотел, чтобы эта скользящая сумма была рассчитана для каждой единицы отдельно:

 adunit   date  revenue  rolled_sum
0   2       1       1       NaN
1   2       2       1       NaN
2   3       1       3       NaN
3   3       2       5       NaN
4   3       3       7       8.0
5   4       1       6       NaN
6   4       2       6       NaN
7   4       3       2       12.0
8   5       1       9       NaN

Другими словами: скользящая сумма должна быть выполнена для каждой единицы отдельно. В моем исходном наборе данных у меня есть сотни единиц, и я хочу ежедневно выполнять скользящую сумму для каждого из них.

Есть идеи?

Заранее большое спасибо:)

Энди

Ответы [ 2 ]

2 голосов
/ 22 октября 2019

IIUC, вы можете катиться по группам:

a['rolled_sum'] = (a.groupby('unit')
                    .rolling(2, on='date').sum()['revenue']
                    .groupby('unit').shift(1)
                    .to_numpy()
                  )

Выход:

   unit  date  revenue  rolled_sum
0     2     1        1         NaN
1     2     2        1         NaN
2     3     1        3         NaN
3     3     2        5         NaN
4     3     3        7         8.0
5     4     1        6         NaN
6     4     2        6         NaN
7     4     3        2        12.0
8     5     1        9         NaN
0 голосов
/ 22 октября 2019

С вашей сортировкой вы можете замаскировать, где она не должна быть установлена.

m = a.unit.eq(a.unit.shift()) & a.unit.eq(a.unit.shift(-1))
a['rolled_sum'] = (a.rolling(2, on='date').sum().shift(+1)['revenue']
                     .where(m.shift().fillna(False)))

   unit  date  revenue  rolled_sum
0     2     1        1         NaN
1     2     2        1         NaN
2     3     1        3         NaN
3     3     2        5         NaN
4     3     3        7         8.0
5     4     1        6         NaN
6     4     2        6         NaN
7     4     3        2        12.0
8     5     1        9         NaN
...