使用三重索引在数据框中填充日期

时间:2019-01-24 15:20:24

标签: python pandas date multi-index fillna

我知道已经对此提出了一个类似的问题,但是当您只有一个分类变量时,该解决方案才有效。我有两个,MultiIndexes一直很难与我一起工作。问题是,我有以下数据框:

 Date        Product    eCommerce   Sales
12-10-2018      A           1        10
12-12-2018      A           0        7
12-13-2018      A           1        4
12-15-2018      A           1        2
12-15-2018      A           0        2
12-11-2018      B           1        8
12-13-2018      B           1        6

因此,我需要了解每个日期有无电子商务的销售情况,并填写没有出现零销售的日期。我想要的输出将是:

 Date        Product    eCommerce   Sales
12-10-2018      A           1        10
12-11-2018      A           1        0
12-12-2018      A           1        0
12-13-2018      A           1        4
12-14-2018      A           1        0
12-15-2018      A           1        2

12-12-2018      A           0        7
12-13-2018      A           0        0
12-14-2018      A           0        0
12-15-2018      A           0        2

12-11-2018      B           1        8
12-12-2018      B           1        0
12-13-2018      B           1        6

注意:这只是一个DataFrame,我只是添加了空格以区分索引。

因此,在原始DataFrame中,产品A的电子商务销售缺少12-11和12-14,对于产品A的非电子商务销售则缺少12-13和12-14,而对于电子商务则缺少12-12产品B的销售量

问题是,我设法通过一个效率很低的循环来实现自己想要的目标,该循环大约需要25分钟才能运行:

df_full= pd.DataFrame(columns=df.columns)
for sku in df['Product'].unique():

    aux=df.loc[df['Product']==sku]
    dates= pd.DataFrame(pd.date_range(start=aux.Date.min(), end=aux.Date.max(),freq='D'),columns=['Date'])

    df3 = df.loc[df['id_prod']==sku].merge(dates,
                                                   how='outer',left_on='Date',
                                                   right_on='Date').sort_values(by='Date')

    df3.fillna(method='ffill',inplace=True)
    df_full= df_full.append(df3)

我非常有信心我可以向量化的方式进行操作,这应该花费更少的时间(我有290种可能的日期有2300种产品)。你知道我该怎么做到吗?

编辑:添加了加粗的文字,以更好地说明问题

1 个答案:

答案 0 :(得分:1)

使用单个DatetimeIndex,然后使用groupby + resample.asfreq()(对于数字列可以使用总和),因为日期范围取决于组。

import pandas as pd

df['Date'] = pd.to_datetime(df.Date)
df = df.set_index('Date')

df.groupby(['Product', 'eCommerce'], sort=False).Sales.resample('D').sum().reset_index()

如果您想用零填充很多列,那么:

(df.groupby(['Product', 'eCommerce'], sort=False)
    .resample('D').sum()
    .drop(columns=['Product', 'eCommerce'])
    .reset_index())

输出:

   Product  eCommerce       Date  Sales
0        A          1 2018-12-10     10
1        A          1 2018-12-11      0
2        A          1 2018-12-12      0
3        A          1 2018-12-13      4
4        A          1 2018-12-14      0
5        A          1 2018-12-15      2
6        A          0 2018-12-12      7
7        A          0 2018-12-13      0
8        A          0 2018-12-14      0
9        A          0 2018-12-15      2
10       B          1 2018-12-11      8
11       B          1 2018-12-12      0
12       B          1 2018-12-13      6