Python pandas 自定义函数与数据处理实战指南

小岛来信
小岛来信
发布时间:2026-10-12 | 2人浏览过
原创

本文详解 Python pandas 中自定义函数的应用,包括 apply、applymap 及 lambda 表达式。涵盖数据排序、多层索引重构、多表连接(内/外/左右连接)、数据合并及分组聚合(groupby、agg、transform)等核心操作,提供完整代码示例与逻辑解析。

自定义函数的应用

在 pandas 中,将自定义函数应用于 Series 或 DataFrame 是数据清洗与特征工程的常见需求。主要涉及 apply、applymap 以及匿名函数(lambda)的使用。

Series 与 DataFrame 的 apply 方法

apply 函数允许将自定义逻辑作用于 Series 的行或 DataFrame 的行/列。以下示例展示了如何定义函数并作用于数据:

import numpy as np
import pandas as pd

# 创建示例数据
ser1 = pd.Series(np.random.randint(-10, 10, 5), index=list('abcde'))
df1 = pd.DataFrame(np.random.randint(-10, 10, (4, 5)), index=list('ACBD'), columns=list('abcde'))

# 定义自定义函数:计算最大值与最小值的差、绝对值及平方
def func(x):
    num = np.max(x) - np.min(x)
    a = abs(x)
    b = x ** 2
    return b  # 返回平方值

# 对 Series 应用函数
print(ser1.apply(func))

# 对 DataFrame 按行(axis=1)应用函数
def func1(x):
    a = abs(x)
    b = x ** 2
    return b

print(df1.apply(func1, axis=1))

匿名函数与 applymap

对于简单的逻辑,使用 lambda 表达式更为简洁。此外,applymap 专门用于对 DataFrame 中的每个元素执行操作,无需指定 axis 参数:

# 使用 lambda 对 DataFrame 按行操作
print(df1.apply(lambda x: x ** 2, axis=1))
print(df1.apply(lambda x: np.max(x) - np.min(x), axis=1))

# applymap 作用于每个元素
print(df1.applymap(lambda x: x ** 2))
print(df1.applymap(lambda x: abs(x)))

数据排序操作

pandas 提供了按索引或按值进行排序的方法,支持升序与降序控制。

import numpy as np
import pandas as pd

ser1 = pd.Series(np.random.randint(-10, 10, 10), index=list('acbdfeghji'))
df1 = pd.DataFrame(np.random.randint(-10, 10, (4, 5)), index=list('ADBC'), columns=list('abcde'))

# Series 排序
print(ser1.sort_values())  # 默认升序
print(ser1.sort_values(ascending=False))  # 降序

# DataFrame 排序:按列值排序
print(df1.sort_values(by='a'))  # 按列 'a' 升序
print(df1.sort_values(by='a', ascending=False))  # 按列 'a' 降序

# DataFrame 排序:按行索引或列索引排序
print(df1.sort_index(axis=1))  # 按列名升序
print(df1.sort_index(ascending=False, axis=1))  # 按列名降序

数据重构与多层索引

处理多层索引(MultiIndex)数据时,取值、交换层级以及对象转换是关键操作。

import numpy as np
import pandas as pd

# 创建多层索引 Series
ser1 = pd.Series(np.random.randint(-10, 10, 10), index=[list('aabbccddee'), [1, 2, 1, 2, 1, 2, 1, 2, 1, 2]])

# 多层索引取值
print(ser1['a'])  # 获取单个外层索引
print(ser1['a':'e'])  # 获取多个外层索引切片
print(ser1[:, 1])  # 获取内层索引为 1 的数据
print(ser1['a', 1])  # 指定外层和内层索引取值

# 交换分层与转换
print(ser1.swaplevel())  # 交换内外层索引
print(ser1.unstack())  # Series 转 DataFrame(外层为行,内层为列)

# DataFrame 转换
print(df1.stack())  # DataFrame 转 Series(列索引变为内层索引)
print(df1.to_dict())  # DataFrame 转字典
print(df1.to_csv())  # 输出 CSV 格式字符串

数据连接操作

使用 pd.merge 进行多表连接,支持内连接(inner)、外连接(outer)、左连接(left)和右连接(right)。

import numpy as np
import pandas as pd

df1 = pd.DataFrame({'key1': list('abcdefgh'), 'data1': np.random.randint(-5, 10, 8)})
df2 = pd.DataFrame({'key2': list('defgh'), 'data2': np.random.randint(-5, 10, 5)})

# 内连接:返回键的交集
print(pd.merge(df1, df2, left_on='key1', right_on='key2'))

# 外连接:返回键的并集
print(pd.merge(df1, df2, how='outer', left_on='key1', right_on='key2'))

# 左连接:保留左表所有数据
print(pd.merge(df1, df2, how='left', left_on='key1', right_on='key2'))

# 右连接:保留右表所有数据
print(pd.merge(df1, df2, how='right', left_on='key1', right_on='key2'))

# 通过行索引连接
print(pd.merge(df1, df2, left_on='data1', right_index=True))
print(pd.merge(df1, df2, left_index=True, right_index=True))  # 按行索引匹配
print(pd.merge(df1, df2, how='left', left_index=True, right_index=True))

数据合并(Concat)

pd.concat 用于沿特定轴合并 Series 或 DataFrame。默认沿行(axis=0)合并,可通过设置 axis=1 沿列合并。

import numpy as np
import pandas as pd

# Series 合并
ser1 = pd.Series(np.random.randint(10, 20, 3))
ser2 = pd.Series(np.random.randint(10, 20, 5))
ser3 = pd.Series(np.random.randint(10, 20, 7))

print(pd.concat([ser1, ser2, ser3]))  # 默认列合并(纵向)
print(pd.concat([ser1, ser2, ser3], axis=1))  # 行合并(横向),不足处填 NaN
print(pd.concat([ser1, ser2, ser3], axis=1, join='outer'))  # 并集合并

# DataFrame 合并
df1 = pd.DataFrame({'key1': list('abcdefgh'), 'data1': np.random.randint(-5, 10, 8)})
df2 = pd.DataFrame({'key2': list('abcde'), 'data2': np.random.randint(-5, 10, 5)})

print(pd.concat((df1, df2)))  # 默认纵向合并
print(pd.concat((df1, df2), axis=1))  # 横向合并
print(pd.concat((df1, df2), axis=1, join='inner'))  # 交集合并

分组聚合(Groupby)

groupby 是数据分析的核心操作,支持按指定列分组后进行聚合计算。可以使用内置函数、自定义函数或 lambda 表达式。

import pandas as pd
import numpy as np

df1 = pd.DataFrame({
    'key1': list('abcdefgh'),
    'data1': np.random.randint(-5, 10, 8),
    'key2': list('11223344'),
    'data2': np.random.randint(-5, 10, 8)
})

# 创建分组对象
group_obj = df1.groupby(by='key2')

# 使用内置聚合函数
print(group_obj.sum())  # 求和
print(group_obj.mean())  # 均值
print(group_obj.size())  # 元素个数
print(group_obj.count())  # 非空值计数

# 使用 agg 进行复杂聚合
print(group_obj.agg('max'))  # 单个内置函数
print(group_obj.agg(['max', 'min', 'mean']))  # 多个内置函数
print(group_obj.agg([('最大值', 'max'), ('最小值', 'min'), ('均值', 'mean')]))  # 带中文别名

# 自定义函数聚合
def print1(x):
    return x.max() - x.min()

print(group_obj.agg([('差值', print1)]))

# 不同列应用不同函数
print(group_obj.agg({
    'data1': ['max'],
    'data2': [('最小值', 'min')]
}))

分组后合并数据

在分组聚合后,常需将结果与原数据合并。使用 transform 可保持原数据结构,便于后续合并。

import pandas as pd
import numpy as np

dict_new = {
    'data1': np.random.randint(5, 15, 8),
    'data2': np.random.randint(5, 15, 8),
    'data3': 4,
    'key1': list('aabbccdd'),
    'key2': ['one', 'two', 'three', 'one', 'two', 'three', 'one', 'two']
}
df1 = pd.DataFrame(dict_new, index=list('ADCBFEGH'))

# 按 key1 分组并求和
groupby_obj = df1.loc[:, ['data1', 'data2']].groupby(df1['key1'])
data = groupby_obj.sum()

# 使用 transform 保持原结构并添加前缀
data1 = groupby_obj.transform('sum').add_prefix('trans_group')

# 按行合并原数据与聚合结果
print(pd.concat([df1, data1], axis=1))

以上就是 Python pandas 自定义函数、排序、连接与分组聚合的详细内容,更多关于 Python 数据处理、pandas 高级用法及数据分析实战的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表