Как выполнить скользящую сумму из другой категории - PullRequest
4 голосов
/ 23 января 2020

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

Ввод:

Date       Category  Value
2012-01-04        A     10
2012-01-06        A     20
2012-02-15        B    -10
2012-04-29        A      5
2012-04-30        A     70
2012-10-15        A     15
2012-10-16        B    -30
2012-11-19        B    -50

Ожидаемый результат: только строки B, но с указанием скользящего итога A с момента предыдущего появления B

Date       Category  Value  Total_A_since_previous_B
2012-02-15        B    -10                        30
2012-10-16        B    -30                        90
2012-11-19        B    -50                         0

Я пробовал несколько вещей без успеха. Можете ли вы помочь мне понять, как это сделать?

Ответы [ 2 ]

2 голосов
/ 23 января 2020

Сначала создайте группы для каждого вхождения B, суммируйте значения и затем назначьте его в качестве нового столбца для отфильтрованного df.

(
    pd.Series(np.where(df.Category.eq('B'), df.index, np.nan)).bfill()
    .pipe(lambda x: df.groupby(x).Value.apply(lambda x: x[:-1].sum()))
    .pipe(lambda x: df[df.Category=='B'].assign(Total_A_since_previous_B=x))
)

    Date        Category    Value   Total_A_since_previous_B
2   2012-02-15  B           -10     30
6   2012-10-16  B           -30     90
7   2012-11-19  B           -50     0
2 голосов
/ 23 января 2020

Использование GroupBy.agg:

blocks = df.Category.shift().eq('B').cumsum()
new_df = (df.groupby(blocks)
            .agg(Date= ('Date','last'),
                 Category = ('Category','last'),
                 Value = ('Value','last'),
                 Total_A_since_previous_B = ('Value','sum')
                )
             .assign(Total_A_since_previous_B = lambda x: x.Total_A_since_previous_B
                                                           .sub(x.Value))
             .reset_index(drop=True))

print(new_df)
         Date Category  Value  Total_A_since_previous_B
0  2012-02-15        B    -10                        30
1  2012-10-16        B    -30                        90
2  2012-11-19        B    -50                         0
...