如何高效获取Pandas DataFrame指定日期前的最新状态及统计数量
高效获取Pandas每行指定日期前的最新状态
问题背景
给定截止日期2020-05-31,以及如下列名为状态的Pandas DataFrame(值为日期或None):
rejected revocation decision rfe interview premium received rfe_response biometrics withdrawal appeal 196 None None 2020-01-28 None None None 2020-01-16 None None None None 203 None None 2020-06-20 2020-04-01 None None 2020-01-03 2020-08-08 None None None 209 None None 2020-12-03 2020-06-03 None None 2020-01-03 None None None None 213 None None 2020-06-23 None None None 2020-01-27 None 2020-02-19 None None 1449 None None 2020-05-12 None None None 2020-01-06 None None None None 1660 None None 2021-09-23 2021-05-27 None None 2020-01-21 2021-08-17 None None None
需求为:
- 获取每行中在截止日期及之前的最新状态(形式一:索引对应状态)
- 统计各状态的出现数量(形式二:包含所有状态,数量为0的需显示)
当前逐行循环构建字典排序的方法速度极慢,需要更高效的实现方式。
高效实现方案
利用Pandas的矢量化操作替代循环,充分发挥其底层优化优势:
步骤1:数据预处理
import pandas as pd # 定义截止日期 cutoff_date = pd.to_datetime('2020-05-31') # 构建示例DataFrame(已有DataFrame可跳过此步) data = { 'rejected': [None, None, None, None, None, None], 'revocation': [None, None, None, None, None, None], 'decision': ['2020-01-28', '2020-06-20', '2020-12-03', '2020-06-23', '2020-05-12', '2021-09-23'], 'rfe': [None, '2020-04-01', '2020-06-03', None, None, '2021-05-27'], 'interview': [None, None, None, None, None, None], 'premium': [None, None, None, None, None, None], 'received': ['2020-01-16', '2020-01-03', '2020-01-03', '2020-01-27', '2020-01-06', '2020-01-21'], 'rfe_response': [None, '2020-08-08', None, None, None, '2021-08-17'], 'biometrics': [None, None, None, '2020-02-19', None, None], 'withdrawal': [None, None, None, None, None, None], 'appeal': [None, None, None, None, None, None] } df = pd.DataFrame(data, index=[196, 203, 209, 213, 1449, 1660]) # 将所有列转换为datetime类型,None自动转为NaT(缺失时间值) df = df.apply(pd.to_datetime, errors='coerce')
步骤2:筛选截止日期前的有效日期
# 仅保留截止日期及之前的日期,之后的日期设为NaT df_filtered = df.where(df <= cutoff_date)
步骤3:获取每行最新状态
# 按行取最大日期对应的列名,即为该行最新状态 latest_status = df_filtered.idxmax(axis=1)
输出形式一:索引对应最新状态
for idx, status in latest_status.items(): print(f"{idx}: {status}")
输出结果:
196: decision 203: rfe 209: received 213: biometrics 1449: decision 1660: received
输出形式二:状态数量统计
# 统计各状态数量,确保包含原DataFrame的所有列(数量为0的填充为0) status_counts = latest_status.value_counts().reindex(df.columns, fill_value=0) # 按指定格式输出 print("{") for col, count in status_counts.items(): print(f"{col} = {count},") print("}")
输出结果:
{ rejected = 0, revocation = 0, decision = 2, rfe = 1, interview = 0, premium = 0, received = 2, rfe_response = 0, biometrics = 1, withdrawal = 0, appeal = 0, }
注:原需求示例形式二中biometrics标注为0是错误值,实际213行的biometrics日期在截止日期范围内,统计应为1。
方案优势
全程使用Pandas矢量化操作,避免逐行循环,相比原方法速度提升显著,尤其在数据量较大时效果更明显。
内容的提问来源于stack exchange,提问作者Sharhad
相关产品推荐
相关产品推荐

