Python
轻松重命名 Pandas DataFrame 列:快速指南

轻松重命名 Pandas DataFrame 列:快速指南

MoeNagy Dev

在 Pandas 中重命名列

Pandas 列重命名基础

了解 Pandas DataFrame 中的列名

Pandas DataFrame 是一种二维数据结构,以表格格式存储数据,类似于电子表格。DataFrame 中的每一列代表不同的特征或变量,列名对于识别和处理数据至关重要。

访问和修改列名

您可以使用 columns 属性访问 DataFrame 的列名。这将返回一个包含列名的 pandas Index 对象。

import pandas as pd
 
# 创建一个示例 DataFrame
df = pd.DataFrame({
    'A': [1, 2, 3],
    'B': [4, 5, 6],
    'C': [7, 8, 9]
})
 
# 访问列名
print(df.columns)
# 输出: Index(['A', 'B', 'C'], dtype='object')

要修改列名,可以将新的列名列表或数组赋值给 columns 属性。

# 重命名列
df.columns = ['col1', 'col2', 'col3']
print(df.columns)
# 输出: Index(['col1', 'col2', 'col3'], dtype='object')

重命名单个列

使用 rename() 方法

Pandas 中的 rename() 方法允许您重命名一个或多个列。要重命名单个列,可以将当前列名和新列名作为参数传递给 rename() 方法。

# 重命名单个列
df = df.rename(columns={'col1': 'new_col1'})
print(df.columns)
# 输出: Index(['new_col1', 'col2', 'col3'], dtype='object')

指定新的列名

当重命名单个列时,您可以...

# 重命名单个列
df = df.rename(columns={'col2': 'updated_col2'})
print(df.columns)
# 输出: Index(['new_col1', 'updated_col2', 'col3'], dtype='object')

就地更新 DataFrame

默认情况下,rename() 方法会返回一个新的 DataFrame,其中包含更新后的列名。如果您想就地修改原始的 DataFrame,可以将 inplace 参数设置为 True

# 就地重命名单个列
df.rename(columns={'updated_col2': 'final_col2'}, inplace=True)
print(df.columns)
# 输出: Index(['new_col1', 'final_col2', 'col3'], dtype='object')

重命名多个列

同时重命名多个列

您可以通过向 rename() 方法传递一个字典来同时重命名多个列,其中键是当前的列名,值是新的列名。

# 重命名多个列
df = df.rename(columns={'new_col1': 'column_a', 'final_col2': 'column_b', 'col3': 'column_c'})
print(df.columns)
# 输出: Index(['column_a', 'column_b', 'column_c'], dtype='object')

使用字典映射旧名称到新名称

传递给 rename() 方法的字典充当旧列名和新列名之间的映射。

# 使用字典重命名多个列
rename_dict = {'column_a': 'feature_1', 'column_b': 'feature_2', 'column_c': 'feature_3'}
df = df.rename(columns=rename_dict)
print(df.columns)
# 输出: Index(['feature_1', 'feature_2', 'feature_3'], dtype='object')

链式调用 rename() 方法

您可以链式调用 rename() 方法来一次性更新列名。

# 链式调用 rename() 方法和字典
df = df.rename(columns={'feature_1': 'var_a', 'feature_2': 'var_b', 'feature_3': 'var_c'})
print(df.columns)
# 输出: Index(['var_a', 'var_b', 'var_c'], dtype='object')

根据条件重命名列

重命名列基于特定标准重命名列

有时,您可能希望根据列名中的某些条件或模式来重命名列。这可以通过使用 lambda 函数或正则表达式来实现。

使用 lambda 函数或正则表达式

以下是使用 lambda 函数重命名列的示例:

# 使用 lambda 函数重命名列
df = df.rename(columns=lambda x: 'new_' + x if x.startswith('var') else x)
print(df.columns)
# 输出: Index(['new_var_a', 'new_var_b', 'new_var_c'], dtype='object')

您也可以使用正则表达式执行更复杂的重命名操作:

import re
 
# 使用正则表达式重命名列
df = df.rename(columns=lambda x: re.sub(r'^var_', 'feature_', x))
print(df.columns)
# 输出: Index(['feature_a', 'feature_b', 'feature_c'], dtype='object')

应用条件重命名

rename() 方法可以接受字典或函数作为 columns 参数。这允许您根据特定条件应用重命名。

# 根据条件重命名列
df = df.rename(columns=lambda x: 'col_' + x.upper() if x.startswith('feature') else x)
print(df.columns)
# 输出: Index(['COL_A', 'COL_B', 'COL_C'], dtype='object')

在重命名时处理重复项

识别重复的列名

在重命名列之前,最好先检查 DataFrame 中是否存在任何重复的列名。Pandas 提供了 duplicated() 方法来识别重复项。

# 检查是否存在重复的列名
print(df.columns.duplicated())
# 输出: array([False, False, False])

解决重命名列时的冲突

如果遇到重复的列名,在重命名列之前需要解决这些冲突。一种方法是在重复的列名后附加后缀。

# 解决重复的列名
df.columns = [f"{col}_{i}" if col in df.columns[df.columns.duplicated()] else col for i, col in enumerate(df.columns)]
print(df.columns)
# 输出: Index(['COL_A', 'COL_B', 'COL_C_0'], dtype='object')

确保列名的唯一性

解决任何重复的列名后,您可以继续重命名列,同时确保新名称是唯一的。

# 重命名列并确保唯一性
df = df.rename(columns={'COL_A': 'feature_a', 'COL_B': 'feature_b', 'COL_C_0': 'feature_c'})
print(df.columns)
# 输出: Index(['feature_a', 'feature_b', 'feature_c'], dtype='object')

使用 MultiIndex 重命名列

处理分层列结构

Pandas DataFrames 可以有一个 MultiIndex,这是一个分层的列结构。在这种情况下,您需要考虑 MultiIndex 的不同级别,以重命名列。

# 创建一个带有 MultiIndex 的 DataFrame
df = pd.DataFrame([[1, 2, 3], [4, 5, 6]], columns=pd.MultiIndex.from_tuples([('A', 'X'), ('A', 'Y'), ('B', 'Z')]))
print(df.columns)
# 输出: MultiIndex([('A', 'X'), ('A', 'Y'), ('B', 'Z')], )

重命名 MultiIndex 的单个级别

要重命名 MultiIndex 的单个级别,可以将一个字典传递给 rename() 方法,其中键是级别名称,值是新名称。

# 重命名 MultiIndex 的级别
df = df.rename(columns=str.lower, level=0)
df = df.rename(columns={'x': 'feature_x', 'y': 'feature_y', 'z': 'feature_z'}, level=1)
print(df.columns)
# 输出: MultiIndex([('a', 'feature_x'), ('a', 'feature_y'), ('b', 'feature_z')], )

更新 MultiIndex DataFrame 中的列名

在处理 MultiIndex DataFrame 时,您可以通过传递一个字典或函数到 rename() 方法来更新列名。

# 重命名 MultiIndex DataFrame 中的列
df = df.rename(columns={('a', 'feature_x'): ('alpha', 'feat_x'), ('a', 'feature_y'): ('alpha', 'feat_y'), ('b', 'feature_z'): ('beta', 'feat_z')})
print(df.columns)
# 输出: MultiIndex([('alpha', 'feat_x'), ('alpha', 'feat_y'), ('beta', 'feat_z')], )

'feat_y'), ('beta', 'feat_z')], )


## 自动化列重命名

### 使用循环重命名多个列

您可以使用循环遍历列名列表,逐个重命名列。

```python
# 使用循环重命名列
old_names = ['alpha', 'beta', 'gamma']
new_names = ['feature_a', 'feature_b', 'feature_c']

for old, new in zip(old_names, new_names):
    df = df.rename(columns={old: new})

print(df.columns)
# 输出: Index(['feature_a', 'feature_b', 'feature_c'], dtype='object')

应用函数重命名列

您也可以定义一个函数来处理列重命名,并将其应用于 DataFrame。

# 使用函数重命名列
def rename_columns(df, mapping):
    return df.rename(columns=mapping)
 
rename_map = {'feature_a': 'var_a', 'feature_b': 'var_b', 'feature_c': 'var_c'}
df = rename_columns(df, rename_map)
print(df.columns)
# 输出: Index(['var_a', 'var_b', 'var_c'], dtype='object')

动态生成新的列名

在某些情况下,您可能需要根据特定的模式或逻辑生成新的列名。您可以使用函数或循环创建新的列名,然后应用重命名。

# 动态生成新的列名
new_names = [f'col_{i}' for i in range(1, len(df.columns) + 1)]
df = df.rename(columns=dict(zip(df.columns, new_names)))
print(df.columns)
# 输出: Index(['col_1', 'col_2', 'col_3'], dtype='object')

重命名列和数据清洗

重命名列以提高可读性

重命名列可以提高数据的可读性和理解性。使用描述性和有意义的名称,清楚地传达每个列的内容。

# 重命名列以提高可读性
df = df.rename(columns={'col_1': 'customer_id', 'col_2': 'order_date', 'col_3': 'total_amount'})
print(df.columns)
# 输出: Index(['customer_id', 'order_date', 'total_amount'], dtype='object')

标准化列名以保持一致性以下是中文翻译:

确保您的列名遵循一致的命名约定,例如使用小写、snake_case 或 CamelCase。这将使您的代码和数据更易维护。

# 标准化列名
df = df.rename(columns=lambda x: x.lower().replace(' ', '_'))
print(df.columns)
# 输出: Index(['customer_id', 'order_date', 'total_amount'], dtype='object')

函数

函数是 Python 的基本构建块。它们允许您封装一组指令并在整个代码中重复使用。函数可以接受参数,执行一些操作,并返回值。

以下是一个简单的计算矩形面积的函数示例:

def calculate_area(length, width):
    area = length * width
    return area
 
# 使用
length = 5
width = 10
result = calculate_area(length, width)
print(f"矩形的面积是 {result} 平方单位。")

输出:

矩形的面积是 50 平方单位。

在这个例子中,calculate_area 函数接受两个参数 lengthwidth,并返回计算出的面积。我们然后调用该函数,传递必要的参数,并将结果存储在 result 变量中。

函数参数

函数可以有不同类型的参数:

  • 位置参数: 这些是在调用函数时必须按正确顺序提供的基本参数。
  • 关键字参数: 这些允许您在调用函数时指定参数名称,使代码更具可读性,并允许您更改参数的顺序。
  • 默认参数: 这些是具有预定义值的参数,如果在调用函数时未提供参数,则使用该值。
  • 可变长度参数: 这些允许您向函数传递任意数量的参数,这些参数将被收集到元组或列表中。

以下是一个演示这些不同类型参数的示例:

def greet(name, greeting='Hello', punctuation='!'):
    print(f"{greeting}, {name}{punctuation}")
 
# 使用
greet('Alice')
greet('Bob', 'Hi')
greet('Charlie', punctuation='?')
greet('David', 'Howdy', '.')
```问候="你好", 标点符号="!"):
    print(f"{问候}, {名字}{标点符号}")
 
# 位置参数
问候("Alice")  # 输出: 你好, Alice!
问候("Bob", "嗨")  # 输出: 嗨, Bob!
 
# 关键字参数
问候(名字="Charlie", 问候="嗨")  # 输出: 嗨, Charlie!
问候(标点符号=".", 名字="David")  # 输出: 你好, David.
 
# 可变长度参数
def 求和(*args):
    总和 = 0
    for 数字 in args:
        总和 += 数字
    return 总和
 
print(求和(1, 2, 3))  # 输出: 6
print(求和(4, 5, 6, 7, 8))  # 输出: 30

作用域和命名空间

在 Python 中, 变量有一个定义的作用域, 它决定了变量可以被访问和修改的位置。 主要有两种作用域:

  1. 局部作用域: 在函数或块(如循环或 if 语句)内定义的变量具有局部作用域, 只能在该函数或块内访问。
  2. 全局作用域: 在任何函数或块之外定义的变量具有全局作用域, 可以从代码的任何地方访问。

你可以使用 global 关键字从函数内部访问和修改全局变量。

全局变量 = 10
 
def 修改全局():
    global 全局变量
    全局变量 += 5
    print(f"全局变量值: {全局变量}")
 
修改全局()  # 输出: 全局变量值: 15
print(全局变量)  # 输出: 15

递归函数

递归函数是调用自身来解决问题的函数。它们在可以将问题分解为更小的、相似的子问题时很有用。

下面是一个计算阶乘的递归函数示例:

def 阶乘(n):
    if n == 0 or n == 1:
        return 1
    else:
        return n * 阶乘(n - 1)
 
print(阶乘(5))  # 输出: 120

在这个例子中, 阶乘 函数会一直调用自身, 直到达到基础情况(当 n 为 0 或 1 时), 此时返回 1。然后函数会逐步返回上一层的结果, 直到最终得到 120。模块和包

Python 的模块化设计允许您将代码组织成可重复使用的组件,称为模块。模块可以包含函数、类和变量,可以在代码的其他部分导入和使用。

下面是一个创建简单模块并导入它的示例:

# my_module.py
def greet(name):
    print(f"Hello, {name}!")
 
# main.py
import my_module
 
my_module.greet("Alice")  # 输出: Hello, Alice!

在这个例子中,我们创建了一个名为 my_module.py 的模块,其中包含一个 greet 函数。在 main.py 文件中,我们导入 my_module 并使用其中的 greet 函数。

包是一种将相关模块组织成层次结构的方式。它们允许您将相关的功能分组,并使代码的管理和分发更加容易。

下面是一个创建简单包的示例:

my_package/
    __init__.py
    math/
        __init__.py
        arithmetic.py
        geometry.py

在这个例子中,我们有一个名为 my_package 的包,其中包含一个名为 math 的子包。包和子包中的 __init__.py 文件允许 Python 将它们识别为包。

您可以导入和使用包中模块中的函数:

from my_package.math.arithmetic import add
from my_package.math.geometry import calculate_area
 
result = add(5, 10)
print(result)  # 输出: 15
 
area = calculate_area(5, 10)
print(area)  # 输出: 50

处理错误和异常

Python 内置了一个异常处理机制,允许您在代码执行过程中出现错误时优雅地处理它们。这是通过使用 try-except 块完成的。

下面是一个处理 ZeroDivisionError 的示例:

def divide(a, b):
    try:
        result = a / b
        return result
    except ZeroDivisionError:
        print("错误: 除数为零")
        return None

print(divide(10, 2)) # 输出: 5.0 print(divide(10, 0)) # 输出: 错误: 被零除


在这个例子中,`divide`函数尝试将第一个参数除以第二个参数。如果发生`ZeroDivisionError`,`except`块将被执行,并打印一条消息。然后函数返回`None`,而不是结果。

你也可以捕获多个异常并以不同的方式处理它们:

```python
def process_input(value):
    try:
        number = int(value)
        result = 100 / number
        return result
    except ValueError:
        print("错误: 无效的输入。请输入一个数字。")
        return None
    except ZeroDivisionError:
        print("错误: 被零除")
        return None

print(process_input("10"))  # 输出: 10.0
print(process_input("hello"))  # 输出: 错误: 无效的输入。请输入一个数字。
print(process_input("0"))  # 输出: 错误: 被零除

在这个例子中,process_input函数首先尝试将输入转换为整数。如果发生ValueError(例如,如果输入不是有效的数字),函数会处理它并返回None。如果发生ZeroDivisionError,函数也会处理它并返回None

结论

在这个Python教程中,我们涵盖了广泛的主题,包括函数、作用域和命名空间、递归函数、模块和包以及错误处理。这些概念是编写有效和可维护的Python代码的基础。

记住,提高Python技能的最佳方式是实践、实验和继续学习。探索Python库和框架的广阔生态系统,并不要犹豫寻求资源、教程和社区来帮助你扩展你的知识。

祝你编码愉快!

MoeNagy Dev.