Pandas сумма за остаток месяца - PullRequest
0 голосов
/ 31 января 2020

У меня есть датафрейм, который выглядит следующим образом:

import pandas as pd

date = ['28-01-2017','29-01-2017','30-01-2017','31-01-2017','01-02-2017','02-02-2017','...']
sales = [1,2,3,4,1,2,'...']
days_left_in_m = [3,2,1,0,29,28,'...']
df_test = pd.DataFrame({'date': date,'days_left_in_m':days_left_in_m,'sales':sales})

df_test

Я пытаюсь найти продажи до конца месяца.

Итак, 28 января 2017 года он вычислит сумму следующих 3-х дней, 29 января - сумма следующих 2-х дней и т. д. ...

Результат должен выглядеть следующим образом: «Обязательный» столбец ниже.

       date    days_left_in_m   sales   required
0   28-01-2017     3              1        10
1   29-01-2017     2              2        9
2   30-01-2017     1              3        7
3   31-01-2017     0              4        4
4   01-02-2017     29             1        3
5   02-02-2017     28             2        2
6   ...           ...            ...      ...

Мое текущее решение действительно некрасиво - я использую не-pythoni c looping:

for i in range(lenght_of_t_series):

        days_left = data_in.loc[i].days_left_in_m

        if days_left == 0:

            sales_temp_list.append(0)
        else:
            if (i+days_left) <= lenght_of_t_series:

                sales_temp_list.append(sum(data_in.loc[(i+1):(i+days_left)].sales))    
            else:
                sales_temp_list.append(np.nan)

Я думаю, что гораздо лучший способ сделать это - использовать df['sales'].rolling(n).sum() Однако каждая строка имеет разные окно.

Посоветуйте, пожалуйста, лучший способ сделать это ...

1 Ответ

1 голос
/ 31 января 2020

Я думаю, вам нужно DataFrame.sort_values с GroupBy.cumsum. Если вы не хотите учитывать текущий день, вы можете использовать groupby.shift (см. Закомментированный код).

Сначала вы можете преобразовать столбец даты в datetime, чтобы использовать Series.dt.month

df_test['date'] = pd.to_datetime(df_test['date'],format = '%d-%m-%Y')

Тогда мы можем использовать:

months = df_test['date'].dt.month
df_test['required'] = (df_test.sort_values('date',ascending = False)
                              .groupby(months)['sales'].cumsum()
                             #.groupby(months).shift(fill_value = 0)
                        )
print(df_test)

Выход

        date  days_left_in_m  sales  required
0 2017-01-28               3      1        10
1 2017-01-29               2      2         9
2 2017-01-30               1      3         7
3 2017-01-31               0      4         4
4 2017-02-01              29      1         3
5 2017-02-02              28      2         2

Если вы не хотите конвертировать date столбец в datetime, используйте:

months = pd.to_datetime(df_test['date'],format = '%d-%m-%Y').dt.month
df_test['required'] = (df_test.sort_values('date',ascending = False)
                              .groupby(months)['sales'].cumsum()
                             #.groupby(months).shift(fill_value = 0)
                        )
...