调整日期列(填写日期间隔并更新到特定日期)

时间:2019-10-08 19:52:34

标签: python pandas datetime dask

我有以下情况:

一个数据框,显示每个产品和商店的每个库存移动(买/卖)。

        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月8日,那么更新此日期的最佳方法是什么:

  • 填补空白(例如添加2019-01-03行)
  • 将每个(sku和商店)更新为今天的日期:
    • 保留最后一个值的存储和余额列
    • 将0插入单位列(这意味着这些天我没有出售单位)

所以输出应该是这样的:

           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 个答案:

答案 0 :(得分:1)

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的最小日期相差甚远并且距离今天很远,则此方法可能会很昂贵。