DataFrame按25秒降采样异常:原因排查与修正方案
时间序列降采样:每25秒保留一行的问题与修正
问题背景
需要对包含经纬度和时间的数据集进行降采样,规则为每25秒保留一行(从第一个数据点开始,后续仅保留与上一个保留点时间差≥25秒的记录)。当前使用resample的代码输出不符合预期,输入、当前输出、预期输出示例如下:
输入示例
lon lat time 0 116.317117 40.075417 2007-05-06 04:21:12 1 116.317067 40.075217 2007-05-06 04:21:33 2 116.317233 40.075250 2007-05-06 04:21:53 3 116.317217 40.075417 2007-05-06 04:22:04 4 116.317133 40.075567 2007-05-06 04:22:23 5 116.317167 40.075400 2007-05-06 04:46:48 6 116.317233 40.075183 2007-05-06 04:46:54 7 116.317050 40.074933 2007-05-06 04:47:00 8 116.313567 40.073983 2007-05-06 04:47:36 9 116.311133 40.073167 2007-05-06 04:48:44 10 116.308017 40.072300 2007-05-06 04:49:15 11 116.307467 40.072483 2007-05-06 04:49:22 12 116.306250 40.074017 2007-05-06 04:49:45 13 116.306450 40.074283 2007-05-06 04:49:52
当前输出(不符合预期)
lon lat time 0 116.317117 40.075417 2007-05-06 04:21:12 1 116.317067 40.075217 2007-05-06 04:21:33 2 116.317217 40.075417 2007-05-06 04:22:04 3 116.317133 40.075567 2007-05-06 04:22:23 4 116.317050 40.074933 2007-05-06 04:47:00 5 116.313567 40.073983 2007-05-06 04:47:36 6 116.311133 40.073167 2007-05-06 04:48:44 7 116.307467 40.072483 2007-05-06 04:49:22 8 116.306450 40.074283 2007-05-06 04:49:52 ...
预期输出
lon lat time 0 116.317117 40.075417 2007-05-06 04:21:12 -> Include 1 116.317067 40.075217 2007-05-06 04:21:33 -> Exclude 2 116.317233 40.075250 2007-05-06 04:21:53 -> Include 3 116.317217 40.075417 2007-05-06 04:22:04 -> Exclude 4 116.317133 40.075567 2007-05-06 04:22:23 -> Include 5 116.317167 40.075400 2007-05-06 04:46:48 -> Include 6 116.317233 40.075183 2007-05-06 04:46:54 -> Exclude 7 116.317050 40.074933 2007-05-06 04:47:00 -> Exclude 8 116.313567 40.073983 2007-05-06 04:47:36 -> Include 9 116.311133 40.073167 2007-05-06 04:48:44 -> Exclude 10 116.308017 40.072300 2007-05-06 04:49:15 -> Include ...
原代码问题分析
原代码使用resample('25S').last(),核心问题在于:
- Pandas的
resample是基于固定时间窗口的聚合,窗口边界从整点/整分的00秒、25秒、50秒等位置划分(比如04:21:00-04:21:25、04:21:25-04:21:50),而非从数据的第一个点开始计算25秒间隔。 - 示例中第一个数据点是
04:21:12,落在04:21:00-04:21:25窗口,下一个窗口04:21:25-04:21:50包含04:21:33的点,last()会保留这个点,与预期的“从第一个点后25秒(即04:21:37之后)才保留”不符。
修正方案
方法1:遍历筛选(直观易理解)
通过遍历数据,记录上一个保留点的时间,仅保留与上一个点时间差≥25秒的记录:
import pandas as pd # 读取数据并解析时间列 df = pd.read_csv('20070506033305.csv', parse_dates=['time']) # 确保数据按时间排序(避免乱序导致错误) df = df.sort_values('time').reset_index(drop=True) # 初始化保留列表,默认保留第一个点 keep = [0] last_time = df['time'].iloc[0] # 遍历后续数据点 for idx, row in df.iloc[1:].iterrows(): if (row['time'] - last_time).total_seconds() >= 25: keep.append(idx) last_time = row['time'] # 提取结果 df_resampled = df.loc[keep].reset_index(drop=True)
方法2:矢量化分组(高效,适合大数据集)
计算每个点与第一个点的时间差,按25秒间隔分组,保留每组的第一个点:
import pandas as pd df = pd.read_csv('20070506033305.csv', parse_dates=['time']) df = df.sort_values('time').reset_index(drop=True) # 计算每个点与第一个点的时间差(秒) time_diff = (df['time'] - df['time'].iloc[0]).dt.total_seconds() # 按25秒间隔分组,取每组第一个点 df_resampled = df.groupby(time_diff // 25).first().reset_index(drop=True)
验证结果
两种方法都会得到符合预期的输出:
- 保留
04:21:12(第一个点) - 跳过
04:21:33(与上一个点差21秒<25),保留04:21:53(差41秒≥25) - 跳过
04:22:04(差11秒<25),保留04:22:23(差30秒≥25) - 对于长时间间隔后的
04:46:48,自动保留(与上一个点间隔远超25秒)
内容的提问来源于stack exchange,提问作者Darkmoor
相关产品推荐
相关产品推荐

