基于公共时间列合并不同长度的Pandas DataFrames(Python3.8.3/Pandas1.0.5)
从HDF5文件合并多数据集为带公共时间轴的DataFrame
问题背景
需要从H5(h5td)格式的HDF5文件中读取大规模数据集并合并为单个DataFrame:
- 数据集命名规则:每个数据数据集(如
group1/dataset1)对应一个同名加_Time后缀的时间数据集(如group1/dataset1_Time) - 不同组的时间轴可能存在差异(采样频率不同、时间戳不完全重合)
- 合并要求:基于完整的公共时间轴合并所有数据,缺失值用
NaN填充,不能丢失任何原始数据
已尝试的无效方法
以下方法无法满足需求:
df.append():仅在无共享时间戳时有效,存在重叠时间戳时会生成重复行,丢失数据关联pd.merge(how="left"):仅适用于两个数据集时间戳完全一致的场景,无法处理采样频率不同的情况
已尝试代码:
import pandas as pd import h5py with h5py.File(filename,'r') as hfid: timeName = "time" # 修正原代码变量名笔误 data1Name = "data1" df1 = pd.DataFrame(columns=[timeName, data1Name]) df1[timeName] = hfid["group1/dataset1_Time"][:] df1[data1Name] = hfid["group1/dataset1"][:] data3Name = "data3" df2 = pd.DataFrame(columns=[timeName, data3Name]) df2[timeName] = hfid["group2/dataset3_Time"][:] df2[data3Name] = hfid["group2/dataset3"][:] # 方法1:仅适用于无时间重叠场景 # df = df1.append(df2) # 方法2:仅适用于时间戳完全一致场景 # df = pd.merge(df1, df2, on=timeName, how="left")
解决方案:基于索引对齐的合并
利用Pandas的索引对齐特性,先将每个数据集的时间列设为索引,再按列合并,自动填充缺失值。该方法高效且能处理大规模数据。
核心步骤
- 读取每个数据-时间对,创建DataFrame并将
time设为唯一索引 - 使用
pd.concat按列合并所有DataFrame,自动对齐时间索引 - 重置索引将时间变回列,并按时间排序
完整代码示例
import pandas as pd import h5py def load_hdf5_dataset(hfid, data_path): """读取单个数据-时间对,返回以time为索引的DataFrame""" time_path = f"{data_path}_Time" time_data = hfid[time_path][:] data_data = hfid[data_path][:] # 提取数据集名称作为列名(如group1/dataset1 → dataset1) col_name = data_path.split("/")[-1] return pd.DataFrame({col_name: data_data}, index=time_data) filename = "your_file.h5" dfs = [] with h5py.File(filename, 'r') as hfid: # 递归遍历所有组和数据集,过滤掉_Time结尾的时间数据集 def traverse(name, obj): if isinstance(obj, h5py.Dataset) and not name.endswith("_Time"): df = load_hdf5_dataset(hfid, name) dfs.append(df) hfid.visititems(traverse) # 合并所有DataFrame,按时间索引对齐,缺失值填充NaN merged_df = pd.concat(dfs, axis=1) # 重置索引并排序时间轴 merged_df = merged_df.reset_index().rename(columns={"index": "time"}).sort_values(by="time").reset_index(drop=True) print(merged_df)
预期输出
| time | data1 | data3 |
|---|---|---|
| 100.5 | 0 | 1 |
| 100.6 | NaN | 1 |
| 100.7 | 0 | 1 |
| 100.8 | NaN | 1 |
内容的提问来源于stack exchange,提问作者KerbFusion
相关产品推荐
相关产品推荐

