如何解决在具有相同结尾的组内填充数据框上的日期
这就是我所拥有的:
df = pd.DataFrame({'item': [1,1,2,1],'shop': ['A','A','B','B'],'date': pd.to_datetime(['2018.01.'+ str(x) for x in [2,3,4,5]]),'qty': [5,6,7,8,9,10]})
print(df)
item shop date qty
0 1 A 2018-01-02 5
1 1 A 2018-01-03 6
2 2 A 2018-01-01 7
3 2 A 2018-01-04 8
4 1 B 2018-01-04 9
5 1 B 2018-01-05 10
这就是我想要的:
out = pd.DataFrame({'item': [1,5,10]})
print(out)
item shop date qty
0 1 A 2018-01-02 5
1 1 A 2018-01-03 6
2 1 A 2018-01-04 0
3 1 A 2018-01-05 0
4 2 A 2018-01-01 7
5 2 A 2018-01-02 0
6 2 A 2018-01-03 0
7 2 A 2018-01-04 8
8 2 A 2018-01-05 0
9 1 B 2018-01-04 9
10 1 B 2018-01-05 10
这是我目前取得的成就:
df.set_index('date').groupby(['item','shop']).resample("D")['qty'].sum().reset_index(name='qty')
item shop date qty
0 1 A 2018-01-02 5
1 1 A 2018-01-03 6
2 1 B 2018-01-04 9
3 1 B 2018-01-05 10
4 2 A 2018-01-01 7
5 2 A 2018-01-02 0
6 2 A 2018-01-03 0
7 2 A 2018-01-04 8
我想完成缺失的日期(按天!),以便每个组 [item-shop] 都以相同的日期结束。
想法?
解决方法
这里的关键是在不同的组内创建min
和max
,然后我们创建范围和explode
merge
返回
# find the min date for each shop under each item
s = df.groupby(['item','shop'])[['date']].min()
# find the global max
s['datemax'] = df['date'].max()
# combine two results
s['date'] = [pd.date_range(x,y) for x,y in zip(s['date'],s['datemax'])]
out = s.explode('date').reset_index().merge(df,how='left').fillna(0)
out
item shop date datemax qty
0 1 A 2018-01-02 2018-01-05 5.0
1 1 A 2018-01-03 2018-01-05 6.0
2 1 A 2018-01-04 2018-01-05 0.0
3 1 A 2018-01-05 2018-01-05 0.0
4 1 B 2018-01-04 2018-01-05 9.0
5 1 B 2018-01-05 2018-01-05 10.0
6 2 A 2018-01-01 2018-01-05 7.0
7 2 A 2018-01-02 2018-01-05 0.0
8 2 A 2018-01-03 2018-01-05 0.0
9 2 A 2018-01-04 2018-01-05 8.0
10 2 A 2018-01-05 2018-01-05 0.0
,
我认为这给了你你想要的东西(列的顺序不同)
max_date = df.date.max()
def reindex_to_max_date(df):
return df.set_index('date').reindex(pd.date_range(df.date.min(),max_date,name='date'),fill_value=0)
res = df.groupby(['shop','item']).apply(reindex_to_max_date)
res = res.qty.reset_index()
我按商店、商品分组以提供与 out
中相同的排序顺序,但这些可以互换。
不确定这是否是最有效的方法,但一个想法是创建一个包含所有日期的数据框,并在商店项目级别进行左连接,如下所示
初始数据
import pandas as pd
df = pd.DataFrame({'item': [1,1,2,1],'shop': ['A','A','B','B'],'date': pd.to_datetime(['2018.01.'+ str(x)
for x in [2,3,4,5]]),'qty': [5,6,7,8,9,10]})
df = df.set_index('date')\
.groupby(['item','shop'])\
.resample("D")['qty']\
.sum()\
.reset_index(name='qty')
包含所有日期的数据框
我们首先得到最大和最小日期
rg = df.agg({"date":{"min","max"}})
然后我们创建一个包含所有可能日期的 df
df_dates = pd.DataFrame(
{"date": pd.date_range(
start=rg["date"]["min"],end=rg["date"]["max"])
})
完成日期
现在对于每个商店商品,我们都会对所有可能的日期进行左连接
def complete_dates(x,df_dates):
item = x["item"].iloc[0]
shop = x["shop"].iloc[0]
x = pd.merge(df_dates,x,on=["date"],how="left")
x["item"] = item
x["shop"] = shop
return x
我们最终将这个函数应用到原来的 df
上。
df.groupby(["item","shop"])\
.apply(lambda x:
complete_dates(x,df_dates)
)\
.reset_index(drop=True)
date item shop qty
0 2018-01-01 1 A NaN
1 2018-01-02 1 A 5.0
2 2018-01-03 1 A 6.0
3 2018-01-04 1 A NaN
4 2018-01-05 1 A NaN
5 2018-01-01 1 B NaN
6 2018-01-02 1 B NaN
7 2018-01-03 1 B NaN
8 2018-01-04 1 B 9.0
9 2018-01-05 1 B 10.0
10 2018-01-01 2 A 7.0
11 2018-01-02 2 A 0.0
12 2018-01-03 2 A 0.0
13 2018-01-04 2 A 8.0
14 2018-01-05 2 A NaN
,
您可以使用 complete 中的 pyjanitor 函数来暴露缺失值;结束日期是 date
的最大值,每组 item
和 shop
的开始日期各不相同。
创建一个将目标列 date
与新日期范围配对的字典:
new_date = {"date" : lambda date: pd.date_range(date.min(),df['date'].max())}
将 new_date
变量传递给 complete :
# pip install https://github.com/pyjanitor-devs/pyjanitor.git
import janitor
import pandas as pd
df.complete([new_date],by = ['item','shop']).fillna(0)
item shop date qty
0 1 A 2018-01-02 5.0
1 1 A 2018-01-03 6.0
2 1 A 2018-01-04 0.0
3 1 A 2018-01-05 0.0
4 1 B 2018-01-04 9.0
5 1 B 2018-01-05 10.0
6 2 A 2018-01-01 7.0
7 2 A 2018-01-02 0.0
8 2 A 2018-01-03 0.0
9 2 A 2018-01-04 8.0
10 2 A 2018-01-05 0.0
complete 只是 Pandas 函数的抽象,可以更轻松地显式暴露 Pandas 数据帧中的缺失值。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。