“`python
Pandas Groupby 与其他函数的结合应用:数据分析的强大武器
Pandas Groupby 是一个强大的数据分析工具,它允许你将数据集按照一个或多个列进行分组,然后对每个分组应用聚合、转换或过滤操作。 然而,Groupby 的真正威力在于它与其他 Pandas 函数以及自定义函数的结合应用。 通过巧妙地结合这些工具,你可以执行复杂的数据分析,提取有价值的见解,并构建高效的数据处理流程。 本文将深入探讨 Pandas Groupby 与各种函数的结合应用,并通过实例说明其强大的功能和灵活性。
1. Groupby 基础回顾
首先,我们快速回顾一下 Groupby 的基本概念。 Groupby 操作主要分为三个阶段:
- Split (拆分): 将 DataFrame 按照指定的列(或多个列)的值进行分组。
- Apply (应用): 对每个分组应用一个函数。 这个函数可以是一个聚合函数(例如
sum
,mean
,count
),一个转换函数(例如transform
,apply
),或一个过滤函数(例如filter
)。 - Combine (组合): 将每个分组的结果组合成一个新的 DataFrame 或 Series。
简单的 Groupby 示例:
“`python
import pandas as pd
创建一个示例 DataFrame
data = {‘Team’: [‘A’, ‘A’, ‘B’, ‘B’, ‘C’, ‘C’],
‘Player’: [‘P1’, ‘P2’, ‘P3’, ‘P4’, ‘P5’, ‘P6’],
‘Points’: [10, 15, 8, 12, 18, 20],
‘Assists’: [5, 7, 3, 6, 9, 10]}
df = pd.DataFrame(data)
按照 ‘Team’ 列进行分组,并计算每个团队的总得分
team_points = df.groupby(‘Team’)[‘Points’].sum()
print(team_points)
按照 ‘Team’ 列进行分组,并计算每个团队的平均助攻数
team_assists = df.groupby(‘Team’)[‘Assists’].mean()
print(team_assists)
“`
2. Groupby 与聚合函数
聚合函数是最常见的 Groupby 应用之一。 Pandas 提供了许多内置的聚合函数,例如:
sum()
: 计算总和mean()
: 计算平均值median()
: 计算中位数min()
: 计算最小值max()
: 计算最大值count()
: 计算非缺失值的数量size()
: 计算每个分组的大小(包括缺失值)std()
: 计算标准差var()
: 计算方差
你可以使用 agg()
方法将多个聚合函数同时应用于一个 Groupby 对象。
“`python
按照 ‘Team’ 列进行分组,并计算每个团队的总得分、平均得分和最大得分
team_stats = df.groupby(‘Team’)[‘Points’].agg([‘sum’, ‘mean’, ‘max’])
print(team_stats)
使用字典自定义聚合函数的名称
team_stats = df.groupby(‘Team’)[‘Points’].agg(
TotalPoints=’sum’,
AveragePoints=’mean’,
MaxPoints=’max’
)
print(team_stats)
对不同的列应用不同的聚合函数
team_stats = df.groupby(‘Team’).agg(
TotalPoints=(‘Points’, ‘sum’),
AverageAssists=(‘Assists’, ‘mean’)
)
print(team_stats)
“`
3. Groupby 与转换函数
转换函数用于对每个分组的每个元素进行转换,并返回与原始 DataFrame 具有相同索引的 DataFrame。 常见的转换函数包括:
transform()
: 将一个函数应用于每个分组的每个元素,并返回与原始 DataFrame 具有相同索引的 DataFrame。apply()
: 更通用的函数,可以应用于每个分组,返回一个 Series、DataFrame 或标量。fillna()
: 用指定的值填充缺失值。
3.1. 使用 transform()
进行标准化
transform()
函数非常适合用于对每个分组进行标准化或归一化。 例如,你可以计算每个团队内每个球员的得分占该团队总得分的比例。
“`python
计算每个团队的总得分
df[‘TeamTotalPoints’] = df.groupby(‘Team’)[‘Points’].transform(‘sum’)
计算每个球员的得分占该团队总得分的比例
df[‘PointsPercentage’] = df[‘Points’] / df[‘TeamTotalPoints’]
print(df)
“`
3.2. 使用 transform()
进行排名
transform()
还可以用于在每个分组内进行排名。
“`python
计算每个团队内球员的得分排名
df[‘Rank’] = df.groupby(‘Team’)[‘Points’].rank(method=’dense’, ascending=False).transform(‘first’)
print(df)
“`
3.3. 使用 apply()
进行自定义转换
apply()
函数提供了更大的灵活性,允许你应用更复杂的自定义转换逻辑。
“`python
定义一个函数,计算每个团队内得分高于平均水平的球员数量
def count_above_average(group):
return (group[‘Points’] > group[‘Points’].mean()).sum()
使用 apply() 函数计算每个团队内得分高于平均水平的球员数量
team_above_average = df.groupby(‘Team’).apply(count_above_average)
print(team_above_average)
定义一个函数,返回每个分组的前N行
def top_n(group, column, n=2):
return group.sort_values(by=column, ascending=False).head(n)
使用 apply() 函数获取每个团队得分最高的前两名球员
top_players = df.groupby(‘Team’).apply(top_n, column=’Points’, n=2)
print(top_players)
“`
4. Groupby 与过滤函数
过滤函数用于根据分组的属性筛选 Groupby 对象。 常用的过滤函数是 filter()
。
“`python
定义一个函数,判断一个团队的总得分是否大于30
def filter_teams(group):
return group[‘Points’].sum() > 30
使用 filter() 函数筛选出总得分大于30的团队
filtered_df = df.groupby(‘Team’).filter(filter_teams)
print(filtered_df)
另一个例子:筛选出至少有两名球员的团队
def filter_teams_by_size(group):
return len(group) >= 2
filtered_df = df.groupby(‘Team’).filter(filter_teams_by_size)
print(filtered_df)
“`
5. Groupby 与 rolling()
函数
rolling()
函数用于计算滑动窗口统计量。 它可以与 Groupby 结合使用,以计算每个分组内的滑动窗口统计量。
“`python
创建一个包含时间序列数据的 DataFrame
data = {‘Date’: pd.to_datetime([‘2023-01-01’, ‘2023-01-02’, ‘2023-01-03’, ‘2023-01-04’, ‘2023-01-05’,
‘2023-01-06’, ‘2023-01-07’, ‘2023-01-08’, ‘2023-01-09’, ‘2023-01-10’]),
‘Category’: [‘A’, ‘A’, ‘A’, ‘A’, ‘A’, ‘B’, ‘B’, ‘B’, ‘B’, ‘B’],
‘Value’: [10, 12, 15, 13, 16, 8, 10, 11, 9, 12]}
df = pd.DataFrame(data)
按照 ‘Category’ 列进行分组,并计算每个类别的3日滚动平均值
df[‘RollingMean’] = df.groupby(‘Category’)[‘Value’].rolling(window=3).mean().reset_index(drop=True)
print(df)
“`
6. Groupby 与 resample()
函数
resample()
函数用于对时间序列数据进行重采样。 它可以与 Groupby 结合使用,以对每个分组的时间序列数据进行重采样。
“`python
按照 ‘Category’ 列进行分组,并对每个类别的数据进行日度重采样,计算每日的总值
resampled_df = df.groupby(‘Category’).resample(‘D’, on=’Date’)[‘Value’].sum()
print(resampled_df)
“`
7. Groupby 与 merge()
函数
merge()
函数用于将两个 DataFrame 按照指定的列进行合并。 它可以与 Groupby 结合使用,以将 Groupby 的结果与其他 DataFrame 合并。
“`python
创建一个包含团队信息的 DataFrame
team_info = pd.DataFrame({‘Team’: [‘A’, ‘B’, ‘C’],
‘Region’: [‘North’, ‘South’, ‘East’]})
按照 ‘Team’ 列进行分组,并计算每个团队的总得分
team_points = df.groupby(‘Team’)[‘Points’].sum().reset_index()
将团队得分信息与团队信息合并
merged_df = pd.merge(team_points, team_info, on=’Team’)
print(merged_df)
“`
8. Groupby 与自定义函数
Groupby 的强大之处在于你可以使用自定义函数来执行非常特定的数据分析任务。
“`python
定义一个函数,计算每个分组的四分位数极差 (IQR)
def iqr(group):
return group.quantile(0.75) – group.quantile(0.25)
使用 apply() 函数计算每个团队的得分 IQR
team_iqr = df.groupby(‘Team’)[‘Points’].apply(iqr)
print(team_iqr)
定义一个函数,计算每个分组中大于某个阈值的元素的数量
def count_above_threshold(group, threshold):
return (group > threshold).sum()
使用 apply() 函数计算每个团队中得分大于15的球员数量
team_above_15 = df.groupby(‘Team’)[‘Points’].apply(count_above_threshold, threshold=15)
print(team_above_15)
“`
9. Groupby 的性能优化
当处理大型数据集时,Groupby 操作可能会比较耗时。 以下是一些优化 Groupby 性能的技巧:
- 避免不必要的类型转换: 确保用于分组的列的数据类型是正确的。
- 使用
categorical
数据类型: 如果分组的列是分类数据,则使用categorical
数据类型可以提高性能。 - 使用
numba
进行加速: 对于自定义的聚合或转换函数,可以使用numba
等库进行加速。 - 并行处理: 可以使用
dask
等库进行并行处理,以加速 Groupby 操作。
10. 总结
Pandas Groupby 是一个极其灵活和强大的数据分析工具。 通过与各种 Pandas 函数(例如 agg
, transform
, filter
, rolling
, resample
, merge
)以及自定义函数的结合应用,你可以执行复杂的数据分析,提取有价值的见解,并构建高效的数据处理流程。 理解和掌握 Groupby 的各种用法是成为优秀数据分析师的关键一步。 本文通过详细的示例展示了 Groupby 与各种函数的结合应用,希望能帮助读者更好地理解和使用 Groupby。 实践是最好的老师,建议读者在自己的数据分析项目中尝试使用 Groupby,并探索其更多可能性。