Скользящая сумма сдвинутой группы, не работающей на кадре данных для первой записи группы - PullRequest
0 голосов
/ 04 июня 2018

У меня проблема при попытке добавить поле к DataFrame, которое суммирует последние три месяца (то есть, не включая этот месяц).

У меня есть DataFrame, который показываетежемесячные платежи, относящиеся к channel_id:

+-------+---------+------------+----------+-------------------------+
| index |  date   | channel_id |   fee    |       NEW COLUMN        |
+-------+---------+------------+----------+-------------------------+
|    10 | 2018-03 |         22 | 24525.88 | (depends on rows above) |
|    11 | 2018-04 |         22 |    10493 | (depends on rows above) |
|    12 | 2018-05 |         22 |    12500 | (depends on rows above) |
|    13 | 2017-10 |         43 |     1000 | 0                       |
|    14 | 2017-11 |         43 |     1000 | 0                       |
|    15 | 2017-12 |         43 |     1000 | 0                       |
|    16 | 2018-01 |         43 |     1000 | 3000                    |
|    17 | 2018-02 |         43 |     1000 | 3000                    |
|    18 | 2018-03 |         43 |     1000 | 3000                    |
|    19 | 2018-04 |         43 |     1000 | 3000                    |
|    20 | 2018-05 |         43 |     1000 | 3000                    |
|    21 | 2017-10 |         58 |     1750 | 0                       |
|    22 | 2017-11 |         58 |     1750 | 0                       |
|    23 | 2017-12 |         58 |   3302.1 | 0                       |
|    .. | ..      |         .. |   ..     | ..                      |
+-------+---------+------------+----------+-------------------------+

Для каждого channel_id я хочу объединить сборы за последние 3 месяца.Первые три месяца для каждого channel_id (например, индексы строк 4,5,6) должны быть равны 0, так как для суммирования нет 3 предыдущих месяцев.

Для этого я использую:

df.groupby(['channel_id']).rolling(3)[fee].sum().shift(1).sort_index(level=1).fillna(0)

Этот в основном работает, но для первого экземпляра некоторых channel_ids он заполняет значение, которое я не могу ни к чему привязать...:

+---------+------------+----------+----------+----------+
|  date   | channel_id |   fee    | NEW_COL  | Correct? |
+---------+------------+----------+----------+----------+
| 2018-03 |         22 | 24525.88 | 52572.85 | YES      |
| 2018-04 |         22 |    10493 | 60211.76 | YES      |
| 2018-05 |         22 |    12500 | 53933.88 | YES      |
| 2017-10 |         43 |     1000 |     2400 | NO!!!    |
| 2017-11 |         43 |     1000 |        0 | YES      |
| 2017-12 |         43 |     1000 |        0 | YES      |
| 2018-01 |         43 |     1000 |     3000 | YES      |
| 2018-02 |         43 |     1000 |     3000 | YES      |
| 2018-03 |         43 |     1000 |     3000 | YES      |
| 2018-04 |         43 |     1000 |     3000 | YES      |
| 2018-05 |         43 |     1000 |     3000 | YES      |
| 2017-10 |         58 |     1750 |        0 | YES      |
| 2017-11 |         58 |     1750 |        0 | YES      |
| 2017-12 |         58 |   3302.1 |        0 | YES      |
+---------+------------+----------+----------+----------+

Я немного разбираюсь в операциях с df, но мое понимание цепочки:

df.groupby(['channel_id']): группирует данные по channel_id

.rolling(3)[fee].sum(): применяет скользящую 3-месячную сумму к groupby dfs

.shift(1): сдвигает значения на 1 (как нам не нужно в текущем месяце)

.sort_index(level=1): Не уверен, что именно это делает в контексте, но это необходимо ...

.fillna(0): Заполнить NaN 0, где 3 предыдущих месяца недоступны.

Я игралвокруг с различными значениями sort_index (и shift), но я не могу понять, как это работает, это неправильное значение.

Ответы [ 2 ]

0 голосов
/ 04 июня 2018

С apply

df.groupby(['channel_id'])['fee'].apply(lambda x :x.rolling(3).sum().shift(1).fillna(0))
Out[319]: 
0        0.0
1        0.0
2        0.0
3        0.0
4        0.0
5        0.0
6     3000.0
7     3000.0
8     3000.0
9     3000.0
10    3000.0
11       0.0
12       0.0
13       0.0
Name: fee, dtype: float64
0 голосов
/ 04 июня 2018

Я думаю, что нужно DataFrameGroupBy.shift:

df['new'] = (df.groupby(['channel_id']).rolling(3)['fee'].sum()
              .groupby(level=0)
              .shift(1)
              .sort_index(level=1)
              .fillna(0)
              .reset_index(level=0, drop=True))
print (df)
          date  channel_id       fee  NEW COLUMN     new
index                                                   
10     2018-03          22  24525.88         NaN     0.0
11     2018-04          22  10493.00         NaN     0.0
12     2018-05          22  12500.00         NaN     0.0
13     2017-10          43   1000.00         0.0     0.0
14     2017-11          43   1000.00         0.0     0.0
15     2017-12          43   1000.00         0.0     0.0
16     2018-01          43   1000.00      3000.0  3000.0
17     2018-02          43   1000.00      3000.0  3000.0
18     2018-03          43   1000.00      3000.0  3000.0
19     2018-04          43   1000.00      3000.0  3000.0
20     2018-05          43   1000.00      3000.0  3000.0
21     2017-10          58   1750.00         0.0     0.0
22     2017-11          58   1750.00         0.0     0.0
23     2017-12          58   3302.10         0.0     0.0

Или, может быть, 4:

df['new'] = (df.groupby(['channel_id']).rolling(4)['fee'].sum()
              .sort_index(level=1)
              .fillna(0)
              .reset_index(level=0, drop=True))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...