python - 扩展 pandas 数据框以包含“缺失”周
问题描述
我有一个包含时间序列数据的 pandas 数据框,因此数据框的索引是 datetime64 类型,每周间隔一次,每个日期发生在每个日历周的星期一。
记录订单时数据框中只有条目,因此如果没有下订单,则数据框中没有相应的记录。我想“填充”这个数据框,以便给定日期范围内的任何周都包含在数据框中,并输入相应的零数量。
我已经设法通过创建一个虚拟数据框来完成这项工作,其中包括我想要的每周条目,数量为零,然后合并这两个数据框并删除虚拟数据框列。这会产生第三个填充数据帧。
我不认为这是解决问题的好方法,并且对于 pandas 来说是新手想知道是否有更具体和/或 Python 的方式来实现这一点,可能无需创建一个虚拟数据框然后合并。
我使用的代码如下获得我当前的解决方案:
# Create the dummy product
# Week hold the week date of the order, want to set this as index later
group_by_product_name = df_all_products.groupby(['Week', 'Product Name'])['Qty'].sum()
first_date = group_by_product_name.head(1) # First date in entire dataset
last_date = group_by_product_name.tail().index[-1] # last date in the data set
bdates = pd.bdate_range(start=first_date, end=last_date, freq='W-MON')
qty = np.zeros(bdates.shape)
dummy_product = {'Week':bdates, 'DummyQty':qty}
df_dummy_product = pd.DataFrame(dummy_product)
df_dummy_product.set_index('Week', inplace=True)
group_by_product_name = df_all_products.groupby('Week')['Qty'].sum()
df_temp = pd.concat([df_dummy_product, group_by_product_name], axis=1, join='outer')
df_temp.fillna(0, inplace=True)
df_temp.drop(columns=['DummyQty'], axis=1, inplace=True)
这种方法的问题是有时(我不知道为什么)索引不正确匹配,我认为某个数据帧上的索引的 dtype 以某种方式丢失了它的类型并转到 object 而不是保持 dtype datetime64。所以我确信有比我目前的解决方案更好的方法来解决这个问题。
编辑
这是一个带有“缺少条目”的示例数据框
df1 = pd.DataFrame({'Week':['2018-05-28', '2018-06-04',
'2018-06-11', '2018-06-25'], 'Qty':[100, 200, 300, 500]})
df1.set_index('Week', inplace=True)
df1.head()
这是一个填充数据框的示例,其中包含日期范围之间的其他缺失日期
df_zero = pd.DataFrame({'Week':['2018-05-21', '2018-05-28', '2018-06-04',
'2018-06-11', '2018-06-18', '2018-06-25', '2018-07-02'], 'Dummy Qty':[0, 0, 0, 0, 0, 0, 0]})
df_zero.set_index('Week', inplace=True)
df_zero.head()
这是连接两个数据帧后的预期结果
df_padded = pd.concat([df_zero, df1], axis=1, join='outer')
df_padded.fillna(0, inplace=True)
df_padded.drop(columns=['Dummy Qty'], inplace=True)
df_padded.head(6)
请注意,缺少的条目会在最终数据帧中必要的其他条目之前和之间添加。
编辑2:
根据此处的要求,这是初始产品数据框的示例:
df_all_products = pd.DataFrame({'Week':['2018-05-21', '2018-05-28', '2018-05-21', '2018-06-11', '2018-06-18',
'2018-06-25', '2018-07-02'],
'Product Name':['A', 'A', 'B', 'A', 'B', 'A', 'A'],
'Qty':[100, 200, 300, 400, 500, 600, 700]})
解决方案
好的,鉴于您的原始数据,您可以通过对任何缺失的周使用pivot
和重新采样来实现预期结果,如下所示:
results = df_all_products.groupby(
['Week','Product Name']
)['Qty'].sum().reset_index().pivot(
index='Week',columns='Product Name', values='Qty'
).resample('W-MON').asfreq().fillna(0)
输出结果:
Product Name A B
Week
2018-05-21 100.0 300.0
2018-05-28 200.0 0.0
2018-06-04 0.0 0.0
2018-06-11 400.0 0.0
2018-06-18 0.0 500.0
2018-06-25 600.0 0.0
2018-07-02 700.0 0.0
因此,如果您想获取df
产品名称 A,您可以执行results['A']
.
推荐阅读
- python - 从列表字典中删除 'nan'
- javascript - 如何使用 Javascript 滚动到下一个 div?
- python - Python/Scrapy:自定义管道无效/使用自定义文件名下载文件
- assembly - 为什么 x86 汇编器允许将负整数放入无符号变量中?
- html - 键值的顺序选择选项
- pdf - Ghostscript 删除修剪和出血框和输出配置文件
- nodes - 更新 cytoscape.js 中的图表:节点位置未更新
- azure - 带有 WHERE 子句的 Azure Log Analytics 查询不会产生任何结果
- wordpress - 如何在 wordpress 的旋转滑块中添加播放/暂停按钮
- terminal - 从特定文件中获取值并在终端中显示交换的值