如何查找Pandas 30分钟频率时间序列最长无NaN连续段的起止索引
解决方案:找到30分钟频率时间序列中最长无NaN连续序列
步骤说明
无需依赖时间维度的±1计数,直接基于值的连续性分组即可,具体步骤如下:
- 将数据转为pandas Series,用时间戳做索引,方便后续分组和索引提取。
- 标记NaN值,通过累加NaN的出现次数生成连续非NaN段的分组标签。
- 按分组标签聚合,计算每个非NaN段的长度、起始和结束索引。
- 筛选出长度最大的分段,提取其起止时间戳。
完整代码
import pandas as pd import numpy as np # 原始数据 values = [5468.0, 5946.0, np.nan, 6019.0, 5797.0, 5879.0, np.nan, 5706.0, 5986.0, 6228.0, 6285.0, np.nan, 5667.0, 5886.0, 6380.0, 5988.0, 6290.0, 5899.0, 6429.0, 6177.0] dates = [pd.Timestamp('2018-10-17 13:30:00'), pd.Timestamp('2018-10-17 14:00:00'), pd.Timestamp('2018-10-17 14:30:00'), pd.Timestamp('2018-10-17 15:00:00'), pd.Timestamp('2018-10-17 15:30:00'), pd.Timestamp('2018-10-17 16:00:00'), pd.Timestamp('2018-10-17 16:30:00'), pd.Timestamp('2018-10-17 17:00:00'), pd.Timestamp('2018-10-17 17:30:00'), pd.Timestamp('2018-10-17 18:00:00'), pd.Timestamp('2018-10-17 18:30:00'), pd.Timestamp('2018-10-17 19:00:00'), pd.Timestamp('2018-10-17 19:30:00'), pd.Timestamp('2018-10-17 20:00:00'), pd.Timestamp('2018-10-17 20:30:00'), pd.Timestamp('2018-10-17 21:00:00'), pd.Timestamp('2018-10-17 21:30:00'), pd.Timestamp('2018-10-17 22:00:00'), pd.Timestamp('2018-10-17 22:30:00'), pd.Timestamp('2018-10-17 23:00:00')] # 创建时间序列 ts = pd.Series(values, index=dates) # 标记NaN值 is_nan = ts.isnull() # 生成连续非NaN段的分组标签:每次遇到NaN,分组号递增 group_labels = is_nan.cumsum() # 聚合每个非NaN分组的长度、起始和结束索引 non_nan_groups = ts[~is_nan].groupby(group_labels[~is_nan]).agg({ 'size': 'count', 'start': lambda x: x.index[0], 'end': lambda x: x.index[-1] }) # 找到最长的非NaN分组 longest_segment = non_nan_groups[non_nan_groups['size'] == non_nan_groups['size'].max()] # 输出结果 print(f"最长无NaN连续序列起始时间: {longest_segment['start'].values[0]}") print(f"最长无NaN连续序列结束时间: {longest_segment['end'].values[0]}") print(f"序列包含 {longest_segment['size'].values[0]} 个30分钟周期")
输出结果
最长无NaN连续序列起始时间: 2018-10-17 19:30:00 最长无NaN连续序列结束时间: 2018-10-17 23:00:00 序列包含 8 个30分钟周期
关键逻辑解释
is_nan.cumsum():将布尔值转为数值累加,每次遇到NaN(True=1)时分组号加1,确保连续的非NaN值属于同一个分组。groupby(group_labels[~is_nan]):仅对非NaN值按分组标签聚合,避免NaN干扰。- 聚合函数直接提取每个分组的首尾索引,无需额外处理时间频率——因为你的时间序列本身是连续的30分钟间隔,只要值连续即可。
内容的提问来源于stack exchange,提问作者till Kadabra
相关产品推荐
相关产品推荐

