
本文介绍如何使用 pandas 的 pd.concat() 配合 reset_index(),将字典中多个 DataFrame 垂直拼接,并自动将字典键注入为结果 DataFrame 的第一列(即索引转列为普通列),避免手动构造或循环。
本文介绍如何使用 pandas 的 `pd.concat()` 配合 `reset_index()`,将字典中多个 dataframe 垂直拼接,并自动将字典键注入为结果 dataframe 的第一列(即索引转列为普通列),避免手动构造或循环。
在实际数据分析中,我们常将多个结构一致的 DataFrame 存储于字典中(如按基因 ID、样本名或实验组别为键)。当需要统一分析时,需将其合并为单个 DataFrame;而字典键本身往往携带关键元信息(如基因符号、样本编号),理应保留在结果中作为标识列。
pd.concat() 支持通过 keys 参数为拼接后的数据添加多级索引,但默认会将键置于行索引顶层(即 MultiIndex),而非普通列。要将其转为第一列,核心技巧是:先用 keys 构建带命名的层级索引,再调用 reset_index() 提取指定层级。
以下为推荐写法(简洁、健壮、符合 pandas 最佳实践):
import pandas as pd
# 示例数据(字典,键为基因ID,值为DataFrame)
test_list = {
'ENSMUSG00000025333.10': pd.DataFrame({
'treatment_code': [0, 1],
'subjectCode': [2, 4],
'fraction_modified_entropy_in_log2': [1.822939, 0.811278],
'log_RPKM': [3.109444, 3.476707]
}, index=[59478, 107087]),
'ENSMUSG00000025903.14': pd.DataFrame({
'treatment_code': [0, 1],
'subjectCode': [1, 3],
'fraction_modified_entropy_in_log2': [1.000000, 3.551271],
'log_RPKM': [3.175110, 3.002025]
}, index=[178498, 107116]),
'ENSMUSG00000063663.11': pd.DataFrame({
'treatment_code': [0, 1],
'subjectCode': [2, 3],
'fraction_modified_entropy_in_log2': [2.755851, 3.088372],
'log_RPKM': [1.070400, 1.191470]
}, index=[59417, 118918])
}
# ✅ 推荐方式:直接传入字典,指定 names 并 reset_index(0)
out = pd.concat(test_list, ignore_index=False, names=['gene_id']).reset_index(0)
print(out.head())输出结果中,gene_id 列位于最左侧,原始索引(如 59478, 107087 等)保留为新 DataFrame 的行索引:
gene_id treatment_code subjectCode fraction_modified_entropy_in_log2 log_RPKM 59478 ENSMUSG00000025333.10 0 2 1.822939 3.109444 107087 ENSMUSG00000025333.10 1 4 0.811278 3.476707 178498 ENSMUSG00000025903.14 0 1 1.000000 3.175110 107116 ENSMUSG00000025903.14 1 3 3.551271 3.002025 59417 ENSMUSG00000063663.11 0 2 2.755851 1.070400
⚠️ 注意事项:
- pd.concat(test_list, ...) 等价于 pd.concat(test_list.values(), keys=test_list.keys(), ...),但更简洁且自动关联键值;
- names=['gene_id'] 为 MultiIndex 的第一级命名,便于后续 reset_index(0) 明确提取;
- reset_index(0) 表示仅重置第 0 级索引(即字典键所在层),保留原始行索引不变;若需重置全部索引,可改用 reset_index(drop=False);
- 若原始 DataFrame 含重复索引,拼接后可能产生非唯一索引,建议提前检查或设置 ignore_index=True(此时需放弃原始索引,改用连续整数索引)。
此方法无需循环、不依赖 pd.concat(...).assign() 手动插入列,代码简短、语义清晰,是处理“字典→宽表+键列”场景的标准范式。


















