Pandas Groupby 函数:用法、参数与常见问题 – wiki基地

Pandas Groupby 函数:用法、参数与常见问题

Pandas 的 groupby() 函数是数据分析中一个极其强大且常用的工具。它允许你根据一个或多个列的值将 DataFrame 分组,然后对这些分组执行各种聚合、转换和过滤操作。掌握 groupby() 函数对于进行有效的探索性数据分析、特征工程和构建机器学习模型至关重要。 本文将深入探讨 Pandas groupby() 函数的用法、参数、常见的用例,并解答一些常见的疑问。

1. groupby() 函数的基本原理

groupby() 函数遵循一个”split-apply-combine”策略:

  • Split (拆分): DataFrame 按照指定的列或函数进行分组,形成多个子 DataFrame。
  • Apply (应用): 将一个函数(例如聚合函数、转换函数或过滤函数)应用于每个子 DataFrame。
  • Combine (合并): 将应用函数后的结果合并成一个新的 DataFrame。

2. groupby() 函数的基本语法

groupby() 函数的基本语法如下:

python
DataFrame.groupby(by=None, axis=0, level=None, as_index=True, sort=True, group_keys=True, observed=False, dropna=True)

让我们详细了解每个参数:

  • by (必须) 指定用于分组的列名、列表、Series 或函数。这是 groupby() 函数最重要的参数。
    • 可以是单个列名 (字符串)。
    • 可以是列名列表,用于多列分组。
    • 可以是 Series,其索引与 DataFrame 的索引匹配。
    • 可以是一个函数,该函数应用于 DataFrame 的索引或列,并返回分组键。
  • axis 指定分组的轴。 0 表示按行分组(默认), 1 表示按列分组。 在大多数情况下,我们都是按行分组。
  • level 如果 DataFrame 具有 MultiIndex,则指定用于分组的级别名称或级别索引。
  • as_index 一个布尔值,指示是否将分组键作为结果 DataFrame 的索引。 默认为 True。如果设置为 False,分组键将成为普通的列。
  • sort 一个布尔值,指示是否对分组键进行排序。默认为 True。 排序有助于提高可读性。
  • group_keys 一个布尔值,指示是否将分组键添加到结果 DataFrame 的索引中。默认为 True。 当 as_index=False 时,此参数非常有用。
  • observed 一个布尔值,仅在分组的列是 Categorical 类型时相关。 如果为 True,则仅对实际出现在数据中的类别进行分组。 如果为 False (默认),则将包括所有类别,即使它们在数据中不存在。
  • dropna 一个布尔值,指示是否在分组时删除包含 NaN 值的行。 默认为 True

3. groupby() 函数的用法示例

假设我们有一个包含销售数据的 DataFrame:

“`python
import pandas as pd

data = {‘Region’: [‘East’, ‘East’, ‘West’, ‘West’, ‘North’, ‘North’, ‘South’, ‘South’],
‘Product’: [‘A’, ‘B’, ‘A’, ‘C’, ‘B’, ‘A’, ‘C’, ‘B’],
‘Sales’: [100, 150, 120, 200, 180, 110, 220, 190]}

df = pd.DataFrame(data)

print(df)
“`

输出:

Region Product Sales
0 East A 100
1 East B 150
2 West A 120
3 West C 200
4 North B 180
5 North A 110
6 South C 220
7 South B 190

3.1 单列分组并计算总销售额

“`python
grouped_sales = df.groupby(‘Region’)[‘Sales’].sum()

print(grouped_sales)
“`

输出:

Region
East 250
North 290
South 410
West 320
Name: Sales, dtype: int64

在这个例子中,我们首先使用 groupby('Region') 将 DataFrame 按照 ‘Region’ 列进行分组。 然后,我们选择 ‘Sales’ 列,并使用 sum() 函数计算每个区域的总销售额。 结果是一个 Series,其中 ‘Region’ 作为索引,总销售额作为值。

3.2 多列分组并计算平均销售额

“`python
grouped_sales = df.groupby([‘Region’, ‘Product’])[‘Sales’].mean()

print(grouped_sales)
“`

输出:

Region Product
East A 100.0
B 150.0
North A 110.0
B 180.0
South B 190.0
C 220.0
West A 120.0
C 200.0
Name: Sales, dtype: float64

这里,我们使用 groupby(['Region', 'Product']) 按照 ‘Region’ 和 ‘Product’ 两列进行分组。 然后,计算每个区域和产品的平均销售额。 结果是一个带有 MultiIndex 的 Series。

3.3 使用 agg() 函数进行多种聚合

agg() 函数允许您同时对分组后的数据应用多个聚合函数。

“`python
grouped_sales = df.groupby(‘Region’)[‘Sales’].agg([‘sum’, ‘mean’, ‘max’])

print(grouped_sales)
“`

输出:

sum mean max
Region
East 250 125.0 150
North 290 145.0 180
South 410 205.0 220
West 320 160.0 200

在这个例子中,我们计算了每个区域的总销售额 (sum)、平均销售额 (mean) 和最高销售额 (max)。 agg() 函数接受一个函数列表作为参数。

3.4 使用 agg() 函数进行自定义聚合

agg() 函数还可以接受自定义函数。

“`python
def range_sales(x):
return x.max() – x.min()

grouped_sales = df.groupby(‘Region’)[‘Sales’].agg([‘sum’, ‘mean’, range_sales])

print(grouped_sales)
“`

输出:

sum mean range_sales
Region
East 250 125.0 50
North 290 145.0 70
South 410 205.0 30
West 320 160.0 80

这里,我们定义了一个名为 range_sales 的自定义函数,用于计算销售额的范围(最大值减去最小值)。 然后,我们使用 agg() 函数将其应用于分组后的数据。

3.5 使用 transform() 函数进行转换

transform() 函数允许您对分组后的数据进行转换,并返回一个与原始 DataFrame 具有相同索引和形状的 DataFrame。 这对于计算标准化值、排名或填充缺失值非常有用。

“`python
df[‘Sales_Mean_Region’] = df.groupby(‘Region’)[‘Sales’].transform(‘mean’)

print(df)
“`

输出:

Region Product Sales Sales_Mean_Region
0 East A 100 125.0
1 East B 150 125.0
2 West A 120 160.0
3 West C 200 160.0
4 North B 180 145.0
5 North A 110 145.0
6 South C 220 205.0
7 South B 190 205.0

在这个例子中,我们计算了每个区域的平均销售额,并将结果添加为 DataFrame 的新列 ‘Sales_Mean_Region’。 transform('mean') 将每个区域的平均销售额广播到该区域的每一行。

3.6 使用 filter() 函数进行过滤

filter() 函数允许您根据分组后的数据进行过滤,仅保留满足特定条件的组。

“`python
grouped_sales = df.groupby(‘Region’).filter(lambda x: x[‘Sales’].sum() > 300)

print(grouped_sales)
“`

输出:

Region Product Sales
2 West A 120
3 West C 200
4 North B 180
5 North A 110
6 South C 220
7 South B 190

在这个例子中,我们过滤了总销售额大于 300 的区域。 filter() 函数接受一个函数作为参数,该函数应用于每个分组的 DataFrame,并返回一个布尔值。 只有返回 True 的组才会被保留。

3.7 使用 apply() 函数进行更复杂的操作

apply() 函数提供了一种更灵活的方式来处理分组后的数据。 它可以应用于每个分组的 DataFrame,并返回任何类型的结果(例如 DataFrame、Series 或标量值)。

“`python
def top_product(x):
return x.sort_values(by=’Sales’, ascending=False).iloc[0]

top_products = df.groupby(‘Region’).apply(top_product)

print(top_products)
“`

输出:

Region Product Sales Sales_Mean_Region
Region
East East B 150 125.0
North North B 180 145.0
South South C 220 205.0
West West C 200 160.0

在这个例子中,我们定义了一个名为 top_product 的函数,用于找到每个区域销售额最高的产品。 然后,我们使用 apply() 函数将其应用于分组后的数据。 apply() 函数将每个区域的 DataFrame 传递给 top_product 函数,并将返回的结果合并成一个新的 DataFrame。

4. 常见问题与解决方案

  • 问题:groupby() 之后如何访问特定的组?

    可以使用 get_group() 方法:

    python
    grouped = df.groupby('Region')
    east_group = grouped.get_group('East')
    print(east_group)

  • 问题:如何重置分组后的 DataFrame 的索引?

    可以使用 reset_index() 方法:

    python
    grouped_sales = df.groupby('Region')['Sales'].sum().reset_index()
    print(grouped_sales)

  • 问题:如何处理分组键中的 NaN 值?

    默认情况下,dropna=True 会删除包含 NaN 值的行。如果想要包含 NaN 值作为一个组,可以将 dropna 设置为 False

    python
    import numpy as np
    df2 = df.copy()
    df2.loc[0, 'Region'] = np.nan
    grouped_sales = df2.groupby('Region', dropna=False)['Sales'].sum()
    print(grouped_sales)

  • 问题:groupby() 和 MultiIndex 的结合使用?

    groupby() 可以与 MultiIndex DataFrame 完美结合。 可以使用 level 参数来指定 MultiIndex 中的哪个级别用于分组。

    python
    index = pd.MultiIndex.from_tuples([('A', 'a'), ('A', 'b'), ('B', 'a'), ('B', 'b')], names=['Category', 'Subcategory'])
    df3 = pd.DataFrame({'Value': [1, 2, 3, 4]}, index=index)
    grouped = df3.groupby(level='Category')['Value'].sum()
    print(grouped)

  • 问题:groupby() 性能优化?

    对于大型数据集,groupby() 操作可能会比较慢。可以尝试以下优化方法:

    • 将分组键转换为 Categorical 类型: 如果分组键是字符串或数字,将其转换为 Categorical 类型可以显著提高性能。
    • 使用 numexpr 库: 对于数值计算,numexpr 库可以提供更快的执行速度。
    • 避免在 apply() 函数中使用循环: 尽量使用 Pandas 内置的向量化操作。

5. 总结

Pandas 的 groupby() 函数是一个功能强大的工具,可以用于进行各种数据分析和处理任务。 通过灵活地使用 by 参数、聚合函数 (如 sum(), mean(), max())、agg(), transform()filter() 函数,可以对 DataFrame 进行分组、聚合、转换和过滤,从而提取有价值的见解。理解 groupby() 函数的原理、参数和常见用例,对于有效使用 Pandas 进行数据分析至关重要。 记住,熟练掌握 groupby() 需要大量的练习和实践。 通过不断地尝试不同的数据和用例,您将逐渐掌握这个强大的工具。

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部