我有一张表格,其中包含 2015 年至 2017 年期间数千种产品的每月销售额和预测。 我的数据给出了每个站点、类型、产品和日期(仅几个月)的需求和预测
问题是,如果一个月内没有销售且没有预测,我看不到具体的行。在下面的示例中,您会看到缺少“2015-08-31”行。 我希望看到这条线的需求为 0,预测为 0。 (请参阅下面的 df_expected 示例)。
基本上,对于 2015 年 6 月 30 日到 2017 年 9 月 30 日之间的所有产品/类型/网站组合,我想用 0 填充此表。
正如您在代码中看到的,我没有定义任何索引,但基本上 ["Site","Type","Product","Date"] 可以被视为多索引。
请注意,我有数百万行。
import pandas as pd
data = [("W1","G1",1234,pd.to_datetime("2015-07-31"),8,4),
("W1","G1",1234,pd.to_datetime("2015-09-30"),2,4),
("W1","G1",1234,pd.to_datetime("2015-10-31"),2,4),
("W1","G1",1234,pd.to_datetime("2015-11-30"),4,4),
("W1","G2",2345,pd.to_datetime("2015-07-31"),5,0),
("W1","G2",2345,pd.to_datetime("2015-08-31"),1,3),
("W1","G2",2345,pd.to_datetime("2015-10-31"),1,3),
("W1","G2",2345,pd.to_datetime("2015-11-30"),3,3)]
labels = ["Site","Type","Product","Date","Demand","Forecast"]
df = pd.DataFrame(data,columns=labels)
df
Site Type Product Date Demand Forecast
0 W1 G1 1234 2015-07-31 8 4
1 W1 G1 1234 2015-09-30 2 4
2 W1 G1 1234 2015-10-31 2 4
3 W1 G1 1234 2015-11-30 4 4
4 W1 G2 2345 2015-07-31 5 0
5 W1 G2 2345 2015-08-31 1 3
6 W1 G2 2345 2015-10-31 1 3
7 W1 G2 2345 2015-11-30 3 3
这就是我期待的结果
data_expected = [("W1","G1",1234,pd.to_datetime("2015-07-31"),8,4),
("W1","G1",1234,pd.to_datetime("2015-08-31"),0,0),
("W1","G1",1234,pd.to_datetime("2015-09-30"),2,4),
("W1","G1",1234,pd.to_datetime("2015-10-31"),2,4),
("W1","G1",1234,pd.to_datetime("2015-11-30"),4,4)]
df_expected = pd.DataFrame(data_expected,columns=labels)
df_expected
Site Type Product Date Demand Forecast
0 W1 G1 1234 2015-07-31 8 4
1 W1 G1 1234 2015-08-31 0 0
2 W1 G1 1234 2015-09-30 2 4
3 W1 G1 1234 2015-10-31 2 4
4 W1 G1 1234 2015-11-30 4 4
我最初考虑的是 stack/unstack 来确保我有所有的月份。但这对于具有数百万行的数据框来说并不是最佳选择。
df = (df
.set_index("Date")
.groupby(["Site","Product","Type",pd.TimeGrouper('M')])[["Forecast","Demand"]].sum()
.unstack()
.fillna(0)
.astype(int))
你觉得怎么样?
最佳答案
您可以使用DataFrameGroupBy.resample
与 asfreq
:
df = (df.set_index('Date')
.groupby(["Site","Type","Product"])['Demand','Forecast']
.resample('M')
.asfreq()
.fillna(0)
.astype(int)
.reset_index())
print (df)
Site Type Product Date Demand Forecast
0 W1 G1 1234 2015-07-31 8 4
1 W1 G1 1234 2015-08-31 0 0
2 W1 G1 1234 2015-09-30 2 4
3 W1 G1 1234 2015-10-31 2 4
4 W1 G1 1234 2015-11-30 4 4
编辑:
我尝试使用 unstack
中的 fill_value
参数稍微改进原始解决方案:
(df.set_index("Date")
.groupby(["Site","Product","Type",pd.TimeGrouper('M')])['Demand','Forecast'].sum()
.unstack(fill_value=0)
.stack())
关于python - 填充 pandas 中多索引数据框的所有月份,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46427186/