You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

关键步骤说明

  1. 日期类型转换:先将date列转为datetime类型,才能正确计算日期差值。
  2. 分组标识生成:true_df['date'].diff().dt.days != 1会在连续日期中断的位置返回True,通过cumsum()累加这些True值,就能为每个连续区间分配唯一的分组ID。
  3. 聚合统计:用groupby对每个分组取最小日期(起始)、最大日期(结束)和行数(天数),一步完成统计。

这种方法完全避免了循环,利用pandas的向量化操作,代码更简洁高效,尤其适合处理大规模数据。


内容的提问来源于stack exchange,提问作者diedro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 18:53:10