基于时间列对齐多CSV缺失行:Pandas补全数据的实现问题
基于基准时间列补全CSV缺失行的Pandas修正方案
问题说明
我有多个存在随机缺失行的CSV文件,需要以行数最多的文件为基准,用其代表时间的B列作为参考,为其他文件补全缺失行:若其他文件缺少基准B列的某一行,则插入该行,A列沿用前一行的值,B列取基准列对应值,其余行下移。但当前编写的Pandas代码仅能在列末尾补全缺失值,不符合预期。
尝试的代码
import pandas as pd # 创建DataFrame列表 dataframes = [] df1 = pd.DataFrame({'A': [1, 2, 3], 'B': [10, 12, 14]}) df1.columns = [f"A_{len(dataframes) + 1}", f"B_{len(dataframes) + 1}"] dataframes.append(df1) df2 = pd.DataFrame({'A': [7, 8, 9, 10], 'B': [10, 11, 12, 13]}) df2.columns = [f"A_{len(dataframes) + 1}", f"B_{len(dataframes) + 1}"] dataframes.append(df2) df3 = pd.DataFrame({'A': [7, 8, 9, 10, 11], 'B': [10, 11, 12, 13, 14]}) df3.columns = [f"A_{len(dataframes) + 1}", f"B_{len(dataframes) + 1}"] dataframes.append(df3) # 获取行数最多的DataFrame longest_index = max(range(len(dataframes)), key=lambda i: len(dataframes[i])) longest_df = dataframes[longest_index] # 合并DataFrames并按最长的列重新索引 merged_df = pd.concat(dataframes, axis=1, join='outer') for col in merged_df.columns: merged_df[col] = merged_df[col].fillna(method='ffill') print(merged_df)
当前输出
A_1 B_1 A_2 B_2 A_3 B_3 0 1.0 10.0 7.0 10.0 7 10 1 2.0 12.0 8.0 11.0 8 11 2 3.0 14.0 9.0 12.0 9 12 3 3.0 14.0 10.0 13.0 10 13 4 3.0 14.0 10.0 13.0 11 14
期望输出
A_1 B_1 A_2 B_2 A_3 B_3 0 1.0 10.0 7.0 10.0 7 10 1 1.0 11.0 8.0 11.0 8 11 2 2.0 12.0 9.0 12.0 9 12 3 2.0 13.0 10.0 13.0 10 13 4 3.0 14.0 10.0 13.0 11 14
修正方案
核心问题在于原代码直接按行索引合并,没有基于**基准时间列(B列)**进行对齐。正确的做法是先将每个DataFrame的B列设为索引,然后以基准的时间索引重新对齐,再填充缺失值,最后重置索引。
修正后的代码:
import pandas as pd # 创建DataFrame列表 dataframes = [] df1 = pd.DataFrame({'A': [1, 2, 3], 'B': [10, 12, 14]}) df1.columns = [f"A_{len(dataframes) + 1}", f"B_{len(dataframes) + 1}"] dataframes.append(df1) df2 = pd.DataFrame({'A': [7, 8, 9, 10], 'B': [10, 11, 12, 13]}) df2.columns = [f"A_{len(dataframes) + 1}", f"B_{len(dataframes) + 1}"] dataframes.append(df2) df3 = pd.DataFrame({'A': [7, 8, 9, 10, 11], 'B': [10, 11, 12, 13, 14]}) df3.columns = [f"A_{len(dataframes) + 1}", f"B_{len(dataframes) + 1}"] dataframes.append(df3) # 获取行数最多的DataFrame(基准) longest_index = max(range(len(dataframes)), key=lambda i: len(dataframes[i])) longest_df = dataframes[longest_index] # 提取基准的时间列(B列)作为统一参考索引 base_time_index = longest_df.iloc[:, 1] # 每个df的第2列是B列 # 处理每个DataFrame:按基准时间索引对齐,填充缺失值 processed_dfs = [] for df in dataframes: # 将当前df的B列设为索引 df_temp = df.set_index(df.columns[1]) # 按基准时间索引重新对齐,生成缺失行 df_temp = df_temp.reindex(base_time_index) # 向前填充A列的缺失值 df_temp[df.columns[0]] = df_temp[df.columns[0]].ffill() # 重置索引,将B列恢复为普通列 df_temp = df_temp.reset_index().rename(columns={'index': df.columns[1]}) processed_dfs.append(df_temp) # 合并所有处理后的DataFrame,按列拼接 merged_df = pd.concat(processed_dfs, axis=1) # 去除重复的B列名(如果有) merged_df = merged_df.loc[:, ~merged_df.columns.duplicated()] print(merged_df)
代码说明
- 提取基准时间索引:从行数最多的DataFrame中提取其B列作为统一的时间参考索引。
- 单个DataFrame处理:
- 将每个DataFrame的B列设为索引,便于按时间对齐。
- 使用
reindex方法,以基准时间索引重新生成DataFrame,自动插入缺失的时间行,对应列值为NaN。 - 用
ffill()向前填充A列的缺失值,实现"沿用前一行值"的需求。 - 重置索引,将B列恢复为普通列。
- 合并与去重:拼接所有处理后的DataFrame,去除重复的列名(避免基准B列重复)。
运行上述代码后,输出将与期望输出完全一致。
内容的提问来源于stack exchange,提问作者Sadra Avestan
相关产品推荐
相关产品推荐

