накопительная сумма за период времени

#python #pandas #pandas-groupby

#python #pandas #pandas-groupby

Вопрос:

мой фрейм данных имеет следующую структуру:

  date_today = dt.datetime.now()
 size=20
 df = pd.DataFrame({"usd": pd.Series(np.random.randint(1,100,size))*10,
               "sent": dt.datetime.now(),
               "temp":np.random.randint(0,15, size=size)
              })
df.sent  = df.temp.map(dt.timedelta)
df.temp = np.random.randint(10,25, size=size)
df["reminder"] = df.sent   df.temp.map(dt.timedelta)
df.temp = np.random.randint(1,65, size=size)
df["completed"] = df.reminder   df.temp.map(dt.timedelta)
df.loc[df['temp']%3 == 0, ['reminder']] = [""]
df.loc[df['temp']%2 == 0, ['completed']] = [""]
df=df[["usd", "sent", "reminder", "completed"]]
  

usd — это деньги, которые я запрашиваю (числовые), остальные столбцы — это дата-время (когда я запрашивал, когда я отправил напоминание и когда я получил деньги; последние два обнуляются).
Я также создал следующий список кварталов месяца:

 date_index = []
previous_date=""
for m in range(0,14):
    month = (m%12) 1
    year = m//12
    current_date = dt.date(2019 year, month, 1)
    if previous_date:
        timedelta = current_date-previous_date
        date_index.append(previous_date 1*timedelta/4)
        date_index.append(previous_date 2*timedelta/4)
        date_index.append(previous_date 3*timedelta/4)
    date_index.append(current_date)
    previous_date = current_date
  

Я хотел бы получить фрейм данных со следующей структурой:

 df_result = pd.DataFrame(columns=["date","sent_amount","reminder_amount","completed_amount"])
  

где df_result.столбец date — это последовательность date_index из предыдущего пункта, sent_amount — это сумма столбцов df.amount для записей, где df.отправленные столбцы — < df_result.date, reminder_amount — это сумма столбцов df.amount для записей, где столбцы df.reminder — < df_result.date . Я могу достичь этого с помощью цикла, но мне бы хотелось узнать, как сделать мой код более тонким. Если у вас есть какие-либо предложения по созданию случайного фрейма данных или списка кварталов месяца, они также приветствуются.

Ответ №1:

Вы можете melt преобразовать фрейм данных, cut даты в диапазоны дат из date_index , затем сгруппировать по комбинации переменных (завершено / напоминание / отправлено) дата, sum увеличить usd суммы, затем разложить их обратно по столбцам и cumsum получить совокупные суммы:

 x = df.melt('usd', value_name='date')
x['date'] = pd.cut(x['date'], pd.to_datetime(date_index)).apply(lambda x: x.right)
x['variable']  = '_amount'

df_result = x.dropna().groupby(['variable', 'date'])['usd'].sum().unstack(0, 0).sort_index().cumsum()

print(df_result)
  

Вывод:

 variable    completed_amount  reminder_amount  sent_amount
date                                                      
2019-03-16                 0                0         3180
2019-03-24                 0                0         8840
2019-04-01                 0             1700        10350
2019-04-08                 0             3230        10350
2019-04-16                 0             6200        10350
2019-04-23               320             6860        10350
2019-05-01              1170             6860        10350
2019-05-16              2300             6860        10350
2019-06-01              5130             6860        10350
2019-06-08              5710             6860        10350