基于每日时间规则过滤Pandas DataFrame的技术实现
Pandas按日期筛选符合时间条件的记录
数据与需求
现有如下包含date_time列的DataFrame:
import datetime import pandas as pd date_time_df = pd.DataFrame({'date_time':[datetime.datetime(2020, 7, 10, 9, 15, 3), datetime.datetime(2020, 7, 9, 9, 50, 0), datetime.datetime(2020, 7, 9, 10, 50, 3), datetime.datetime(2020, 7, 9, 16, 50, 0), datetime.datetime(2020, 7, 9, 20, 30, 0), datetime.datetime(2020, 7, 8, 9, 50, 0), datetime.datetime(2020, 7, 8, 10, 50, 3), datetime.datetime(2020, 7, 8, 16, 50, 0), datetime.datetime(2020, 7, 8, 20, 30, 0), datetime.datetime(2020, 7, 7, 10, 50, 3), datetime.datetime(2020, 7, 7, 16, 50, 0), datetime.datetime(2020, 7, 6, 16, 50, 0), datetime.datetime(2020, 7, 6, 20, 30, 0), datetime.datetime(2020, 7, 5, 9, 50, 0), datetime.datetime(2020, 7, 5, 20, 30, 0), datetime.datetime(2020, 7, 4, 16, 50, 0), datetime.datetime(2020, 7, 3, 9, 50, 0), datetime.datetime(2020, 7, 3, 10, 50, 3), datetime.datetime(2020, 7, 3, 16, 50, 0), datetime.datetime(2020, 7, 2, 9, 50, 0), datetime.datetime(2020, 7, 2, 17, 0, 0), datetime.datetime(2020, 7, 1, 10, 45, 3), datetime.datetime(2020, 7, 1, 17, 0, 0), datetime.datetime(2020, 7, 1, 20, 30, 0)]})
需要按照以下规则筛选数据:
- 每个日期仅保留一条10点及以后的记录
- 若某日期只有一条记录,仅保留该记录(前提是时间在10点及以后)
- 若某日期没有10点左右的记录,选择10点之后最早的那条记录
已尝试步骤
- 将
date_time_df拆分为date_time、date、time三列 - 分组统计每日的时间段数量:
gr_df = date_time_df.groupby('date')['time'].nunique().reset_index() gr_df.rename(columns={'time':'count_timeslots'}, inplace=True)
- 筛选仅含一个时间段的日期:
dates_with_one_timeslot = list(gr_df[gr_df['count_timeslots']==1].date_time.unique())
- 筛选包含10点左右时间段的日期:
req_timeslots = list(date_time_df[date_time_df['time'].dt.strftime('%H')=='10'].date_time.unique())
目前卡在如何处理无10点左右时间段但有10点后其他时间段的日期,求解决方案。
解决方案
可以通过分组排序+条件筛选的方式一次性处理所有情况,无需拆分多个步骤:
步骤1:预处理数据,添加日期列和时间筛选标记
先提取日期,同时标记哪些记录是10点及以后的:
# 提取日期部分 date_time_df['date'] = date_time_df['date_time'].dt.date # 标记时间是否>=10点 date_time_df['is_after_10'] = date_time_df['date_time'].dt.hour >= 10
步骤2:筛选出所有10点及以后的记录
先过滤掉10点前的无效记录:
filtered_df = date_time_df[date_time_df['is_after_10']].copy()
步骤3:分组排序,按规则选择目标记录
对每个日期的记录,优先选择10点整小时的记录(即小时为10的),如果没有则选择最早的那条:
# 给10点的记录设置更高的优先级(值越小越优先) filtered_df['priority'] = filtered_df['date_time'].dt.hour.apply(lambda x: 0 if x ==10 else 1) # 按日期分组,先按priority升序(优先选10点的),再按date_time升序(选最早的) result_df = filtered_df.groupby('date').apply( lambda x: x.sort_values(['priority', 'date_time']).iloc[0] ).reset_index(drop=True)
步骤4:提取结果列表
result_lst = result_df['date_time'].tolist()
运行后得到的result_lst与预期一致:
[ datetime.datetime(2020, 7, 9, 10, 50, 3), datetime.datetime(2020, 7, 8, 10, 50, 3), datetime.datetime(2020, 7, 7, 10, 50, 3), datetime.datetime(2020, 7, 6, 16, 50, 0), datetime.datetime(2020, 7, 5, 20, 30, 0), datetime.datetime(2020, 7, 4, 16, 50, 0), datetime.datetime(2020, 7, 3, 10, 50, 3), datetime.datetime(2020, 7, 2, 17, 0, 0), datetime.datetime(2020, 7, 1, 10, 45, 3) ]
逻辑说明
- 先过滤掉所有10点前的记录,确保只处理符合时间范围的候选
- 通过
priority字段给10点的记录设置最高优先级,保证优先被选中 - 同一日期内,若没有10点的记录,则按时间升序选择最早的那条,满足需求中的第三点
内容的提问来源于stack exchange,提问作者Cindy
相关产品推荐
相关产品推荐

