Python pandas 自定义函数与数据处理实战指南
本文详解 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 高级用法及数据分析实战的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









