Python: накопленная сумма по нескольким идентификаторам с отсутствующей строкой - PullRequest
0 голосов
/ 21 декабря 2018

У меня большой набор данных с 104 уникальными датами и 200k SKU.Для этого объяснения я использую 3 SKU и 4 даты.

Данные выглядят следующим образом:

 Date      SKU        Demand      Supply
 20160501   1            10          10
 20160508   1            35          20
 20160501   2            20          15
 20160508   2            15          20
 20160522   2            5           0
 20160522   3            55          45

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

Мой вывод будет выглядеть следующим образом:

Date       SKU        Demand      Supply    Cum_Demand    Cum_Supply
20160501     1         10         10         10            10
20160508     1         35         20         45            30
20160515     1         0          0          45            30
20160522     1         0          0          45            30
20160501     2         20         15         20            15
20160508     2         15         20         35            35
20160515     2         0          0          35            35
20160522     2         5          0          40            35
20160501     3         0          0          0             0
20160508     3         0          0          0             0
20160515     3         0          0          0             0
20160522     3         55         45         55            45

Код для кадра данных

data = pd.DataFrame({'Date':[20160501,20160508,20160501,20160508,20160522,20160522],
                 'SKU':[1,1,2,2,2,3],
                 'Demand':[10,35,20,15,5,55],
                 'Supply':[10,20,15,20,0,45]}
                ,columns=['Date', 'SKU', 'Demand', 'Supply'])

Ответы [ 2 ]

0 голосов
/ 21 декабря 2018

Начните с преобразования date в datetime формат:

df.Date = pd.to_datetime(df.Date, format='%Y%m%d')

. Вы можете создать еженедельно pd.date_range, используя существующие даты:

ix = pd.date_range(df.Date.min(), df.Date.max() + pd.DateOffset(1), freq="W")

Следующим шагом будет GorupBy SKU, reindex в соответствии с созданным диапазоном дат и выбор метода заполнения в соответствии со столбцом, ffill и bfill длязаполните все NaNs в случае SKU и 0 для Demand и Supply.

df1 = (df.set_index('Date').groupby('SKU').apply(lambda x: x.reindex(ix)[['SKU']])
                          .ffill().bfill().reset_index(0, drop=True))
df2 = (df.set_index('Date').groupby('SKU').apply(lambda x: x.reindex(ix)[['Demand','Supply']])
                          .fillna(0).reset_index(0, drop=True))

Последний шаг - объединить два кадра данных и взять cumsum из Demand и Supply:

df_final = pd.concat([df2,df1],axis=1)

(df_final.assign(**df_final.groupby('SKU')
    .agg({'Demand':'cumsum','Supply':'cumsum'})
    .add_prefix('cum_')))

            SKU   Demand  Supply    cum_Demand  cum_Supply
2016-05-01  1.0    10.0    10.0        10.0        10.0
2016-05-08  1.0    35.0    20.0        45.0        30.0
2016-05-15  1.0     0.0     0.0        45.0        30.0
2016-05-22  1.0     0.0     0.0        45.0        30.0
2016-05-01  2.0    20.0    15.0        20.0        15.0
2016-05-08  2.0    15.0    20.0        35.0        35.0
2016-05-15  2.0     0.0     0.0        35.0        35.0
2016-05-22  2.0     5.0     0.0        40.0        35.0
2016-05-01  3.0     0.0     0.0         0.0         0.0
2016-05-08  3.0     0.0     0.0         0.0         0.0
2016-05-15  3.0     0.0     0.0         0.0         0.0
2016-05-22  3.0    55.0    45.0        55.0        45.0
0 голосов
/ 21 декабря 2018

Нужно сначала reindex, затем groupby + cumsum и можно concatenate назад:

import pandas as pd

idx = pd.MultiIndex.from_product([[20160501,20160508,20160515,20160522], 
                                  data.SKU.unique()], names=['Date', 'SKU'])
#If have all unique dates needed in column then: 
#pd.MultiIndex.from_product([np.unique(data.Date), data.SKU.unique()])

data2 = data.set_index(['Date', 'SKU']).reindex(idx).fillna(0)
data2 = pd.concat([data2, data2.groupby(level=1).cumsum().add_prefix('Cum_')], 1).sort_index(level=1).reset_index()

Вывод data2:

        Date  SKU  Demand  Supply  Cum_Demand  Cum_Supply
0   20160501    1    10.0    10.0        10.0        10.0
1   20160508    1    35.0    20.0        45.0        30.0
2   20160515    1     0.0     0.0        45.0        30.0
3   20160522    1     0.0     0.0        45.0        30.0
4   20160501    2    20.0    15.0        20.0        15.0
5   20160508    2    15.0    20.0        35.0        35.0
6   20160515    2     0.0     0.0        35.0        35.0
7   20160522    2     5.0     0.0        40.0        35.0
8   20160501    3     0.0     0.0         0.0         0.0
9   20160508    3     0.0     0.0         0.0         0.0
10  20160515    3     0.0     0.0         0.0         0.0
11  20160522    3    55.0    45.0        55.0        45.0

Вы будетенужно быть осторожным с вашими датами.В этом случае я явно перечислил порядок, поэтому более ранние даты появились первыми.Если они числа, то вы можете использовать np.unique, который будет сортировать значения, гарантируя, что даты упорядочены.Но это зависит от каждой даты, появляющейся в вашем DataFrame хотя бы один раз.В противном случае вам нужно будет как-то создать свой список заказанных дат.

...