基于连续日期条件筛选DataFrame行并提取个体最低分
问题与解决方案
原始数据
Date Name Score Jan-1-2020 Jake 50 Jan-2-2020 Jake 30 Feb-1-2020 Paul 30 Jan-3-2020 Jake 30 Jan-2-2020 Paul 25
已完成排序操作:
Data = Data.sort_values(["Name","Date"], ascending = [True, True])
排序后的数据:
| Date | Name | Score |
|---|---|---|
| Jan-1-2020 | Jake | 50 |
| Jan-2-2020 | Jake | 30 |
| Jan-3-2020 | Jake | 30 |
| Jan-2-2020 | Paul | 25 |
| Feb-1-2020 | Paul | 30 |
需求
针对每个个体,找出其连续2天及以上得分低于35的时段,并提取该时段中的最低分记录(预期输出取该时段内最低分的最后一条记录)。
预期输出
| Date | Name | Score |
|---|---|---|
| Jan-3-2020 | Jake | 30 |
实现方案
步骤说明
- 日期格式转换:将
Date列转为datetime类型,才能准确判断日期连续性。 - 低分记录标记:新增列标记得分低于35的行。
- 连续时段分组:按姓名分组,结合低分标记和日期差,为连续的低分记录分配同一组ID。
- 筛选有效时段:保留分组内记录数≥2的时段(即连续2天及以上的低分)。
- 提取最低分记录:在每个有效时段中,找到最低分对应的最后一条记录。
代码实现
import pandas as pd # 构造原始数据 df = pd.DataFrame({ 'Date': ['Jan-1-2020', 'Jan-2-2020', 'Feb-1-2020', 'Jan-3-2020', 'Jan-2-2020'], 'Name': ['Jake', 'Jake', 'Paul', 'Jake', 'Paul'], 'Score': [50, 30, 30, 30, 25] }) # 执行排序 df = df.sort_values(["Name", "Date"], ascending=[True, True]) # 转换日期格式 df['Date'] = pd.to_datetime(df['Date']) # 标记得分低于35的记录 df['is_low_score'] = df['Score'] < 35 # 计算日期差,判断是否连续 df['date_diff'] = df.groupby('Name')['Date'].diff().dt.days.fillna(1) # 生成连续低分时段的组ID df['group_id'] = ((df['is_low_score'] != df['is_low_score'].shift()) | (df['date_diff'] != 1)).cumsum() # 筛选出符合条件的连续低分时段 valid_segments = df[df['is_low_score']].groupby(['Name', 'group_id']).filter(lambda x: len(x) >= 2) # 提取每个时段中最低分的最后一条记录 result = valid_segments.groupby(['Name', 'group_id']).apply( lambda x: x[x['Score'] == x['Score'].min()].iloc[-1] ).reset_index(drop=True) # 输出目标列 print(result[['Date', 'Name', 'Score']])
结果解释
- Jake的Jan-2和Jan-3是连续两天得分低于35,该时段最低分为30,取时段内最后一条记录(Jan-3-2020)。
- Paul的两条低分记录日期间隔为29天(Jan-2到Feb-1),不属于连续时段,因此未被纳入结果。
内容的提问来源于stack exchange,提问作者Erica Sam
相关产品推荐
相关产品推荐

