跳至内容

Renaming Columns in Pandas: A Complete Guide With Examples

Learn how to rename columns in pandas with .rename(), df.columns, and .set_axis(), plus Python functions for snake_case and fixes for KeyError and ValueError.
更新 2026年8月17日  · 13分钟

用 AI 探索

ChatGPTClaudePerplexity

您从公司的数据库拉取了最新的 CSV,运行 df.head(),看到 CUST_ID_NBRtxn_amt_usd_2Unnamed: 7,或者一个名为 Customer Name (Full) 的列,后面还带着一个不容易发现的空格,直到一个 KeyError 毁掉您整个下午。杂乱的列名是实际数据工作中的小摩擦之一,而在 pandas 中重命名列通常是您在任何真正的分析之前会做的第一步。

在这篇关于如何在 pandas 中重命名列的教程中,您将学到:

  • 使用 .rename() 重命名单个或多个列

  • 使用 df.columns.set_axis() 一次性替换所有列名

  • 应用函数批量转换列名

  • 使用 .str 访问器清理杂乱的列名

  • pd.read_csv() 载入时重命名列

  • 在 Polars 中处理相同任务

  • 避免遇到 KeyErrorValueError: Length mismatch

本教程假定您会导入 pandas 并创建一个 DataFrame。我们将贯穿使用贴近真实的数据集,如客户记录、销售导出和传感器读数,让这些范式可以直接映射到您实际处理的数据上。

应选择哪种 Pandas 重命名方法?

选择与任务范围匹配的方法:定向重命名、完全替换,或对每个名称应用统一规则。

您的目标

方法

适用场景

重命名单个或少数特定列

df.rename(columns={"old": "new"})

其他列保持不变;可安全用于方法链中

替换所有列名

df.columns = [...]df.set_axis([...], axis=1)

比逐个映射更快;当需要链式调用时使用 .set_axis()

按规则重命名(小写、snake_case、去空格)

df.rename(columns=func)df.columns.str....

只需表达一次规则,而非逐列列出

在加载时重命名

pd.read_csv(..., header=0, names=[...])

当您可控模式并且不想要单独步骤时

在 Polars 中实现以上任意方式

df.rename({"old": "new"}), .alias()select

不可变且链式优先,因此没有 inplace

如何使用 .rename() 重命名列?

.rename() 方法是执行 pandas DataFrame 列重命名最灵活的方式,也是您最常用的方法。 

它接收一个将旧名称映射到新名称的字典,不在字典中的列保持不变,并且默认返回一个新的 DataFrame 而不是修改原始对象。这使得 .rename() 可以安全地用于方法链中,也更便于调试时理解行为。

该字典模式如下所示:

sales_data.rename(columns={"old_name": "new_name"})

如果您对字典不熟悉,建议回顾我们的 Python 字典方法教程

关于旧版 copy 参数的说明

在看示例前先说明一点。Pandas 3.0 废弃了 copy 参数,并将 Copy-on-Write 设为默认行为。实际效果是,您不再需要担心 .rename() 是否会对数据进行昂贵的复制。pandas 会在底层按需惰性处理。主要需要考虑的参数只剩下 inplace,我们会在第三小节介绍。

重命名单个列

想象您刚加载了一个从旧版 CRM 导出的客户记录。列名的缩写在 2008 年设计数据库的人看来有意义,但对您并不直观。这是最简单的 pandas 重命名操作:一个旧名、一个新名,放进字典中:

import pandas as pd

customers = pd.DataFrame({
    "cust_id_nbr": [4521, 4522, 4523, 4524],
    "first_nm": ["Abe", "Rick", "Pat", "Kim"],
    "signup_dt": ["2008-03-12", "2008-03-15", "2008-03-18", "2008-03-21"]
})

print(customers)

Python DataFrame

现在,将 cust_id_nbr 重命名为更易读的名称:

customers_renamed = customers.rename(columns={"cust_id_nbr": "customer_id"})
print(customers_renamed)

Python DataFrame

原始的 customers DataFrame 未被修改。.rename() 返回了一个新的 DataFrame,我们将其赋给 customers_renamed。另外两列(first_nmsignup_dt)保持不变。

重命名多个列

该字典可以自然扩展。要处理 pandas 的多列重命名任务,只需在映射中添加更多键值对:

customers_clean = customers.rename(columns={
    "cust_id_nbr": "customer_id",
    "first_nm": "first_name",
    "signup_dt": "signup_date"
})

print(customers_clean)

Python DataFrame

还有一种替代语法,使用 mapperaxis 参数而不是 columns 关键字:

customers.rename(mapper={"cust_id_nbr": "customer_id"}, axis=1)

axis=1 告诉 pandas 您要操作的是列(相对地,axis=0 针对行索引标签)。两种形式产生相同结果。大多数实战代码使用 columns={...},因为一眼更易读,所以余下教程我们将坚持这种写法。

一个实用细节是,如果传入的键不匹配任何现有列,.rename() 默认会静默忽略。这在编写可复用函数、可能处理略有不同模式的 DataFrame 时很方便,但也可能隐藏拼写错误。若要在未知列名时让 pandas 抛出错误,请传入 errors='raise'

使用 inplace 与返回新 DataFrame

默认情况下,.rename() 会返回一个新的 DataFrame,并保持原对象不变。如果您希望直接修改现有 DataFrame,请传入 inplace=True

# 返回一个新的 DataFrame(默认)
customers_v2 = customers.rename(columns={"first_nm": "first_name"})

# 直接修改 customers,本方法返回 None
customers.rename(columns={"first_nm": "first_name"}, inplace=True)

print(customers)

Python DataFrame

那么该用哪种?多数情况下,默认返回新 DataFrame 更优。调试时也更容易,因为当出现问题时,您仍可检查原始 DataFrame。这也避开了在旧代码中产生 SettingWithCopyWarning 的别名问题。

性能也不再是偏好 inplace 的理由。随着 pandas 3.0+ 中 Copy-on-Write 成为默认,非 inplace 版本使用惰性复制。只有在发生修改时才真正复制数据。inplace=True 节省内存的老观点已大不如前。

唯一仍然自然使用 inplace=True 的场景,是在简短的探索性脚本中,您按步骤清理单个 DataFrame,且不关心链式调用。对于生产代码或日后会回看的内容,优先选择默认方式。

如何一次性重命名 pandas 中的所有列?

有时您并不想把旧名映射到新名,只是想一次性替换所有列名。这种情况比您想象得更常见,比如无表头的 CSV,pandas 会将 0, 1, 2 作为列名;或者表头是其他语言的数据集;又或系统生成的导出,列名像 Field1Field2Field3

常见做法有两种:直接给 df.columns 赋值,或使用 .set_axis()。它们产生相同结果,权衡点在于简洁与可链式调用之间。

给 df.columns 赋值列表

最直接的方法是给 columns 属性赋一个新列表。看这个 DataFrame,由无表头的信息(类似读取无表头 CSV 时的情形)构建。pandas 退化为使用整数列名:

import pandas as pd

sensor_readings = pd.DataFrame([
    [1.2, 22.5, 1013],
    [1.5, 22.7, 1012],
    [1.3, 22.6, 1013]
])

print(sensor_readings)

Python DataFrame

这些 012 列名对分析毫无用处。通过给 columns 属性赋一个新列表来替换它们:

sensor_readings.columns = ["wind_speed", "temperature_c", "pressure_hpa"]
print(sensor_readings)

Python DataFrame

关于这种方法有两点需要注意: 

  1. 列表长度必须完全匹配。若为四列的 DataFrame 仅传三列名,pandas 会抛出 ValueError: Length mismatch(我们稍后将详细讲解)。 

  2. 它会就地修改 DataFrame。这里没有 inplace 参数,因为赋值本身就是修改。如果您想得到一个新副本,先用 .copy(),或使用下方的 .set_axis()

使用 .set_axis() 进行方法链式调用

.set_axis() 方法做的是同一件事,但会返回新的 DataFrame,因此可以与其他操作链式调用。看一个类似的无表头 DataFrame,这次数据更杂,比如多余的小数位和缺失读数:

raw_sensor = pd.DataFrame([
    [1.234, 22.567, 1013],
    [1.512, 22.789, 1012],
    [None,  22.601, 1013],
    [1.345, 22.612, 1013]
])

sensor_clean = (
    raw_sensor
    .set_axis(["wind_speed_mps", "temp_celsius", "pressure_hpa"], axis=1)
    .round(1)
    .dropna()
)

print(sensor_clean)

Python DataFrame

axis=1 参数表示您在设置列标签(使用 axis=0 则设置行索引)。由于 .set_axis() 返回一个新的 DataFrame,它很自然地融入您在实际 ETL 或分析代码中会写的链式转换流水线中。这也是在生产环境更偏好它而非直接赋值的主要原因。

如何在 pandas 中使用函数重命名列?

与其把每个旧名映射到新名,您可以向 .rename() 传入一个函数,pandas 会将其应用到每个列名上。当您有一条规则而不是一个列表时,这正是合适工具。例如“全部小写”或“将空格全部替换为下划线”。

使用内置字符串函数

最简单的情况是标准化大小写。将 str.lowerstr.upperstr.title 直接传给 columns 参数:

import pandas as pd

orders = pd.DataFrame({
    "Order ID": [1001, 1002, 1003],
    "Customer Name": ["Abe", "Rick", "Pat"],
    "Total Amount": [49.99, 120.00, 75.50]
})

orders_lower = orders.rename(columns=str.lower)
print(orders_lower.columns.tolist())

Python column list

注意我们传入的是函数本身(str.lower),而不是调用它(str.lower())。pandas 会逐个将其应用于每个列名。这是大小写标准化的简洁捷径,但它不处理空格或特殊字符。要处理这些,您需要 lambda 或自定义函数。

使用 lambda 与自定义函数

对于超出大小写变换的需求,lambda 提供了在一行内表达转换的便捷方式。如果您未使用过 lambda,可以先阅读我们的 Python lambda 函数入门指南

常见模式是一步完成小写化和空格替换为下划线。沿用上一个例子:

orders_snake = orders.rename(columns=lambda col: col.lower().replace(" ", "_"))
print(orders_snake.columns.tolist())

Python column list

当逻辑更复杂时,将其提炼为具名函数。看这个帮助函数,它将 camelCasePascalCase 列名转换为 snake_case

import re

def to_snake_case(name: str) -> str:
    """Convert camelCase or PascalCase to snake_case."""
    s1 = re.sub(r"(.)([A-Z][a-z]+)", r"\1_\2", name)
    s2 = re.sub(r"([a-z0-9])([A-Z])", r"\1_\2", s1)
    return s2.lower()

api_response = pd.DataFrame({
    "userId": [1, 2, 3],
    "firstName": ["Abe", "Rick", "Pat"],
    "accountCreatedAt": ["2024-01-01", "2024-01-02", "2024-01-03"]
})

api_clean = api_response.rename(columns=to_snake_case)
print(api_clean.columns.tolist())

Python column list

像这样的具名函数比精巧的一行式更易于测试、在不同笔记本间复用、并进行文档化。逻辑能在一行表达时用 lambda,否则用自定义函数。

如何在 pandas 中批量清理杂乱的列名?

当数据来自电子表格、第三方 API 或手工编辑的 CSV 时,列名往往存在 .rename() 难以优雅修复的问题,比如:

  • 末尾空白
  • 大小写混用
  • 括号
  • 连字符
  • 特殊字符
  • 不可见的 Unicode 字符

在这些情况下,最干净的做法是使用 .str 访问器直接对 df.columns 操作,它提供了向量化的字符串方法(包括正则),可一次性作用于所有列名。这也是高质量Python 数据清洗的基础。清理列名会让下游每一步(筛选、合并、绘图)更不易出错。

去除空白和特殊字符

看这个 DataFrame,列名类似那种被太多人改动过的 Excel 导出的样子:

import pandas as pd

raw_export = pd.DataFrame({
    "  Order ID ": [1001, 1002, 1003],
    "Customer Name (Full)": ["Abe", "Rick", "Pat"],
    "Total Amount ($)": [49.99, 120.00, 75.50],
    "Order-Date": ["2024-03-12", "2024-03-15", "2024-03-18"]
})

print(raw_export.columns.tolist())

Python column list

前后空格是最常见也最令人挠头的问题,因为它们不可见。用一行代码去掉它们:

raw_export.columns = raw_export.columns.str.strip()
print(raw_export.columns.tolist())

Python column list

对于特殊字符,.str.replace() 可接受正则模式。下面的模式保留字母、数字、下划线和空格,去掉其他所有字符:

raw_export.columns = raw_export.columns.str.replace(r"[^a-zA-Z0-9_ ]", "", regex=True)
print(raw_export.columns.tolist())

Python column list

连字符、括号和美元符号都没了。请注意,Total Amount 现在末尾带了一个空格(原先 ($) 所在的位置),而 OrderDate 则完全丢失了连字符。这正是为什么我们会在清洗流水线末尾再进行一次 strip。

标准化为 snake_case

一个常见的最佳实践是在开始分析前,将所有列名转换为 snake_case:即全部小写、以下划线分隔单词、不含特殊字符。将 .str 方法串联起来,一条表达式即可达成:

raw_export = pd.DataFrame({
    "  Order ID ": [1001, 1002, 1003],
    "Customer Name (Full)": ["Abe", "Rick", "Pat"],
    "Total Amount ($)": [49.99, 120.00, 75.50],
    "Order-Date": ["2024-03-12", "2024-03-15", "2024-03-18"]
})

raw_export.columns = (
    raw_export.columns
    .str.strip()                                  # 移除首尾空白
    .str.lower()                                  # 全部小写
    .str.replace(r"[^a-z0-9]+", "_", regex=True)  # 将非字母数字字符压缩为下划线
    .str.strip("_")                               # 移除首尾下划线
)

print(raw_export.columns.tolist())

Python column list

四行代码,列名就变得可预测、全小写并用下划线分隔。值得将这一模式保存为一个工具函数。一旦有了它,来多少“脏” DataFrame 都能应对自如。 

您也常会把重命名与删除列结合使用。有关这一步的内容,请参阅pandas 删除列教程

如何在 pandas 加载数据时重命名列?

如果在加载文件之前您就已经知道需要不同的列名,可以直接在 pd.read_csv() 中进行重命名。向 names 参数传入一个名称列表,并设置 header=0 以告知 pandas 跳过现有表头,改用您的列名:

import pandas as pd
from io import StringIO

# Simulating a CSV file for demonstration
csv_data = """txnId,custId,amt,date
1001,C01,49.99,2024-01-15
1002,C02,125.00,2024-01-16
1003,C01,79.50,2024-01-17"""

# Renames columns at load time, skipping the original header
transactions = pd.read_csv(
    StringIO(csv_data),
    header=0,
    names=["transaction_id", "customer_id", "amount_usd", "transaction_date"]
)
print(transactions)

Python DataFrame

当您可控模式并不想让单独的 .rename() 步骤使加载代码变得杂乱时,这是一个很有用的捷径。如果文件根本没有表头行,省略 header=0,直接用 names=[...] 从零指定列名。若想更深入了解数据加载选项,建议阅读 pandas read_csv() 教程。

但需注意:这是一个全或无的方式。names 参数会替换每个列名,因此列表长度必须与文件中的列数完全一致。如果您只想重命名少数列,请先加载文件,然后使用 .rename()

若想在引导式演练中将这些模式与其他常见清理任务结合起来学习,推荐参加我们的 Cleaning Data in Python 课程。

在 Polars 与 Pandas 中重命名列

如果您在 pandas 和 Polars 之间切换,或有此预期,了解它们各自如何处理列重命名是值得的。高层 API 相似,但细节有所不同,第一次会有些出乎意料。Polars 是一个以 Rust 为后端的高速 DataFrame 库,在现代数据栈中越来越常见,而您在 pandas 中形成的肌肉记忆并不总能无缝迁移。

核心思路是相同的:用字典将旧名映射到新名。差别在细节上。Polars 设计为不可变(无 inplace),链式调用是惯用风格,且在 select 中进行列级重命名时使用 .alias(),而不是单独的重命名步骤。

并排比较

任务

Pandas

Polars

重命名特定列

df.rename(columns={"old": "new"})

df.rename({"old": "new"})

替换所有列名

df.columns = [...]df.set_axis([...], axis=1)

df.rename(dict(zip(df.columns, [...])))

在选择时重命名

先选择,再用 .rename()

df.select(pl.col("old").alias("new"))

就地修改

支持 inplace=True

不支持。始终返回新的 DataFrame

惯用风格

inplace 或链式调用

始终链式调用

两种库中的相同重命名

做个对比,以下是在两个库中的简单重命名。

Pandas:

# Pandas
import pandas as pd

orders_pd = pd.DataFrame({
    "ord_id": [1001, 1002, 1003],
    "cust_nm": ["Abe", "Rick", "Pat"]
})

orders_pd = orders_pd.rename(columns={"ord_id": "order_id", "cust_nm": "customer_name"})
print(orders_pd)

Python DataFrame

Polars:

# Polars
import polars as pl

orders_pl = pl.DataFrame({
    "ord_id": [1001, 1002, 1003],
    "cust_nm": ["Abe", "Rick", "Pat"]
})

orders_pl = orders_pl.rename({"ord_id": "order_id", "cust_nm": "customer_name"})
print(orders_pl)

Python DataFrame

可以注意到两点小差异。Polars 的 .rename() 直接接收字典,没有 columns= 关键字,因为 Polars 只支持重命名列(无行索引)。并且您必须重新赋值结果,Polars 中没有 inplace=True,每个操作都会返回新的 DataFrame。

Polars 的输出还会内联显示 dtypes(i64str)以及顶部的形状信息,这是许多人切换过去后会喜欢的小便利之一。 

在选择时重命名列

在转换过程中进行重命名时,Polars 在 .select().with_columns() 中使用 .alias()

# Polars
import polars as pl

orders_pl = pl.DataFrame({
    "ord_id": [1001, 1002, 1003],
    "cust_nm": ["Abe", "Rick", "Pat"]
})

# Select and rename in one expression
renamed = orders_pl.select(
    pl.col("ord_id").alias("order_id"),
    pl.col("cust_nm").alias("customer_name")
)

print(renamed)

Python DataFrame

在 pandas 中,等效做法是在列选择后再 .rename()。两者并无优劣,只是各自库的设计哲学所致。 

如果您想更深入地比较二者,我推荐阅读 pandas 与 polars 性能 教程。若您想将 polars 纳入工具箱,推荐参加我们的 Introduction to Polars程。 

常见错误及其修复方法

在重命名 pandas 列时,有两类错误反复出现。下面是它们的表现、原因以及修复方法。

KeyError:找不到列名

默认情况下,.rename() 会静默忽略与现有列不匹配的键。但如果您传入 errors='raise' 以捕捉拼写错误,那么当键不存在时,您会得到一个 KeyError

import pandas as pd

orders = pd.DataFrame({
    "order_id": [1001, 1002, 1003],
    "customer_name": ["Abe", "Rick", "Pat"]
})

# This raises an error
orders.rename(columns={"Order_ID": "order_id"}, errors="raise")

KeyError

最常见原因是大小写不一致(Order_IDorder_id)或不可见的尾随空格("order_id ""order_id")。遇到 KeyError 时,按以下顺序检查三件事:

  1. 拼写与大小写是否完全一致
  2. 是否存在隐藏空白
  3. 该列是否已在更早步骤被重命名

要验证实际的列名:

print(orders.columns.tolist())

# Use repr() as an alternative
print([repr(c) for c in orders.columns])

Python column list

一旦看到 pandas 实际持有的精确字符串,通常就能立刻发现拼写问题。然后修正并重跑:

orders = orders.rename(columns={"order_id": "Order_ID"}, errors="raise")
print(orders.columns.tolist())

Python column list

问题在于,何时使用 errors='raise',何时使用默认的 errors='ignore'。 

  • 默认更宽容。适合在处理模式可变的 DataFrame 的脚本中使用,缺失列不应导致崩溃。 

  • 在开发时,尤其是笔记本环境中,为了让拼写错误尽早暴露,切换为 errors='raise',以免静默失败导致下游长时间困惑的调试。

ValueError:df.columns 长度不匹配

当您给 df.columns 赋列表或者使用 .set_axis() 时,列表长度必须与列数完全一致。否则 pandas 会抛出 ValueError

import pandas as pd

products = pd.DataFrame({
    "sku": ["A100", "A101", "A102"],
    "name": ["Widget", "Gadget", "Gizmo"],
    "price": [9.99, 14.99, 19.99]
})

# This raises an error
products.columns = ["product_sku", "product_name"]

ValueError

DataFrame 有三列,但只提供了两个新名称。修复方法是在赋值前检查列数:

print(len(products.columns))
products.columns = ["product_sku", "product_name", "product_price"]
print(products.columns.tolist())

Python column list

如果您处理的 DataFrame 列数可能变化,使用带字典的 .rename() 更安全。它只会触及您指明的列,因此多一列或少一列都不会让代码崩溃。

结语

在 pandas 中重命名列,核心在于选择与任务范围匹配的方法。无论选择哪种方式,最大的实际收益是确定并坚持一种命名规范,并在每次分析的一开始就应用它。snake_case 是多数 Python 代码采用的风格。干净的列名在开头多花几秒钟,却能为整个项目省去后续 KeyError 的惊喜。

针对性重命名请使用带字典的 .rename()。当每个列名都需要更换时,赋值给 df.columns 或使用 .set_axis() 比构建完整映射字典更快。而如果重命名遵循某种规则,比如去空白、全部小写、camelCase 转换,那么传入函数或使用 .str 访问器可以让您一次性表达规则而无需逐一列举。Polars 用类似的 API 完成相同工作,但其不可变、链式优先的风格会促使您形成不同的习惯。 

若想继续提升您的 DataFrame 技能,建议下一步学习 Data Manipulation with pandas 课程。如果您想要结构化的学习路径,Data Analyst in Python 职业路径会在教授 DataFrame 操作的同时覆盖分析师工具包的其他部分。

在 pandas 中重命名列的常见问题

如何在 pandas 中重命名列?

方法有多种,但最直接的是 使用 df = df.rename(columns={"old_name": "new_name"})。您也可以传入 inplace=True 来直接修改 DataFrame。

如何在 pandas 中重命名多个列?

要在 pandas 中重命名多个列,将所有重命名放在一个字典中传入:df.rename(columns={"old1": "new1", "old2": "new2"})

如何一次性重命名 pandas DataFrame 的所有列?

将包含新名称的列表赋给 df.columns。注意:确保列表长度与列数匹配,否则会得到 ValueError

为什么 df.rename() 没有改动我的 DataFrame?

默认情况下,.rename() 返回一个新的 DataFrame。请将结果重新赋回 df = df.rename(...),或者使用 inplace=True

如何在 pandas 中将列名改为小写?

使用 df.columns = df.columns.str.lower() 一步将所有列名转换为小写。

主题

与 DataCamp 一起学习 Python!

Courses

使用 pandas 进行数据处理

4小时
559.2K
学习如何使用 pandas 导入和清洗数据、计算统计量并创建可视化。
查看详情Right Arrow
开始课程
查看更多Right Arrow