Столбец с корректировкой даты (Заполните пробелы в дате и обновите до определенной даты) - PullRequest
1 голос
/ 08 октября 2019

У меня следующая ситуация:

Фрейм данных, который показывает каждое движение инвентаря (покупка / продажа) каждого товара и магазина.

        date     sku     store  Units   balance
0 2019-10-01  103993.0    001    0.0     10.0
1 2019-10-02  103993.0    001    1.0      9.0
2 2019-10-04  103993.0    001    1.0      8.0
3 2019-10-05  103993.0    001    0.0      8.0
4 2019-10-01  103994.0    002    0.0     12.0
5 2019-10-02  103994.0    002    1.0     11.0
6 2019-10-04  103994.0    002    1.0     10.0
7 2019-10-05  103994.0    002    0.0     10.0

Предположим, сегодня 2019-10-08Какой лучший способ обновить эту дату:

  • Заполнение пробелов (например, добавление строки 2019-01-03)
  • Обновление каждые (sku и Store) до сегодняшней даты:
    • Сохранение столбца Store and Balance с последним значением
    • Вставка 0 в столбцы Units (что означает, что в эти дни у меня не было проданных единиц)

Таким образом, выходные данные должны быть такими:

           date     sku     store  Units   balance
    0 2019-10-01  103993.0    001    0.0     10.0
    1 2019-10-02  103993.0    001    1.0      9.0
    2 2019-10-03  103993.0    001    0.0      9.0
    3 2019-10-04  103993.0    001    1.0      8.0
    4 2019-10-05  103993.0    001    0.0      8.0
    5 2019-10-06  103993.0    001    0.0      8.0
    6 2019-10-07  103993.0    001    0.0      8.0
    7 2019-10-08  103993.0    001    0.0      8.0
    8 2019-10-01  103994.0    002    0.0     12.0
    9 2019-10-02  103994.0    002    1.0     11.0
   10 2019-10-03  103994.0    002    0.0     11.0
   11 2019-10-04  103994.0    002    1.0     10.0
   12 2019-10-05  103994.0    002    0.0     10.0
   13 2019-10-06  103994.0    002    0.0     10.0
   14 2019-10-07  103994.0    002    0.0     10.0
   15 2019-10-08  103994.0    002    0.0     10.0

Я нашел только один способ сделать это:

    dfs = []
    for _, d in df.groupby(['sku', 'store']):

        start_date = d.date.iloc[0]
        end_date = pd.Timestamp('2019-10-08')

        d.set_index('date', inplace=True)
        d = d.reindex(pd.date_range(start_date, end_date))
        dfs.append(d)

    df = pd.concat(dfs)
    df[['units']] = df[['units']].fillna(0)
    df.ffill(inplace=True)

Однако этот код не векторизован,Есть ли лучший способ получить тот же результат?

1 Ответ

1 голос
/ 08 октября 2019

IIUC, вы можете сделать:

# min date
min_date = df.date.min()

# create a new index
new_idx = pd.MultiIndex.from_product((df.sku.unique(),
                                      pd.date_range(min_date, '2019-10-08', freq='D')),
                                     names=['sku','date']
                                    )

# reindex
new_df = df.set_index(['sku','date']).reindex(new_idx)

# fillna
new_df.Units = new_df.Units.fillna(0)

# ffill by group and dropna for invalid dates
new_df = new_df.groupby(level=0).ffill().dropna()

Вывод:

                     store  Units  balance
sku      date                             
103993.0 2019-09-30    1.0    0.0     10.0
         2019-10-01    1.0    0.0     10.0
         2019-10-02    1.0    1.0      9.0
         2019-10-03    1.0    0.0      9.0
         2019-10-04    1.0    1.0      8.0
         2019-10-05    1.0    0.0      8.0
         2019-10-06    1.0    0.0      8.0
         2019-10-07    1.0    0.0      8.0
         2019-10-08    1.0    0.0      8.0
103994.0 2019-10-01    2.0    0.0     12.0
         2019-10-02    2.0    1.0     11.0
         2019-10-03    2.0    0.0     11.0
         2019-10-04    2.0    1.0     10.0
         2019-10-05    2.0    0.0     10.0
         2019-10-06    2.0    0.0     10.0
         2019-10-07    2.0    0.0     10.0
         2019-10-08    2.0    0.0     10.0

Примечание: этот подход может быть дорогостоящим, если минимальная дата для разных sku составляеточень разные и далекие от сегодняшнего дня.

...