如何用Pandas高效统计连续True值的日期区间及天数?
问题描述
我有如下DataFrame:
date qq q_t l_t 1956-01-01 1 4 True 1956-01-02 2 5 True 1956-01-03 3 1 False 1956-01-04 4 1 False 1956-01-05 5 1 False 1956-01-06 6 10 True 1956-01-07 7 11 True 1956-01-08 8 12 True 1956-01-09 9 5 False 1956-01-10 10 3 False 1956-01-11 11 3 False 1956-01-12 12 3 False 1956-01-13 13 50 True 1956-01-14 14 51 True 1956-01-15 15 52 True 1956-01-16 16 53 True 1956-01-17 17 1 False 1956-01-18 18 23 True 1956-01-19 19 1 False
希望统计l_t列值为True的连续天数,并记录每个连续区间的起始和结束日期,生成如下新DataFrame:
index days start end 1 2 1956-01-01 1956-01-02 2 3 1956-01-06 1956-01-08 3 4 1956-01-13 1956-01-16 4 1 1956-01-18 1956-01-18
我原本打算用np.where结合循环实现,代码大致如下:
_fref = np.where(dfr_['l_t'] == 'True') for i in range(0, len(_fref)-1): i_1 = _fref[i] i_2 = _fref[i+1] deltat = i_2-i_1 if deltat == 1: ...
但这种方法不够优雅,我确信有更优方案。请问是否有更好的方法替代循环策略?
解决方案
可以利用pandas的分组聚合能力,无需循环即可高效实现需求,核心思路是标记连续的True区间,再对每个区间做聚合统计:
完整代码示例
import pandas as pd # 构造原始DataFrame data = { 'date': ['1956-01-01', '1956-01-02', '1956-01-03', '1956-01-04', '1956-01-05', '1956-01-06', '1956-01-07', '1956-01-08', '1956-01-09', '1956-01-10', '1956-01-11', '1956-01-12', '1956-01-13', '1956-01-14', '1956-01-15', '1956-01-16', '1956-01-17', '1956-01-18', '1956-01-19'], 'qq': [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19], 'q_t': [4,5,1,1,1,10,11,12,5,3,3,3,50,51,52,53,1,23,1], 'l_t': [True,True,False,False,False,True,True,True,False,False,False,False,True,True,True,True,False,True,False] } df = pd.DataFrame(data) df['date'] = pd.to_datetime(df['date']) # 确保date列为datetime类型 # 筛选l_t为True的行 true_df = df[df['l_t']] # 生成连续区间的分组标识:日期差不为1天时标记为新组 true_df['group'] = (true_df['date'].diff().dt.days != 1).cumsum() # 分组聚合计算结果 result = true_df.groupby('group').agg( start=('date', 'min'), end=('date', 'max'), days=('date', 'count') ).reset_index(drop=True) # 调整索引从1开始 result.index = result.index + 1 print(result)
运行结果
start end days 1 1956-01-01 1956-01-02 2 2 1956-01-06 1956-01-08 3 3 1956-01-13 1956-01-16 4 4 1956-01-18 1956-01-18 1
关键步骤说明
- 日期类型转换:先将
date列转为datetime类型,才能正确计算日期差值。 - 分组标识生成:
true_df['date'].diff().dt.days != 1会在连续日期中断的位置返回True,通过cumsum()累加这些True值,就能为每个连续区间分配唯一的分组ID。 - 聚合统计:用
groupby对每个分组取最小日期(起始)、最大日期(结束)和行数(天数),一步完成统计。
这种方法完全避免了循环,利用pandas的向量化操作,代码更简洁高效,尤其适合处理大规模数据。
内容的提问来源于stack exchange,提问作者diedro
相关产品推荐
相关产品推荐

