Накопление / совокупная сумма единиц, отправленных за 3 дня с момента первой отправки в Pandas

Это немного сложно объяснить, но я буду стараться изо всех сил, пожалуйста, потерпите меня.

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

ID          Shipping Date Units Expected output
153131151007    20180801    1   1
153131151007    20180828    1   2
153131151007    20180829    1   0
153131151007    20180904    1   1
153131151007    20181226    2   4
153131151007    20181227    1   0
153131151007    20181228    1   0
153131151007    20190110    1   1
153131151007    20190115    2   3
153131151007    20190116    1   0
153131151011*   20180510    1   2
153131151011*   20180511    1   0
153131151011*   20180513    1   2
153131151011*   20180515    1   0
153131151011*   20180813    1   1
153131151011*   20180822    1   2
153131151011*   20180824    1   0
153131151011*   20190103    1   1

Код должен проверять дату, видеть, есть ли какие-либо поставки в следующие 3 дня, если есть доставка, он должен просуммировать ее в своем столбце текущей даты и убедиться, что он не учитывает суммарное количество для расчета следующей даты.

Таким образом, для первой даты отправки идентификатора 20181226 он проверяет 1226,1227,1228, суммирует их и показывает результат в 1226, а в следующих 2 ячейках показывает 0.

Аналогично для 2-го ID 20180510 0510 - это первая дата отгрузки в серии. Он проверяет 0510,0511 и 0512 и суммирует его в 0510, а остальные обнуляет, поэтому 0511 не учитывает 0513 и является частью другой группы отгрузки.

data = pd.DataFrame({'ID':['153131151007','153131151007','153131151007','153131151007','153131151007','153131151007','153131151007','153131151007','153131151007','153131151007','153131151011*','153131151011*','153131151011*','153131151011*','153131151011*','153131151011*','153131151011*','153131151011*'],
'Date':[20180801,20180828,20180829,20180904,20181226,20181227,20181228,20190110,20190115,20190116,20180510,20180511,20180513,20180515,20180813,20180822,20180824,20190103],
'Units':[1,1,1,1,2,1,1,1,2,1,1,1,1,1,1,1,1,1]})

person Neil S    schedule 20.05.2019    source источник
comment
Перед закрывающей скобкой отсутствует фигурная скобка   -  person Nev1111    schedule 20.05.2019
comment
Исправил. :)   -  person Neil S    schedule 20.05.2019


Ответы (1)


Это работает, но результаты в широком формате:

import pandas as pd
import numpy as np
from dateutil.parser import parse
from datetime import timedelta

data = pd.DataFrame({'ID':['153131151007','153131151007','153131151007','153131151007','153131151007','153131151007','153131151007','153131151007','153131151007','153131151007','153131151011*','153131151011*','153131151011*','153131151011*','153131151011*','153131151011*','153131151011*','153131151011*'],
'Date':[20180801,20180828,20180829,20180904,20181226,20181227,20181228,20190110,20190115,20190116,20180510,20180511,20180513,20180515,20180813,20180822,20180824,20190103],
'Units':[1,1,1,1,2,1,1,1,2,1,1,1,1,1,1,1,1,1]})

def keep_first(ser):
    ixs = []
    ts = ser.dropna().index[0]
    while ts <= ser.dropna().index.max():
        if ts in ser.dropna().index:
            ixs.append(ts)
            ts+=timedelta(3)
        else:
            ts+=timedelta(1)
    return np.where(ser.index.isin(ixs), ser, 0)

data['Date'] = data['Date'].map(lambda x: parse(str(x))) # parse dates

units = data.groupby(['ID', 'Date']).sum().unstack(0).resample('D').sum() # create resampled units df

units = units.sort_index(ascending=False).rolling(3, min_periods=1).sum().sort_index() # calculate forward-rolling sum

grouped_ix = data.groupby(['ID', 'Date']).sum().unstack(0).index # get indices for actual data

units.loc[grouped_ix].apply(keep_first) # get sums for actual data indices, keep only first
person seanswe    schedule 21.05.2019
comment
Это частично сработало, и я немного изменил его, чтобы он работал в моем случае. Я не мог понять, что случилось. Я использовал stack().reset_index(), чтобы получить df. У меня было более 2000 идентификаторов, и по какой-то причине он не работал, когда я ввел все данные. Итак, я закончил настройку данных в цикле для каждого идентификатора и слил их в конце. Я получил результат, который искал. Спасибо :) - person Neil S; 29.05.2019