使用Pandas concat合并重采样DataFrame时得到空数据帧的问题咨询
我写了下面的代码,意图将多组数据重采样至统一时间栅格(比如1秒)后合并为单个DataFrame:
raster = "1s" # 将数据重采样到共享时间栅格(如1秒)并合并为单个DataFrame dfs_resampled = [df.resample(raster).ffill() for df in dfs] print("dfs_resampled",dfs_resampled) # 将重采样后的DataFrame合并为单个DataFrame df_custom = pd.concat(dfs_resampled, axis=1, join="inner") print("df_custom",df_custom)
执行后,重采样后的DataFrames输出如下:
dfs_resampled [ CAN1_VD_S00_TotalVehicleDistance CAN1_VD_S00_TripDistance t 2020-01-13 14:01:27 NaN NaN 2020-01-13 14:01:28 464632.5 464632.5 2020-01-13 14:01:29 464632.5 464632.5 ... 2020-01-13 14:04:43 464632.5 464632.5 [197 rows x 2 columns], CAN1_EEC7_S01_EngnCrnksBrthrOlSprtrSpd ... CAN1_EEC7_S01_EngnIntkMnfldCmmnddPrssr t ... 2020-01-13 14:01:28 NaN ... NaN 2020-01-13 14:01:29 6333.0 ... 82.625 ... 2020-01-13 14:04:43 6250.0 ... 107.000 [196 rows x 4 columns]] df_custom Empty DataFrame Columns: [CAN1_VD_S00_TotalVehicleDistance, CAN1_VD_S00_TripDistance, CAN1_EEC7_S01_EngnCrnksBrthrOlSprtrSpd, CAN1_EEC7_S01_EngnExhstGsRrltn1Vlv2Pstn, CAN1_EEC7_S01_EngnExhstGsRrltn1VlvPstn, CAN1_EEC7_S01_EngnIntkMnfldCmmnddPrssr] Index: []
我预期得到两个重采样DataFrame的内连接结果,但实际得到了空DataFrame,就像两者没有匹配的时间戳一样。我检查过时间戳,觉得应该是对齐的,怀疑是不是用错了pd.concat函数?
注:当我把raster改成"5s"时,能得到预期的合并结果,具体如下:
dfs_resampled [ CAN1_VD_S00_TotalVehicleDistance CAN1_VD_S00_TripDistance t 2020-01-13 14:01:25 NaN NaN 2020-01-13 14:01:30 464632.5 464632.5 ... 2020-01-13 14:04:40 464632.5 464632.5, CAN1_EEC7_S01_EngnCrnksBrthrOlSprtrSpd ... CAN1_EEC7_S01_EngnIntkMnfldCmmnddPrssr t ... 2020-01-13 14:01:25 NaN ... NaN 2020-01-13 14:01:30 6329.0 ... 82.750 ... 2020-01-13 14:04:40 6255.0 ... 106.875 [40 rows x 4 columns]] df_custom CAN1_VD_S00_TotalVehicleDistance ... CAN1_EEC7_S01_EngnIntkMnfldCmmnddPrssr t ... 2020-01-13 14:01:25 NaN ... NaN 2020-01-13 14:01:30 464632.5 ... 82.750 ... 2020-01-13 14:04:40 464632.5 ... 106.875 [40 rows x 6 columns]
问题不在pd.concat的用法,核心是时间戳的精度差异导致匹配失败。
原因分析:
用resample("1s")时,pandas生成的时间索引看似是整秒,但原始数据的时间戳可能带有毫秒/微秒级精度,重采样后两个DataFrame的索引表面一致,实际底层精度不同(比如一个是2020-01-13 14:01:28.000000,另一个是2020-01-13 14:01:28.000001),内连接时没有匹配项,最终得到空DataFrame。
而resample("5s")时,时间栅格粒度更大,pandas会自动把索引对齐到5秒的整倍数,忽略了毫秒级差异,所以能正常匹配。
解决方法:
重采样后强制截断时间精度到秒:
消除索引的精度差异,确保两个DataFrame的索引完全对齐:dfs_resampled = [] for df in dfs: resampled_df = df.resample(raster).ffill() # 将索引截断到秒级 resampled_df.index = resampled_df.index.floor('s') dfs_resampled.append(resampled_df) df_custom = pd.concat(dfs_resampled, axis=1, join="inner")统一重采样区间规则(可选):
指定closed和label参数,确保两个DataFrame的重采样区间划分一致:dfs_resampled = [df.resample(raster, closed='left', label='left').ffill() for df in dfs]用merge显式按索引合并:
替代concat,显式指定按索引匹配,同时处理精度问题:df_custom = dfs_resampled[0] for df in dfs_resampled[1:]: df.index = df.index.floor('s') df_custom = pd.merge(df_custom, df, left_index=True, right_index=True, how='inner')
验证方法:
先确认两个重采样后DataFrame的索引是否真的一致:
# 查看共同索引数量 common_index = dfs_resampled[0].index.intersection(dfs_resampled[1].index) print("共同索引数量:", len(common_index)) # 查看索引的毫秒级精度 print(dfs_resampled[0].index[0].strftime('%Y-%m-%d %H:%M:%S.%f')) print(dfs_resampled[1].index[0].strftime('%Y-%m-%d %H:%M:%S.%f'))
如果输出的毫秒部分不同,就说明是精度问题导致的匹配失败。
内容的提问来源于stack exchange,提问作者mfcss

