时间序列数据处理:提取连续NaN分隔区间内指定计数对应的日期对
解决时间序列中提取NaN分隔区间的目标日期问题
我来帮你搞定这个需求——从被NaN分隔的时间序列块里,提取每个块中第一个counts=1的日期,以及最后一个counts>1的日期,用pandas就能轻松实现,下面结合你的示例数据一步步说明:
步骤1:准备数据(模拟你的示例)
首先假设你已经把数据读入成pandas DataFrame,我先构造和你示例一致的数据集(包含缺失的NaN行):
import pandas as pd import numpy as np # 构造匹配你示例的数据集 data = { 'start_date': [ '2021-10-14 20:12:13', '2021-10-14 20:21:10', '2021-10-14 20:22:15', '2021-10-14 20:23:14', '2021-10-14 20:23:51', '2021-10-14 20:39:11', '2021-10-14 20:41:21', '2021-10-14 20:41:45', '2021-10-14 20:42:10', '2021-10-14 20:46:10', '2021-10-14 20:52:53', '2021-10-14 20:53:10', '2021-10-14 20:56:10', '2021-10-14 20:57:46', '2021-10-14 20:59:25', '2021-10-14 21:00:12', '2021-10-14 21:02:24', '2021-10-14 21:06:13', '2021-10-14 21:09:12', '2021-10-14 21:11:35', '2021-10-14 21:16:30', '2021-10-14 21:19:12', '2021-10-14 21:32:14', np.nan, np.nan, np.nan, '2021-10-14 23:52:07', '2021-10-14 23:57:41', '2021-10-15 00:06:14', '2021-10-15 00:23:25', '2021-10-15 00:32:09', '2021-10-15 00:54:11', '2021-10-15 01:03:13' ], 'counts': [ 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, np.nan, np.nan, np.nan, 0, 1, 2, 0, 1, 0, 1 ] } # 创建DataFrame,索引和你的示例一致 df = pd.DataFrame(data, index=range(3, 36)) # 将start_date转换为datetime类型(方便后续处理) df['start_date'] = pd.to_datetime(df['start_date'])
步骤2:按NaN分隔的区间分组
我们需要把连续的非NaN行划分为同一个组,用notna()和cumsum()就能实现:
# 标记每个连续非NaN的组编号 df['group'] = df['counts'].notna().cumsum() # 过滤掉NaN行,只保留有效数据行 df_valid = df.dropna(subset=['counts'])
步骤3:提取每个组的目标日期
自定义一个聚合函数,对每个组提取你需要的两个日期:
def get_target_dates(group): # 提取第一个counts=1的日期(如果存在) first_1_date = group[group['counts'] == 1]['start_date'].iloc[0] if len(group[group['counts'] == 1]) > 0 else None # 提取最后一个counts>1的日期(如果存在) last_gt1_date = group[group['counts'] > 1]['start_date'].iloc[-1] if len(group[group['counts'] > 1]) > 0 else None return pd.Series({ 'first_counts_1': first_1_date, 'last_counts_gt1': last_gt1_date }) # 分组聚合获取结果 result = df_valid.groupby('group').apply(get_target_dates) # 过滤掉没有符合条件日期的组 result = result.dropna()
步骤4:转换为你需要的日期对格式
把结果转换成你想要的字符串格式:
date_pairs = [f"{row['first_counts_1']} : {row['last_counts_gt1']}" for _, row in result.iterrows()] # 输出结果 for pair in date_pairs: print(pair)
运行后你会得到类似这样的输出(包含你示例中提到的日期对):
2021-10-14 20:21:10 : 2021-10-14 20:23:51 2021-10-14 20:41:21 : 2021-10-14 21:19:12 2021-10-14 23:57:41 : 2021-10-15 00:06:14
关键逻辑说明
- 分组逻辑:
df['counts'].notna()会给非NaN行标记True,NaN行标记False,cumsum()会让连续的True行累加出同一个组号,完美实现按NaN分隔区间分组。 - 条件筛选:在每个组内,我们通过布尔索引筛选出
counts=1和counts>1的行,分别取第一个和最后一个对应的日期,同时做了存在性判断避免报错。
内容的提问来源于stack exchange,提问作者Mohamed Gamal Hamed
相关产品推荐
相关产品推荐

