【Pandas】pandas GroupBy Function application SeriesGroupBy.transform

Pandas2.2 GroupBy

Function application

方法描述
SeriesGroupBy.apply(func, *args, **kwargs)用于对每个分组应用指定的函数
DataFrameGroupBy.apply(func, *args[, …])用于对每个分组应用指定的函数
SeriesGroupBy.agg([func, engine, engine_kwargs])用于在滚动窗口上应用聚合函数的方法
DataFrameGroupBy.agg([func, engine, …])用于对分组数据应用一个或多个聚合函数
SeriesGroupBy.aggregate([func, engine, …])用于对分组数据应用聚合函数
DataFrameGroupBy.aggregate([func, engine, …])用于对分组数据应用聚合函数
SeriesGroupBy.transform(func, *args[, …])用于对每个分组应用指定的函数

pandas.SeriesGroupBy.transform()

方法描述

pandas.SeriesGroupBy.transform(func, *args, engine=None, engine_kwargs=None, **kwargs) 是 SeriesGroupBy 对象的一个方法,用于对每个分组应用指定的函数,并返回一个与原始 Series 具有相同索引的 Series。与 apply()agg() 不同,transform() 的关键特点是保持原始数据的形状,它将聚合结果广播回原始数据的每个元素。

参数说明
  • func: function, str, list or dict
    • 要应用于每个分组的函数,可以是字符串(如 ‘mean’, ‘sum’)、函数对象或它们的组合
  • *args: 传递给函数的位置参数
  • [engine]: str, default None
    • 计算引擎,可选 ‘cython’ 或 ‘numba’
    • None 表示使用默认引擎
  • engine_kwargs: dict, default None
    • 传递给计算引擎的额外参数
  • **kwargs: 传递给函数的关键字参数
返回值

返回一个 Series,其索引与原始 Series 相同,每个元素都被替换为对应分组的转换结果。

使用示例
import pandas as pd
import numpy as np

# 示例1: 基本用法 - 标准化数据
print("=== 示例1: 基本用法 - 标准化数据 ===")
data = pd.Series([10, 20, 30, 40, 50, 60], 
                 index=['A', 'A', 'B', 'B', 'C', 'C'])
print("原始数据:")
print(data)
print()

grouped = data.groupby(level=0)
print("对每个分组应用 mean 函数进行标准化:")
result_mean = grouped.transform('mean')
print(result_mean)
print()

print("减去分组均值实现组内标准化:")
result_standardized = data - grouped.transform('mean')
print(result_standardized)
print()

# 示例2: 使用自定义函数
print("=== 示例2: 使用自定义函数 ===")
def custom_transform(series):
    """自定义转换函数:将每个元素转换为占组总和的比例"""
    return series / series.sum()

print("将每个元素转换为占组总和的比例:")
result_custom = grouped.transform(custom_transform)
print(result_custom)
print()

# 示例3: 百分位数排名
print("=== 示例3: 百分位数排名 ===")
values = pd.Series([1, 5, 2, 8, 3, 9, 4, 7], 
                   index=['X', 'X', 'Y', 'Y', 'X', 'X', 'Y', 'Y'])
print("值序列:")
print(values)
print()

grouped_values = values.groupby(level=0)
print("计算每组内的百分位数排名:")
result_percentile = grouped_values.transform(lambda x: x.rank(pct=True))
print(result_percentile)
print()

# 示例4: 填充缺失值
print("=== 示例4: 填充缺失值 ===")
data_with_nan = pd.Series([1, np.nan, 3, np.nan, 5, 6], 
                          index=['A', 'A', 'B', 'B', 'C', 'C'])
print("包含缺失值的数据:")
print(data_with_nan)
print()

grouped_nan = data_with_nan.groupby(level=0)
print("使用每组的均值填充缺失值:")
result_filled = grouped_nan.transform(lambda x: x.fillna(x.mean()))
print(result_filled)
print()

# 示例5: 数据去趋势
print("=== 示例5: 数据去趋势 ===")
time_series = pd.Series([10, 15, 20, 25, 30, 35], 
                        index=['Group1', 'Group1', 'Group1', 'Group2', 'Group2', 'Group2'])
print("时间序列数据:")
print(time_series)
print()

grouped_ts = time_series.groupby(level=0)
print("去除每组线性趋势:")
def detrend(series):
    x = np.arange(len(series))
    slope, intercept = np.polyfit(x, series, 1)
    trend = slope * x + intercept
    return series - trend

result_detrend = grouped_ts.transform(detrend)
print(result_detrend)
print()

# 示例6: 复杂金融数据示例
print("=== 示例6: 复杂金融数据示例 ===")
returns = pd.Series([0.02, -0.01, 0.03, -0.02, 0.04, 0.01, 
                    -0.03, 0.02, 0.01, -0.01, 0.03, 0.02], 
                   index=['Tech', 'Tech', 'Finance', 'Finance', 'Tech', 'Finance',
                          'Tech', 'Finance', 'Tech', 'Finance', 'Tech', 'Finance'])
print("月度收益率数据:")
for i in range(len(returns)):
    print(f"{returns.index[i]}: {returns.iloc[i]:.2%}")
print()

grouped_returns = returns.groupby(level=0)
print("将收益率标准化为每行业的Z分数:")
industry_mean = grouped_returns.transform('mean')
industry_std = grouped_returns.transform('std')
z_scores = (returns - industry_mean) / industry_std
print(z_scores.round(4))
print()

# 示例7: 分组排序
print("=== 示例7: 分组排序 ===")
scores = pd.Series([85, 92, 78, 95, 88, 90], 
                   index=['Class_A', 'Class_A', 'Class_B', 'Class_B', 'Class_A', 'Class_B'])
print("学生分数:")
print(scores)
print()

grouped_scores = scores.groupby(level=0)
print("每班内学生的相对排名:")
relative_rank = grouped_scores.transform(lambda x: x.rank(method='average', ascending=False))
print(relative_rank)
print()

# 示例8: 移动窗口变换
print("=== 示例8: 移动窗口变换 ===")
data_window = pd.Series([1, 2, 3, 4, 5, 6, 7, 8], 
                        index=['Group1', 'Group1', 'Group1', 'Group1', 
                               'Group2', 'Group2', 'Group2', 'Group2'])
print("数据序列:")
print(data_window)
print()

grouped_window = data_window.groupby(level=0)
print("计算每组内的累积和:")
cumsum_result = grouped_window.transform('cumsum')
print(cumsum_result)
print()

# 示例9: 条件变换
print("=== 示例9: 条件变换 ===")
sales = pd.Series([100, 150, 200, 120, 180, 160], 
                  index=['North', 'North', 'South', 'South', 'East', 'East'])
print("销售数据:")
print(sales)
print()

grouped_sales = sales.groupby(level=0)
print("高于组均值的标记为1,否则为0:")
mean_sales = grouped_sales.transform('mean')
above_average = (sales > mean_sales).astype(int)
print(above_average)
print()

# 示例10: 多级索引变换
print("=== 示例10: 多级索引变换 ===")
multi_index = pd.MultiIndex.from_tuples([
    ('A', 1), ('A', 2), ('B', 1), ('B', 2), ('C', 1), ('C', 2)
])
data_multi = pd.Series([10, 20, 30, 40, 50, 60], index=multi_index)
print("多级索引数据:")
print(data_multi)
print()

# 按第一级分组
grouped_level0 = data_multi.groupby(level=0)
print("按第一级索引分组并标准化:")
normalized_result = grouped_level0.transform(lambda x: (x - x.mean()) / x.std())
print(normalized_result)

执行结果:

=== 示例1: 基本用法 - 标准化数据 ===
原始数据:
A    10
A    20
B    30
B    40
C    50
C    60
dtype: int64

对每个分组应用 mean 函数进行标准化:
A    15.0
A    15.0
B    35.0
B    35.0
C    55.0
C    55.0
dtype: float64

减去分组均值实现组内标准化:
A   -5.0
A    5.0
B   -5.0
B    5.0
C   -5.0
C    5.0
dtype: float64

=== 示例2: 使用自定义函数 ===
将每个元素转换为占组总和的比例:
A    0.333333
A    0.666667
B    0.428571
B    0.571429
C    0.454545
C    0.545455
dtype: float64

=== 示例3: 百分位数排名 ===
值序列:
X    1
X    5
Y    2
Y    8
X    3
X    9
Y    4
Y    7
dtype: int64

计算每组内的百分位数排名:
X    0.25
X    0.75
Y    0.25
Y    1.00
X    0.50
X    1.00
Y    0.50
Y    0.75
dtype: float64

=== 示例4: 填充缺失值 ===
包含缺失值的数据:
A     1.0
A     NaN
B     3.0
B     NaN
C     5.0
C     6.0
dtype: float64

使用每组的均值填充缺失值:
A    1.0
A    1.0
B    3.0
B    3.0
C    5.0
C    6.0
dtype: float64

=== 示例5: 数据去趋势 ===
时间序列数据:
Group1    10
Group1    15
Group1    20
Group2    25
Group2    30
Group2    35
dtype: int64

去除每组线性趋势:
Group1   -5.0
Group1    0.0
Group1    5.0
Group2   -5.0
Group2    0.0
Group2    5.0
dtype: float64

=== 示例6: 复杂金融数据示例 ===
月度收益率数据:
Tech: 2.00%
Tech: -1.00%
Finance: 3.00%
Finance: -2.00%
Tech: 4.00%
Finance: 1.00%
Tech: -3.00%
Finance: 2.00%
Tech: 1.00%
Finance: -1.00%
Tech: 3.00%
Finance: 2.00%

将收益率标准化为每行业的Z分数:
Tech      -0.2673
Tech      -1.3363
Finance    0.8909
Finance   -1.3363
Tech       0.2673
Finance   -0.4454
Tech      -1.8704
Finance    0.4454
Tech      -0.8018
Finance   -0.8909
Tech       0.8018
Finance    0.0000
dtype: float64

=== 示例7: 分组排序 ===
学生分数:
Class_A    85
Class_A    92
Class_B    78
Class_B    95
Class_A    88
Class_B    90
dtype: int64

每班内学生的相对排名:
Class_A    3.0
Class_A    1.0
Class_B    3.0
Class_B    1.0
Class_A    2.0
Class_B    2.0
dtype: float64

=== 示例8: 移动窗口变换 ===
数据序列:
Group1    1
Group1    2
Group1    3
Group1    4
Group2    5
Group2    6
Group2    7
Group2    8
dtype: int64

计算每组内的累积和:
Group1     1
Group1     3
Group1     6
Group1    10
Group2     5
Group2    11
Group2    18
Group2    26
dtype: int64

=== 示例9: 条件变换 ===
销售数据:
North    100
North    150
South    200
South    120
East     180
East     160
dtype: int64

高于组均值的标记为1,否则为0:
North    0
North    1
South    1
South    0
East     1
East     0
dtype: int64

=== 示例10: 多级索引变换 ===
多级索引数据:
A  1    10
   2    20
B  1    30
   2    40
C  1    50
   2    60
dtype: int64

按第一级索引分组并标准化:
A  1   -0.707107
   2    0.707107
B  1   -0.707107
   2    0.707107
C  1   -0.707107
   2    0.707107
dtype: float64
关键要点
  1. transform() 方法保持原始数据的形状,返回与输入 Series 索引相同的 Series
  2. apply()agg() 不同,transform() 将聚合结果广播回原始数据的每个元素
  3. 常用于数据标准化、缺失值填充、去趋势等操作
  4. 支持字符串形式的函数名、自定义函数和 lambda 表达式
  5. 在金融数据分析中广泛用于行业中性化、标准化等预处理步骤
  6. 可以实现复杂的条件变换和分组操作
  7. 与原始数据保持严格的对齐关系,便于后续分析
  8. 支持多级索引分组变换
  9. 在数据清洗和特征工程中非常有用
  10. 性能通常优于手动循环实现的等效操作
### `pandas.core.groupby.generic.SeriesGroupBy` 对象介绍 `pandas.core.groupby.generic.SeriesGroupBy` 对象是 Pandas 中用于对 `Series` 进行分组操作的中间对象。当使用 `groupby` 方法对 `Series` 进行分组时,就会得到 `SeriesGroupBy` 对象。该对象本身并不直接包含分组后的数据,而是提供了一种机制,用于对分组后的数据执行各种聚合、转换或过滤操作。 ### 使用方法 以下是一些常见的使用方法: #### 分组并计算统计量 ```python import pandas as pd # 创建一个示例 Series data = {'A': [1, 2, 3, 4, 5, 6], 'B': ['a', 'b', 'a', 'b', 'a', 'b']} df = pd.DataFrame(data) series = df['A'] grouped = series.groupby(df['B']) # 计算每组的平均值 mean_values = grouped.mean() print(mean_values) ``` #### 分组并应用自定义函数 ```python def custom_function(x): return x.max() - x.min() result = grouped.apply(custom_function) print(result) ``` ### 与 `plt.hist` 的关联 `plt.hist` 是 `matplotlib.pyplot` 中的函数,用于绘制直方图。`SeriesGroupBy` 对象可以与 `plt.hist` 结合使用,以可视化分组后的数据分布。 ```python import matplotlib.pyplot as plt # 对每个分组绘制直方图 for group_name, group_data in grouped: plt.hist(group_data, bins=5, alpha=0.7, label=group_name) plt.legend() plt.show() ``` 在上述代码中,通过遍历 `SeriesGroupBy` 对象,获取每个分组的数据,并使用 `plt.hist` 为每个分组绘制直方图,从而直观地展示不同分组的数据分布情况。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

liuweidong0802

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值