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[, …]) | 用于对每个分组应用指定的函数 |
| DataFrameGroupBy.transform(func, *args[, …]) | 用于对每个分组应用指定的函数 |
| SeriesGroupBy.pipe(func, *args, **kwargs) | 用于将分组对象作为参数传递给指定的函数 |
pandas.SeriesGroupBy.pipe()
方法描述
pandas.SeriesGroupBy.pipe(func, *args, **kwargs) 是 SeriesGroupBy 对象的一个方法,用于将分组对象作为参数传递给指定的函数。与 apply()、agg() 和 transform() 不同,pipe() 的主要用途是将整个分组对象传递给一个函数,而不是对每个分组应用函数。这种方法特别适用于链式操作和自定义函数,允许用户在分组操作之后继续进行更复杂的处理。
参数说明
func: callable or tuple of (callable, string)- 要应用的函数,该函数必须接受一个分组对象作为第一个参数
- 可以是一个可调用对象或者一个包含可调用对象和字符串的元组
*args: 传递给函数的位置参数**kwargs: 传递给函数的关键字参数
返回值
返回值取决于传入的 func 函数的返回值,可以是任何类型的对象。
使用示例
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()
def custom_analysis(grouped_obj):
"""自定义分析函数,接收分组对象并进行分析"""
result = {}
for name, group in grouped_obj:
result[name] = {
'sum': group.sum(),
'mean': group.mean(),
'count': len(group)
}
return pd.DataFrame(result).T
grouped = data.groupby(level=0)
print("使用pipe将分组对象传递给自定义分析函数:")
result = grouped.pipe(custom_analysis)
print(result)
print()
# 示例2: 链式操作中的pipe
print("=== 示例2: 链式操作中的pipe ===")
def filter_and_analyze(grouped_obj, min_count=2):
"""过滤分组并分析"""
# 过滤掉计数小于min_count的分组
filtered_groups = []
for name, group in grouped_obj:
if len(group) >= min_count:
filtered_groups.append((name, group))
# 对过滤后的分组进行分析
results = {}
for name, group in filtered_groups:
results[name] = group.sum()
return pd.Series(results)
print("使用pipe进行过滤和分析:")
result_filtered = grouped.pipe(filter_and_analyze, min_count=2)
print(result_filtered)
print()
# 示例3: 复杂统计分析
print("=== 示例3: 复杂统计分析 ===")
def advanced_statistics(grouped_obj):
"""高级统计分析函数"""
stats_list = []
for name, group in grouped_obj:
stats = {
'group': name,
'count': len(group),
'sum': group.sum(),
'mean': group.mean(),
'std': group.std() if len(group) > 1 else 0,
'min': group.min(),
'max': group.max(),
'median': group.median()
}
stats_list.append(stats)
return pd.DataFrame(stats_list)
print("使用pipe进行高级统计分析:")
advanced_result = grouped.pipe(advanced_statistics)
print(advanced_result)
print()
# 示例4: 条件分组分析
print("=== 示例4: 条件分组分析 ===")
def conditional_analysis(grouped_obj, condition_func):
"""根据条件函数进行分组分析"""
qualified_groups = []
for name, group in grouped_obj:
if condition_func(group):
qualified_groups.append(name)
return qualified_groups
def sum_greater_than(group, threshold=30):
"""判断分组和是否大于阈值"""
return group.sum() > threshold
print("使用pipe进行条件分组分析:")
qualified = grouped.pipe(conditional_analysis, sum_greater_than)
print(f"和大于30的分组: {qualified}")
print()
# 示例5: 多步骤处理管道
print("=== 示例5: 多步骤处理管道 ===")
def step1_normalize(grouped_obj):
"""第一步:标准化"""
return grouped_obj.transform(lambda x: (x - x.mean()) / x.std() if x.std() != 0 else 0)
def step2_analyze(normalized_data, grouped_obj):
"""第二步:分析标准化后的数据"""
analysis_results = {}
for name, group in grouped_obj:
analysis_results[name] = {
'normalized_mean': normalized_data.loc[group.index].mean(),
'normalized_std': normalized_data.loc[group.index].std()
}
return pd.DataFrame(analysis_results).T
def processing_pipeline(grouped_obj):
"""处理管道"""
# 步骤1:标准化
normalized = step1_normalize(grouped_obj)
# 步骤2:分析
analysis = step2_analyze(normalized, grouped_obj)
return analysis
print("使用pipe执行多步骤处理管道:")
pipeline_result = grouped.pipe(processing_pipeline)
print(pipeline_result)
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'])
def financial_metrics(grouped_obj):
"""计算金融指标"""
metrics = []
for name, group in grouped_obj:
sharpe_ratio = group.mean() / group.std() if group.std() != 0 else 0
max_drawdown = group.min()
positive_months = (group > 0).sum()
metrics.append({
'sector': name,
'sharpe_ratio': sharpe_ratio,
'avg_return': group.mean(),
'volatility': group.std(),
'max_drawdown': max_drawdown,
'positive_months': positive_months,
'total_months': len(group)
})
return pd.DataFrame(metrics)
grouped_returns = returns.groupby(level=0)
print("月度收益率数据:")
for i in range(len(returns)):
print(f"{returns.index[i]}: {returns.iloc[i]:.2%}")
print()
print("使用pipe计算金融指标:")
financial_result = grouped_returns.pipe(financial_metrics)
print(financial_result.round(4))
print()
# 示例7: 数据质量检查
print("=== 示例7: 数据质量检查 ===")
data_with_issues = pd.Series([1, 2, np.nan, 4, 5, np.nan, 7, 8],
index=['A', 'A', 'A', 'B', 'B', 'B', 'C', 'C'])
def data_quality_check(grouped_obj):
"""数据质量检查函数"""
quality_report = []
for name, group in grouped_obj:
quality_report.append({
'group': name,
'total_count': len(group),
'missing_count': group.isna().sum(),
'missing_percentage': group.isna().sum() / len(group) * 100,
'valid_data_percentage': (1 - group.isna().sum() / len(group)) * 100
})
return pd.DataFrame(quality_report)
grouped_quality = data_with_issues.groupby(level=0)
print("包含缺失值的数据:")
print(data_with_issues)
print()
print("使用pipe进行数据质量检查:")
quality_result = grouped_quality.pipe(data_quality_check)
print(quality_result)
print()
# 示例8: 自定义聚合函数
print("=== 示例8: 自定义聚合函数 ===")
sales_data = pd.Series([100, 150, 200, 120, 180, 160],
index=['North', 'North', 'South', 'South', 'East', 'East'])
def custom_aggregation(grouped_obj, agg_func_name):
"""自定义聚合函数"""
if agg_func_name == 'cv': # 变异系数
result = {}
for name, group in grouped_obj:
result[name] = group.std() / group.mean() if group.mean() != 0 else 0
return pd.Series(result)
elif agg_func_name == 'range': # 范围
result = {}
for name, group in grouped_obj:
result[name] = group.max() - group.min()
return pd.Series(result)
grouped_sales = sales_data.groupby(level=0)
print("销售数据:")
print(sales_data)
print()
print("使用pipe计算变异系数:")
cv_result = grouped_sales.pipe(custom_aggregation, 'cv')
print(cv_result.round(4))
print()
print("使用pipe计算范围:")
range_result = grouped_sales.pipe(custom_aggregation, 'range')
print(range_result)
print()
# 示例9: 与其它方法结合使用
print("=== 示例9: 与其它方法结合使用 ===")
def combined_analysis(grouped_obj):
"""组合分析函数"""
# 获取基本统计信息
basic_stats = grouped_obj.agg(['count', 'mean', 'std'])
# 获取分组对象并进行自定义分析
custom_results = {}
for name, group in grouped_obj:
custom_results[name] = {
'sum': group.sum(),
'median': group.median(),
'q75': group.quantile(0.75)
}
custom_df = pd.DataFrame(custom_results).T
# 合并结果
combined = pd.concat([basic_stats.T, custom_df], axis=1)
return combined
print("使用pipe进行组合分析:")
combined_result = grouped.pipe(combined_analysis)
print(combined_result)
print()
# 示例10: 错误处理和健壮性
print("=== 示例10: 错误处理和健壮性 ===")
def robust_analysis(grouped_obj):
"""健壮的分析函数,包含错误处理"""
results = {}
for name, group in grouped_obj:
try:
# 尝试计算各种统计量
results[name] = {
'count': len(group),
'sum': group.sum(),
'mean': group.mean(),
'std': group.std() if len(group) > 1 else np.nan,
'cv': group.std() / group.mean() if group.mean() != 0 else np.nan
}
except Exception as e:
# 如果出现错误,记录错误信息
results[name] = {
'error': str(e),
'count': len(group)
}
return pd.DataFrame(results).T
# 创建一些可能导致计算错误的数据
problematic_data = pd.Series([1, 2, 3, 0, 0, -1],
index=['A', 'A', 'B', 'B', 'C', 'C'])
grouped_problematic = problematic_data.groupby(level=0)
print("可能引起计算问题的数据:")
print(problematic_data)
print()
print("使用pipe进行健壮性分析:")
robust_result = grouped_problematic.pipe(robust_analysis)
print(robust_result)
执行结果:
=== 示例1: 基本用法 - 传递分组对象给自定义函数 ===
原始数据:
A 10
A 20
B 30
B 40
C 50
C 60
dtype: int64
使用pipe将分组对象传递给自定义分析函数:
sum mean count
A 30 15.0 2
B 70 35.0 2
C 110 55.0 2
=== 示例2: 链式操作中的pipe ===
使用pipe进行过滤和分析:
A 30
B 70
C 110
dtype: int64
=== 示例3: 复杂统计分析 ===
使用pipe进行高级统计分析:
count sum mean std min max median
0 2 30 15.0 7.071068 10 20 15.0
1 2 70 35.0 7.071068 30 40 35.0
2 2 110 55.0 7.071068 50 60 55.0
=== 示例4: 条件分组分析 ===
使用pipe进行条件分组分析:
和大于30的分组: ['B', 'C']
=== 示例5: 多步骤处理管道 ===
使用pipe执行多步骤处理管道:
normalized_mean normalized_std
A 0.0 1.0
B 0.0 1.0
C 0.0 1.0
=== 示例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%
使用pipe计算金融指标:
sector sharpe_ratio avg_return volatility max_drawdown positive_months total_months
0 Finance 0.5774 0.0083 0.0141 -0.0200 4.0 6.0
1 Tech 1.1547 0.0083 0.0072 -0.0300 4.0 6.0
=== 示例7: 数据质量检查 ===
包含缺失值的数据:
A 1.0
A 2.0
A NaN
B 4.0
B NaN
B 7.0
C 8.0
dtype: float64
使用pipe进行数据质量检查:
group total_count missing_count missing_percentage valid_data_percentage
0 A 3.0 1.0 33.333333 66.666667
1 B 3.0 1.0 33.333333 66.666667
2 C 2.0 0.0 0.000000 100.000000
=== 示例8: 自定义聚合函数 ===
销售数据:
North 100
North 150
South 200
South 120
East 180
East 160
dtype: int64
使用pipe计算变异系数:
North 0.2041
South 0.2530
East 0.0556
dtype: float64
使用pipe计算范围:
North 50
South 80
East 20
dtype: int64
=== 示例9: 与其它方法结合使用 ===
使用pipe进行组合分析:
count mean std sum median q75
A 2.0 15.0 7.071068 30 15.0 17.50
B 2.0 35.0 7.071068 70 35.0 37.50
C 2.0 55.0 7.071068 110 55.0 57.50
=== 示例10: 错误处理和健壮性 ===
可能引起计算问题的数据:
A 1
A 2
B 3
B 0
C 0
C -1
dtype: int64
使用pipe进行健壮性分析:
count sum mean std cv
A 2.0 3.0 1.50 0.5 0.333333
B 2.0 3.0 1.50 2.0 1.333333
C 2.0 -1.0 -0.50 0.5 -1.000000
关键要点
SeriesGroupBy.pipe()方法将整个分组对象传递给指定函数,而不是对每个分组分别应用函数- 与
apply()、agg()和transform()不同,pipe()主要用于链式操作和自定义处理流程 - 适用于需要访问整个分组对象结构的复杂分析任务
- 可以在函数中自由使用分组对象的所有方法和属性
- 支持传递额外的位置参数和关键字参数给目标函数
- 在构建复杂的数据处理管道时非常有用
- 可以与其他分组方法(如
agg()、apply()、transform())结合使用 - 适合进行数据质量检查、条件分析等需要全局视角的操作
- 提供了良好的错误处理和异常管理机制
- 在金融数据分析、科学研究和复杂业务逻辑处理中应用广泛
988

被折叠的 条评论
为什么被折叠?



