如何更简洁稳健地合并列名含部分匹配后缀的DataFrame?
问题
需要合并两个Pandas DataFrame:tcia和clin。clin的列名末尾带有第三个短横线后的子串(例如TCGA-2K-A9WE-01,对应tcia中的TCGA-2K-A9WE),要求忽略该子串完成合并,最终保留tcia的列名格式。现有代码可实现需求,但希望获得更简洁稳健的实现方式。
现有代码:
clin_df = clin.copy() clin_df.columns = clin_df.columns.str.rsplit('-', n=1).str.get(0) df = pd.concat([clin_df, tcia], axis=0) df.columns = clin.columns
输入数据
clin的结构
pd.DataFrame({'TCGA-2K-A9WE-01': {'admin.batch_number': '398.45.0', 'age': '53', 'days_to_initial_pathologic_diagnosis': '0', 'days_to_last_follow_up': '207.0', 'ethnicity': 'not hispanic or latino'}, 'TCGA-2Z-A9J1-01': {'admin.batch_number': '398.45.0', 'age': '71', 'days_to_initial_pathologic_diagnosis': '0', 'days_to_last_follow_up': '2298.0', 'ethnicity': 'not hispanic or latino'}, 'TCGA-2Z-A9J3-01': {'admin.batch_number': '398.45.0', 'age': '67', 'days_to_initial_pathologic_diagnosis': '0', 'days_to_last_follow_up': nan, 'ethnicity': 'not hispanic or latino'}, 'TCGA-2Z-A9J6-01': {'admin.batch_number': '398.45.0', 'age': '60', 'days_to_initial_pathologic_diagnosis': '0', 'days_to_last_follow_up': '1731.0', 'ethnicity': 'not hispanic or latino'}, 'TCGA-2Z-A9J7-01': {'admin.batch_number': '398.45.0', 'age': '63', 'days_to_initial_pathologic_diagnosis': '0', 'days_to_last_follow_up': nan, 'ethnicity': 'not hispanic or latino'}})
tcia的结构
pd.DataFrame({'TCGA-2K-A9WE': {'ips_ctla4_neg_pd1_neg': 8.0, 'ips_ctla4_neg_pd1_pos': 7.0, 'ips_ctla4_pos_pd1_neg': 7.0, 'ips_ctla4_pos_pd1_pos': 6.0, 'patient_uuid': '73292c19-d6a8-4bc4-97bc-ccce54f264f8'}, 'TCGA-2Z-A9J1': {'ips_ctla4_neg_pd1_neg': 9.0, 'ips_ctla4_neg_pd1_pos': 8.0, 'ips_ctla4_pos_pd1_neg': 9.0, 'ips_ctla4_pos_pd1_pos': 7.0, 'patient_uuid': '851a1157-e460-4794-8534-2eb6f0ae7468'}, 'TCGA-2Z-A9J3': {'ips_ctla4_neg_pd1_neg': 9.0, 'ips_ctla4_neg_pd1_pos': 7.0, 'ips_ctla4_pos_pd1_neg': 8.0, 'ips_ctla4_pos_pd1_pos': 6.0, 'patient_uuid': '5195c9ac-b649-49f8-8750-f9a4787e8e52'}, 'TCGA-2Z-A9J6': {'ips_ctla4_neg_pd1_neg': 9.0, 'ips_ctla4_neg_pd1_pos': 7.0, 'ips_ctla4_pos_pd1_neg': 8.0, 'ips_ctla4_pos_pd1_pos': 7.0, 'patient_uuid': '4a540448-f106-4b0e-9038-9f7ccefc785b'}, 'TCGA-2Z-A9J7': {'ips_ctla4_neg_pd1_neg': 7.0, 'ips_ctla4_neg_pd1_pos': 5.0, 'ips_ctla4_pos_pd1_neg': 6.0, 'ips_ctla4_pos_pd1_pos': 5.0, 'patient_uuid': 'd66c9261-6c0c-44b0-92fa-a43757f34cb2'}})
期望输出
pd.DataFrame({'TCGA-2K-A9WE': {'admin.batch_number': '398.45.0', 'age': '53', 'days_to_initial_pathologic_diagnosis': '0', 'days_to_last_follow_up': '207.0', 'ethnicity': 'not hispanic or latino', 'ips_ctla4_neg_pd1_neg': 8.0, 'ips_ctla4_neg_pd1_pos': 7.0, 'ips_ctla4_pos_pd1_neg': 7.0, 'ips_ctla4_pos_pd1_pos': 6.0, 'patient_uuid': '73292c19-d6a8-4bc4-97bc-ccce54f264f8'}, 'TCGA-2Z-A9J1': {'admin.batch_number': '398.45.0', 'age': '71', 'days_to_initial_pathologic_diagnosis': '0', 'days_to_last_follow_up': '2298.0', 'ethnicity': 'not hispanic or latino', 'ips_ctla4_neg_pd1_neg': 9.0, 'ips_ctla4_neg_pd1_pos': 8.0, 'ips_ctla4_pos_pd1_neg': 9.0, 'ips_ctla4_pos_pd1_pos': 7.0, 'patient_uuid': '851a1157-e460-4794-8534-2eb6f0ae7468'}, 'TCGA-2Z-A9J3': {'admin.batch_number': '398.45.0', 'age': '67', 'days_to_initial_pathologic_diagnosis': '0', 'days_to_last_follow_up': nan, 'ethnicity': 'not hispanic or latino', 'ips_ctla4_neg_pd1_neg': 9.0, 'ips_ctla4_neg_pd1_pos': 7.0, 'ips_ctla4_pos_pd1_neg': 8.0, 'ips_ctla4_pos_pd1_pos': 6.0, 'patient_uuid': '5195c9ac-b649-49f8-8750-f9a4787e8e52'}, 'TCGA-2Z-A9J6': {'admin.batch_number': '398.45.0', 'age': '60', 'days_to_initial_pathologic_diagnosis': '0', 'days_to_last_follow_up': '1731.0', 'ethnicity': 'not hispanic or latino', 'ips_ctla4_neg_pd1_neg': 9.0, 'ips_ctla4_neg_pd1_pos': 7.0, 'ips_ctla4_pos_pd1_neg': 8.0, 'ips_ctla4_pos_pd1_pos': 7.0, 'patient_uuid': '4a540448-f106-4b0e-9038-9f7ccefc785b'}, 'TCGA-2Z-A9J7': {'admin.batch_number': '398.45.0', 'age': '63', 'days_to_initial_pathologic_diagnosis': '0', 'days_to_last_follow_up': nan, 'ethnicity': 'not hispanic or latino', 'ips_ctla4_neg_pd1_neg': 7.0, 'ips_ctla4_neg_pd1_pos': 5.0, 'ips_ctla4_pos_pd1_neg': 6.0, 'ips_ctla4_pos_pd1_pos': 5.0, 'patient_uuid': 'd66c9261-6c0c-44b0-92fa-a43757f34cb2'}})
更简洁稳健的实现方案
直接通过重命名clin的列并与tcia横向合并的方式实现,逻辑更清晰,避免冗余操作:
# 重命名clin的列,去掉最后一段后缀 clin_renamed = clin.rename(columns=lambda col: col.rsplit('-', n=1)[0]) # 转置后按索引合并,再转回原结构 merged_df = clin_renamed.T.join(tcia.T).T
也可以用链式调用简化代码:
merged_df = clin.rename(columns=lambda col: col.rsplit('-', n=1)[0]).T.join(tcia.T).T
优化说明
- 逻辑更直观:原代码用行拼接后强行修改列名,绕了弯路;直接通过
join按处理后的列名对齐合并,符合数据合并的常规逻辑。 - 减少冗余操作:省略了不必要的
copy()(rename默认返回新对象),也避免了行拼接后可能出现的索引混乱问题。 - 稳健性提升:使用
lambda函数重命名列,比直接修改columns属性更灵活,能兼容列名格式不一致的边界情况。
内容的提问来源于stack exchange,提问作者Anon
相关产品推荐
相关产品推荐

