
本文介绍一种简洁、向量化的方式,利用 set_axis() 和列选择组合,一次性完成列的复制、重命名与保留原始列(如 values)的操作,避免显式循环,提升代码可读性与执行效率。
本文介绍一种简洁、向量化的方式,利用 `set_axis()` 和列选择组合,一次性完成列的复制、重命名与保留原始列(如 `values`)的操作,避免显式循环,提升代码可读性与执行效率。
在数据处理中,常需基于原始 DataFrame 构建多个结构化子表(例如适配不同数据库表结构),此时不仅需要重命名列,还需复制源列值到新列名下——尤其当同一源列被映射到多个目标列(如 B → dt_start 和 B → dt_end)时,简单的 rename() 无法满足需求,而手动循环又违背 pandas 的向量化设计哲学。
推荐解法是:先按需选取源列(支持重复列名),再统一重命名列轴。核心步骤如下:
-
提取源列名列表:从映射字典(如
mapping_dict['table_1'])的values()获取需复制的原始列(如['A', 'B', 'B']); -
拼接保留列:将额外需保留的列(如
['values'])追加至该列表; -
列选择 + 重命名:用
df[...]选取对应列(自动复制值),再通过.set_axis(..., axis=1)批量赋予新列名。
import pandas as pd
df = pd.DataFrame({
'A': [1, 2, 3],
'B': ['2025-10-01', '2025-10-02', '2025-10-01'],
'C': ['2025-02-10', '2025-02-15', '2025-02-20'],
'D': [0, 5, 4],
'values': [52.3, 60.0, 70.6]
})
mapping_dict = {
'table_1': {'id': 'A', 'dt_start': 'B', 'dt_end': 'B'},
'table_2': {'id': 'D', 'dt_start': 'C', 'dt_end': 'C'}
}
# ✅ 一行生成 table_1
table_1 = df[
list(mapping_dict['table_1'].values()) + ['values']
].set_axis(
list(mapping_dict['table_1'].keys()) + ['values'],
axis=1
)
print(table_1)
输出:
id dt_start dt_end values 0 1 2025-10-01 2025-10-01 52.3 1 2 2025-10-02 2025-10-02 60.0 2 3 2025-10-01 2025-10-01 70.6
⚠️ 注意事项:
df[[col1, col2, col2]]会真实复制列数据(非视图),因此col2出现两次即生成两个独立副本;set_axis()是纯列名重命名操作,不改变数据顺序或内容,安全高效;- 若需复用,建议封装为函数(见下方),增强可维护性。
def create_mapped_table(
df: pd.DataFrame,
mapping: dict,
keep_cols: list = None
) -> pd.DataFrame:
"""
根据列映射关系生成新 DataFrame
Parameters:
-----------
df : 原始 DataFrame
mapping : {新列名: 原列名} 的字典,支持原列名重复
keep_cols : 需额外保留的列名列表(默认为空)
Returns:
--------
新 DataFrame,列名为 mapping.keys() + keep_cols
"""
keep_cols = keep_cols or []
source_cols = list(mapping.values()) + keep_cols
new_columns = list(mapping.keys()) + keep_cols
return df[source_cols].set_axis(new_columns, axis=1)
# 复用示例
table_1 = create_mapped_table(df, mapping_dict['table_1'], ['values'])
table_2 = create_mapped_table(df, mapping_dict['table_2'], ['values'])
该方法完全避免了 for 循环和 drop() 操作,兼具性能、可读性与扩展性,是处理多目标列映射场景的推荐实践。










