我有一个熊猫数据框df
,其中包含ID
和date
列:
start = datetime.datetime.today()
dates = [start, start+relativedelta(days=20), start+relativedelta(days=40),
start, start+relativedelta(days=35), start+relativedelta(days=36),
start, start+relativedelta(days=10), start+relativedelta(days=15)]
df = pd.DataFrame({'ID':[1,1,1,2,2,2,3,3,3], 'date':dates})
ID date
0 1 2018-11-29 15:35:56.876549
1 1 2018-12-19 15:35:56.876549
2 1 2019-01-08 15:35:56.876549
3 2 2018-11-29 15:35:56.876549
4 2 2019-01-03 15:35:56.876549
5 2 2019-01-04 15:35:56.876549
6 3 2018-11-29 15:35:56.876549
7 3 2018-12-09 15:35:56.876549
8 3 2018-12-14 15:35:56.876549
现在,我要过滤df
,以便每个ID仅包括前30天。即日期<=(date.min()+ 30天)
例如,这意味着ID = 1(2019年1月1日)距离第一个日期(2018年11月29日)已超过30天,因此应将其删除。等等。产生的新数据框应为:
ID date
0 1 2018-11-29 15:35:56.876549
1 1 2018-12-19 15:35:56.876549
3 2 2018-11-29 15:35:56.876549
6 3 2018-11-29 15:35:56.876549
7 3 2018-12-09 15:35:56.876549
8 3 2018-12-14 15:35:56.876549
这如何以编程方式完成?
答案 0 :(得分:2)
考虑为开始和结束日期添加帮助列,然后运行布尔索引进行过滤。具体来说,将groupby().tansform
用于内联min
聚合:
df['start_date'] = df.groupby(df['ID'])['date'].transform('min')
df['end_date'] = df['start_date'] + relativedelta(days=30)
# BOOLEAN MASK
sub_df = df[(df['date'] >= df['start_date']) & (df['date'] <= df['end_date'])]
print(sub_df)
# ID date start_date end_date
# 0 1 2018-11-29 15:22:35.301788 2018-11-29 15:22:35.301788 2018-12-29 15:22:35.301788
# 1 1 2018-12-19 15:22:35.301788 2018-11-29 15:22:35.301788 2018-12-29 15:22:35.301788
# 3 2 2018-11-29 15:22:35.301788 2018-11-29 15:22:35.301788 2018-12-29 15:22:35.301788
# 6 3 2018-11-29 15:22:35.301788 2018-11-29 15:22:35.301788 2018-12-29 15:22:35.301788
# 7 3 2018-12-09 15:22:35.301788 2018-11-29 15:22:35.301788 2018-12-29 15:22:35.301788
# 8 3 2018-12-14 15:22:35.301788 2018-11-29 15:22:35.301788 2018-12-29 15:22:35.301788
# WITH BETWEEN()
sub_df = df[df['date'].between(df['start_date'], df['end_date'])]
print(sub_df)
# ID date start_date end_date
# 0 1 2018-11-29 15:22:35.301788 2018-11-29 15:22:35.301788 2018-12-29 15:22:35.301788
# 1 1 2018-12-19 15:22:35.301788 2018-11-29 15:22:35.301788 2018-12-29 15:22:35.301788
# 3 2 2018-11-29 15:22:35.301788 2018-11-29 15:22:35.301788 2018-12-29 15:22:35.301788
# 6 3 2018-11-29 15:22:35.301788 2018-11-29 15:22:35.301788 2018-12-29 15:22:35.301788
# 7 3 2018-12-09 15:22:35.301788 2018-11-29 15:22:35.301788 2018-12-29 15:22:35.301788
# 8 3 2018-12-14 15:22:35.301788 2018-11-29 15:22:35.301788 2018-12-29 15:22:35.301788
# WITH QUERY()
sub_df = df.query('date >= start_date & date <= end_date')
print(sub_df)
# ID date start_date end_date
# 0 1 2018-11-29 15:22:35.301788 2018-11-29 15:22:35.301788 2018-12-29 15:22:35.301788
# 1 1 2018-12-19 15:22:35.301788 2018-11-29 15:22:35.301788 2018-12-29 15:22:35.301788
# 3 2 2018-11-29 15:22:35.301788 2018-11-29 15:22:35.301788 2018-12-29 15:22:35.301788
# 6 3 2018-11-29 15:22:35.301788 2018-11-29 15:22:35.301788 2018-12-29 15:22:35.301788
# 7 3 2018-12-09 15:22:35.301788 2018-11-29 15:22:35.301788 2018-12-29 15:22:35.301788
# 8 3 2018-12-14 15:22:35.301788 2018-11-29 15:22:35.301788 2018-12-29 15:22:35.301788
用于清理助手列:
# DROP HELPER COLUMNS
sub_df = sub_df.drop(columns=['start_date', 'end_date'])
print(sub_df)
# ID date
# 0 1 2018-11-29 15:22:35.301788
# 1 1 2018-12-19 15:22:35.301788
# 3 2 2018-11-29 15:22:35.301788
# 6 3 2018-11-29 15:22:35.301788
# 7 3 2018-12-09 15:22:35.301788
# 8 3 2018-12-14 15:22:35.301788