基于PRODUCT_CODE合并Pandas DataFrame行的实现问题
Pandas合并DataFrame:按PRODUCT_CODE合并行且不丢失数据
我正在尝试用Pandas合并两个DataFrame,要求当PRODUCT_CODE列值相同时,合并对应行且不丢失任何数据列的值。以下是我的期望输出、已尝试代码及当前不符合预期的输出,寻求正确实现方法:
期望输出
| PRODUCT_CODE | SERIAL_CODE | BATCH_ID | TL_CODE | TL_EXPIRY | PCE_STATUS | PCE_SN_STATUS | PCE_EXPIRY |
|---|---|---|---|---|---|---|---|
| PC001 | SC001 | B001 | T001 | 2023-10-01 | NaN | NaN | NaN |
| PC002 | SC002 | B002 | T002 | 2023-10-02 | NaN | NaN | NaN |
| PC004 | SC004 | B004 | T003 | 2023-10-03 | Active | Valid | NaN |
| PC005 | SC005 | B005 | NaN | NaN | Inactive | Invalid | 2024-10-02 |
| PC006 | SC006 | B006 | NaN | NaN | Active | Valid | 2024-10-03 |
已尝试的代码
创建示例DataFrame
import pandas as pd desired_order = ['PRODUCT_CODE', 'SERIAL_CODE', 'BATCH_ID', 'TL_CODE', 'TL_EXPIRY', 'PCE_STATUS', 'PCE_SN_STATUS', 'PCE_EXPIRY'] df1 = pd.DataFrame({'PRODUCT_CODE': ['PC001', 'PC002', 'PC004'], 'SERIAL_CODE': ['SC001', 'SC002', ''], 'BATCH_ID': ['B001', 'B002', ''], 'TL_CODE': ['T001', 'T002', 'T003'], 'TL_EXPIRY': ['2023-10-01', '2023-10-02', '2023-10-03']}) df2 = pd.DataFrame({'PRODUCT_CODE': ['PC004', 'PC005', 'PC006'], 'SERIAL_CODE': ['SC004', 'SC005', 'SC006'], 'BATCH_ID': ['B004', 'B005', 'B006'], 'PCE_STATUS': ['Active', 'Inactive', 'Active'], 'PCE_SN_STATUS': ['Valid', 'Invalid', 'Valid'], 'PCE_EXPIRY': ['2024-10-01', '2024-10-02', '2024-10-03']})
尝试的合并函数
def combine_and_rearrange_dataframes(df1, df2, desired_order): # 拼接DataFrames combined_df = pd.concat([df1, df2], ignore_index=True) # 提取唯一列 unique_columns = combined_df.columns.union(df1.columns) # 按期望顺序排列列 final_df = combined_df[desired_order] # 根据PRODUCT_CODE更新行 matching_product_codes = final_df['PRODUCT_CODE'].unique() for product_code in matching_product_codes: df_subset = final_df[final_df['PRODUCT_CODE'] == product_code] df_subset_updated = df1[df1['PRODUCT_CODE'] == product_code] final_df.update(df_subset_updated) return final_df result = combine_and_rearrange_dataframes(df1, df2, desired_order) print(result)
当前不符合预期的输出
| PRODUCT_CODE | SERIAL_CODE | BATCH_ID | TL_CODE | TL_EXPIRY | PCE_STATUS | PCE_SN_STATUS | PCE_EXPIRY |
|---|---|---|---|---|---|---|---|
| PC001 | SC001 | B001 | T001 | 2023-10-01 | NaN | NaN | NaN |
| PC002 | SC002 | B002 | T002 | 2023-10-02 | NaN | NaN | NaN |
| PC004 | T003 | 2023-10-03 | NaN | NaN | NaN | ||
| PC004 | SC004 | B004 | NaN | NaN | Active | Valid | |
| PC005 | SC005 | B005 | NaN | NaN | Inactive | Invalid | 2024-10-02 |
| PC006 | SC006 | B006 | NaN | NaN | Active | Valid | 2024-10-03 |
正确实现方法
之前的concat会生成重复行,update操作还错误覆盖了df2的有效数据。正确做法是使用外连接合并,配合空值处理实现行合并:
完整代码
import pandas as pd desired_order = ['PRODUCT_CODE', 'SERIAL_CODE', 'BATCH_ID', 'TL_CODE', 'TL_EXPIRY', 'PCE_STATUS', 'PCE_SN_STATUS', 'PCE_EXPIRY'] df1 = pd.DataFrame({'PRODUCT_CODE': ['PC001', 'PC002', 'PC004'], 'SERIAL_CODE': ['SC001', 'SC002', ''], 'BATCH_ID': ['B001', 'B002', ''], 'TL_CODE': ['T001', 'T002', 'T003'], 'TL_EXPIRY': ['2023-10-01', '2023-10-02', '2023-10-03']}) df2 = pd.DataFrame({'PRODUCT_CODE': ['PC004', 'PC005', 'PC006'], 'SERIAL_CODE': ['SC004', 'SC005', 'SC006'], 'BATCH_ID': ['B004', 'B005', 'B006'], 'PCE_STATUS': ['Active', 'Inactive', 'Active'], 'PCE_SN_STATUS': ['Valid', 'Invalid', 'Valid'], 'PCE_EXPIRY': ['2024-10-01', '2024-10-02', '2024-10-03']}) def combine_and_rearrange_dataframes(df1, df2, desired_order): # 将df1中的空字符串替换为NaN,方便后续合并时优先取非空值 df1_clean = df1.replace('', pd.NA) # 按PRODUCT_CODE做外连接,保留所有行 merged_df = pd.merge(df1_clean, df2, on='PRODUCT_CODE', how='outer', suffixes=('_df1', '_df2')) # 合并重复列:优先取df2的值,无值时用df1的值 merged_df['SERIAL_CODE'] = merged_df['SERIAL_CODE_df2'].combine_first(merged_df['SERIAL_CODE_df1']) merged_df['BATCH_ID'] = merged_df['BATCH_ID_df2'].combine_first(merged_df['BATCH_ID_df1']) # 删除带后缀的冗余列 cols_to_drop = [col for col in merged_df.columns if '_df1' in col or '_df2' in col] merged_df = merged_df.drop(cols_to_drop, axis=1) # 按期望顺序排列列 final_df = merged_df[desired_order] return final_df # 执行并输出结果 result = combine_and_rearrange_dataframes(df1, df2, desired_order) print(result)
关键步骤说明
- 清理空字符串:把df1中的空字符串替换为
pd.NA,确保合并时能正确识别缺失值,优先使用df2的有效值。 - 外连接合并:
pd.merge(how='outer')保留两个DataFrame中所有PRODUCT_CODE的行,不会丢失任何数据。 - 合并重复列:通过
combine_first方法,对重复列优先取df2的值,实现同PRODUCT_CODE行的字段合并。 - 列重排:最后按指定顺序整理结果列。
内容的提问来源于stack exchange,提问作者ma_yank
相关产品推荐
相关产品推荐

