如何按日期筛选pandas DataFrame中每日首个up方向记录
问题说明
现有按日期排序的pandas DataFrame,包含date(日期)、direction(方向,值为up或空值NaN)两列,需要实现:每个自然日仅保留第一条direction为up的记录,其余同日期的重复up记录删除,非up的记录全部保留。
实现思路
- 首先修正基础代码的疏漏:原代码中日期转换逻辑没有将结果赋值回
date列,会导致日期类型不生效,需要补全赋值操作。 - 由于DataFrame已经提前按日期升序排序,同日期内的记录顺序和原始顺序一致,因此只需要标记出所有「同日期下、不是第一条的up记录」,将这部分记录删除即可。
- 可以用两种pandas原生方法实现标记:
- 方法1:用
duplicated()方法,针对所有up记录按日期去重,保留每组第一条,其余标记为重复待删除 - 方法2:用
groupby() + cumcount()方法,对同日期的up记录按出现顺序编号,编号大于0的即为待删除记录
- 方法1:用
完整代码
简洁实现(duplicated写法)
import pandas as pd from datetime import datetime tbl = {"date" :["2022-02-27", "2022-02-27", "2022-02-27", "2022-02-28", "2022-02-28","2022-02-28"], "direction" : ["up", "up", "NaN", "NaN", "up", "up"]} df = pd.DataFrame(tbl) df = df.replace('NaN', float('nan')) # 修正原代码日期转换未赋值的问题 df['date'] = pd.to_datetime(df['date'], format='%Y-%m-%d') df.sort_values(by = "date", inplace=True) # 标记当日非第一条的up记录 dup_up_index = df[df['direction'] == 'up'].duplicated(subset=['date'], keep='first') # 删除重复up记录,重置索引 result = df.drop(dup_up_index[dup_up_index].index).reset_index(drop=True)
等价直观写法(groupby cumcount写法)
import pandas as pd from datetime import datetime tbl = {"date" :["2022-02-27", "2022-02-27", "2022-02-27", "2022-02-28", "2022-02-28","2022-02-28"], "direction" : ["up", "up", "NaN", "NaN", "up", "up"]} df = pd.DataFrame(tbl) df = df.replace('NaN', float('nan')) df['date'] = pd.to_datetime(df['date'], format='%Y-%m-%d') df.sort_values(by = "date", inplace=True) # 给同日期的up记录按出现顺序编号 df['up_seq'] = df[df['direction'] == 'up'].groupby('date').cumcount() # 过滤掉序号大于0的up记录,删除辅助列 result = df[~((df['direction'] == 'up') & (df['up_seq'] > 0))].drop(columns='up_seq').reset_index(drop=True)
运行上述任意一段代码,得到的结果都符合需求:
- 2022-02-27的三条记录:保留第一条
up、删除第二条重复up、保留NaN记录 - 2022-02-28的三条记录:保留
NaN、保留第一条up、删除第二条重复up
内容的提问来源于stack exchange,提问作者Pren Ven
相关产品推荐
相关产品推荐

