在具有相同结尾的组内填充数据框上的日期
Fill dates on dataframe within groups with same ending
这是我的:
df = pd.DataFrame({'item': [1,1,2,2,1,1],
'shop': ['A','A','A','A','B','B'],
'date': pd.to_datetime(['2018.01.'+ str(x) for x in [2,3,1,4,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,1,1,1,2,2,2,2,2,1,1],
'shop': ['A','A','A','A','A','A','A','A','A','B','B'],
'date': pd.to_datetime(['2018.01.'+ str(x) for x in [2,3,4,5,1,2,3,4,5,4,5]]),
'qty': [5,6,0,0,7,0,0,8,0,9,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
back
# 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
不确定这是否是最有效的方法,但一个想法是创建一个包含所有日期的数据框并在商店项目级别进行左连接,如下所示
初始数据
import pandas as pd
df = pd.DataFrame({'item': [1,1,2,2,1,1],
'shop': ['A','A','A','A','B','B'],
'date': pd.to_datetime(['2018.01.'+ str(x)
for x in [2,3,1,4,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
我认为这可以满足您的需求(列的顺序不同)
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
中相同的排序顺序,但这些可以互换。
您可以使用 complete function from 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 数据框中的缺失值。
这是我的:
df = pd.DataFrame({'item': [1,1,2,2,1,1],
'shop': ['A','A','A','A','B','B'],
'date': pd.to_datetime(['2018.01.'+ str(x) for x in [2,3,1,4,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,1,1,1,2,2,2,2,2,1,1],
'shop': ['A','A','A','A','A','A','A','A','A','B','B'],
'date': pd.to_datetime(['2018.01.'+ str(x) for x in [2,3,4,5,1,2,3,4,5,4,5]]),
'qty': [5,6,0,0,7,0,0,8,0,9,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
back
# 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
不确定这是否是最有效的方法,但一个想法是创建一个包含所有日期的数据框并在商店项目级别进行左连接,如下所示
初始数据
import pandas as pd
df = pd.DataFrame({'item': [1,1,2,2,1,1],
'shop': ['A','A','A','A','B','B'],
'date': pd.to_datetime(['2018.01.'+ str(x)
for x in [2,3,1,4,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
我认为这可以满足您的需求(列的顺序不同)
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
中相同的排序顺序,但这些可以互换。
您可以使用 complete function from 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 数据框中的缺失值。