如何实现两个行长度不同的Pandas DataFrame按索引对齐并排合并,而非上下堆叠
如何实现两个行长度不同的Pandas DataFrame按索引对齐并排合并,而非上下堆叠
嘿,我完全懂你的需求——你想要让两个列数、行数都不一样的DataFrame,按索引位置对齐横向合并,而不是把一个的行直接堆在另一个下面。从你给出的错误输出来看,问题出在筛选出来的filtered_df还保留着原material_df的索引,导致它和block_df的索引不重叠,合并的时候就变成了各自的行分开显示。
核心解决办法
要实现按索引对齐的横向合并,关键是让两个DataFrame的索引都是从0开始的连续整数,这样Pandas会自动按索引位置匹配行,行数少的那个会在缺失的行上自动填充NaN。
具体到你的代码,只需要在筛选出filtered_df之后,重置它的索引就行:
filtered_df = material_df.loc[ (material_df["Material Date"] < cell_a1) & (material_df["Material Date"] >= last_date) ].reset_index(drop=True) # 新增这一行,重置索引为从0开始的连续整数
修正后的完整代码
把上面的修改应用到你的代码里,就能得到你想要的对齐效果了:
import pandas as pd hours_df = pd.read_excel("hours.xlsx").fillna("") hours_columns = hours_df.columns material_df = pd.read_excel("material.xlsx").fillna("") material_df = material_df.rename(columns={'Date': 'Material Date'}) material_columns = material_df.columns temp = [] combined_df = pd.DataFrame() last_date = "1999-01-01" for _, row in hours_df.iterrows(): if row["Date"] != "": block_df = pd.DataFrame(temp, columns=hours_columns) if temp: cell_a1 = block_df.iloc[0,0] # 筛选后重置索引,确保和block_df的索引对齐 filtered_df = material_df.loc[ (material_df["Material Date"] < cell_a1) & (material_df["Material Date"] >= last_date) ].reset_index(drop=True) last_date = cell_a1 # 横向合并两个DataFrame,此时索引对齐,会按行匹配 combined_block = pd.concat([block_df, filtered_df], axis=1) # 把当前合并好的块加到最终结果里 combined_df = pd.concat([combined_df, combined_block], ignore_index=True) temp = [] temp.append(row) # 处理最后剩下的temp数据 if temp: block_df = pd.DataFrame(temp, columns=hours_columns) combined_df = pd.concat([combined_df, block_df], ignore_index=True) print(combined_df)
为什么这样能解决问题?
reset_index(drop=True)会丢弃filtered_df原来的索引(也就是从material_df继承来的非连续索引),生成从0开始的新连续索引,这样它和block_df的索引就完全重叠了。- 当用
pd.concat([df1, df2], axis=1)横向合并时,Pandas会默认按索引对齐行:如果df1有2行,df2有3行,那么前两行会把df1和df2的对应行拼在一起,第三行则会在df1的列位置填充NaN,正好符合你想要的效果。
备注:内容来源于stack exchange,提问作者displayname
相关产品推荐
相关产品推荐

