• pandas数据分析 - 分组聚合、分组转换、分组筛选


    摘要

    在使用 pandas 进行数据处理时,分组聚合、分组转换和分组过滤是三个非常重要的概念,它们提供了强大的工具来分析和处理分组数据。

    1. 分组聚合 (GroupBy Aggregation): 这一过程涉及按照一个或多个键对数据进行分组,然后对每个分组应用一个或多个聚合操作(如求平均值、总和、最大值等)。这可以帮助我们理解数据的统计特性,例如计算每个部门的平均薪资。

    2. 分组转换 (GroupBy Transform): 分组转换用于对分组数据应用一个函数,通常用于数据的标准化或填充缺失值。与聚合不同,转换不会减少数据的行数,而是保留原始数据的形状,使得每个数据点都经过转换,例如对薪资进行标准化处理。

    3. 分组过滤 (GroupBy Filter): 过滤允许根据组的统计数据(例如组内平均值)决定是否保留某个组。这可以用来剔除数据中不符合某些标准的部分,例如过滤出平均薪资超过某个值的部门。

    1. 分组聚合(GroupBy Aggregation)

    分组聚合是指按某个或某些特定的列(键)将数据分组,并对每个组应用一个或多个聚合操作(如求和、平均、最大值、最小值等)。

    示例代码:

    假设我们有一个关于员工数据的 DataFrame,包含员工的部门和薪资。

    import pandas as pd
    
    # 创建数据
    data = {'Department': ['Finance', 'Marketing', 'Finance', 'HR', 'HR', 'Marketing'],
            'Employee': ['Bob', 'Jake', 'Lisa', 'Sue', 'Tom', 'Hannah'],
            'Salary': [90000, 80000, 120000, 70000, 80000, 75000]}
    df = pd.DataFrame(data)
    
    # 分组聚合,计算每个部门的平均薪资
    grouped = df.groupby('Department')['Salary'].mean()
    print(grouped)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    运行结果:
    Department
    Finance      105000.0
    HR            75000.0
    Marketing     77500.0
    Name: Salary, dtype: float64
    
    • 1
    • 2
    • 3
    • 4
    • 5

    这段代码首先通过 .groupby('Department') 对数据按部门进行分组,然后使用 .mean() 聚合函数计算每个部门的平均薪资。

    常见问题及解决方案:
    1. 如何同时计算多个聚合统计量?
      使用 .agg() 方法可以同时计算多个聚合统计量。

      grouped = df.groupby('Department')['Salary'].agg(['mean', 'sum', 'count'])
      
      • 1
    2. 如何对不同列应用不同的聚合函数?
      传递一个字典到 .agg() 方法中,其中键为列名,值为聚合函数或函数列表。

      grouped = df.groupby('Department').agg({'Salary': ['mean', 'sum'], 'Employee': 'count'})
      
      • 1
    3. 如何重置分组聚合后的索引?
      使用 .reset_index() 方法可以将分组后的索引重置为默认整数索引。

      grouped = df.groupby('Department')['Salary'].mean().reset_index()
      
      • 1
    4. 分组后如何筛选数据?
      可以在 .groupby() 后使用 .filter() 方法筛选符合特定条件的组。

      grouped = df.groupby('Department').filter(lambda x: x['Salary'].mean() > 80000)
      
      • 1
    5. 如果分组键有缺失值怎么办?
      默认情况下,含有 NaN 值的组会被自动排除。可以通过设置 dropna=False 来包含这些组。

      grouped = df.groupby('Department', dropna=False)['Salary'].mean()
      
      • 1
    常见的聚合函数

    在使用 pandas 进行数据分析时,聚合函数是处理分组数据的关键工具。它们帮助我们总结、分析数据集中的关键特征。下面是一些常见的聚合函数及其用途:

    1. mean() - 计算数值数据的平均值。非常适用于理解数据的中心趋势。

      df['column'].mean()
      
      • 1
    2. sum() - 计算数值数据的总和。适用于累加值,比如总销售额。

      df['column'].sum()
      
      • 1
    3. min() - 找出数值列中的最小值。适用于确定数值范围的下限。

      df['column'].min()
      
      • 1
    4. max() - 找出数值列中的最大值。适用于确定数值范围的上限。

      df['column'].max()
      
      • 1
    5. std() - 计算数值数据的标准差,用于衡量数据的离散程度。

      df['column'].std()
      
      • 1
    6. var() - 计算数据的方差,同样用于评估数据的离散程度。

      df['column'].var()
      
      • 1
    7. count() - 计数非空(非 NaN)数据点的数量。常用于数据完整性分析。

      df['column'].count()
      
      • 1
    8. size() - 计算每个分组的元素总数,包括 NaN 值。

      df.groupby('group_column').size()
      
      • 1
    9. nunique() - 计算不重复值的数量。常用于了解分类变量的多样性。

      df['column'].nunique()
      
      • 1
    10. median() - 计算数值数据的中位数。当数据分布不对称时,中位数是比平均数更好的中心位置度量。

      df['column'].median()
      
      • 1

    2. 分组转换(GroupBy Transform)

    分组转换涉及对数据进行分组后,对每个组内的数据应用一个函数,通常用于标准化数据或填充缺失值等操作。

    示例代码:

    我们继续使用上述的员工数据。

    # 对每个部门的薪资进行标准化处理
    standardized = df.groupby('Department')['Salary'].transform(lambda x: (x - x.mean()) / x.std())
    df['Standardized Salary'] = standardized
    print(df)
    
    • 1
    • 2
    • 3
    • 4
    运行结果:
      Department Employee  Salary  Standardized Salary
    0    Finance      Bob   90000            -0.707107
    1  Marketing     Jake   80000             0.707107
    2    Finance     Lisa  120000             0.707107
    3         HR
    
          Sue   70000            -0.707107
    4         HR      Tom   80000             0.707107
    5  Marketing   Hannah   75000            -0.707107
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    这个例子中,.transform() 方法用于对每个部门内的薪资数据进行标准化处理。

    常见问题及解决方案:
    1. 如何在分组转换中使用自定义函数?
      通过传递 lambda 函数或定义的函数到 .transform() 方法中。

      df['New Column'] = df.groupby('Department')['Salary'].transform(lambda x: x * 2)
      
      • 1
    2. 分组转换与聚合的区别是什么?
      聚合返回的是按组键减少数据点的结果,而转换返回的是与原始数据相同长度的 DataFrame。

    3. 如何在转换中填充缺失值?
      可以用 .fillna() 方法在 .transform() 中填充缺失值。

      fill_value = df['Salary'].mean()
      df['Filled Salary'] = df.groupby('Department')['Salary'].transform(lambda x: x.fillna(fill_value))
      
      • 1
      • 2
    4. 转换可以用于哪些数据类型?
      可以对数值、字符串等类型的数据进行转换。

    5. 如何确保转换后的数据与原数据对齐?
      .transform() 方法保证转换后的数据与原数据在索引上自动对齐。

    3. 分组过滤(GroupBy Filter)

    分组过滤允许你根据组的特征(如统计数据)决定是否保留某个组。

    示例代码:

    继续使用前面的员工数据。

    # 过滤出平均薪资超过80000的部门
    filtered_df = df.groupby('Department').filter(lambda x: x['Salary'].mean() > 80000)
    print(filtered_df)
    
    • 1
    • 2
    • 3
    运行结果:
      Department Employee  Salary
    0    Finance      Bob   90000
    2    Finance     Lisa  120000
    
    • 1
    • 2
    • 3

    这个例子中,.filter() 方法用于选择那些平均薪资超过 80000 的部门。

    常见问题及解决方案:
    1. 如何根据组大小过滤数据?
      可以使用 .filter() 方法来检查每个组的大小。

      filtered_df = df.groupby('Department').filter(lambda x: len(x) > 1)
      
      • 1
    2. 过滤和聚合有什么不同?
      过滤不会改变数据的内容,只根据条件决定是否保留数据,而聚合会计算统计量。

    3. 可以根据多个条件进行过滤吗?
      是的,可以在 lambda 函数中定义多个条件。

      filtered_df = df.groupby('Department').filter(lambda x: x['Salary'].mean() > 80000 and len(x) > 1)
      
      • 1
    4. 过滤后如何处理组内的数据?
      过滤后可以继续使用 .groupby() 或其他 pandas 方法进行数据处理。

    5. 如何确保过滤后的数据不丢失重要信息?
      在应用过滤条件时确保逻辑的严密性和合理性,避免过度筛选数据。

    以上就是关于 pandas 中的分组聚合、转换和过滤的详细介绍和示例。这些功能在数据处理和分析中非常有用,可以帮助你有效地探索和理解数据集。如果你有更具体的场景或问题,欢迎随时询问!

    4.拓展:自定义函数

    在 pandas 中,自定义函数允许用户根据具体的需求对数据进行特定的处理,这些处理可能超出了内置函数的能力范围。以下是几种常见的自定义函数的写法,以及如何在 DataFrame 上应用这些函数。

    自定义函数与 apply()

    自定义函数可以通过 apply() 方法应用于 pandas 的 DataFrame 或 Series。apply() 方法对 DataFrame 的每一列或每一行执行指定的函数。

    示例代码:计算每一行的最大值与最小值之差

    import pandas as pd
    
    # 创建数据
    df = pd.DataFrame({
        'A': [1, 2, 3],
        'B': [4, 5, 6],
        'C': [7, 8, 9]
    })
    
    # 定义自定义函数
    def max_minus_min(row):
        return row.max() - row.min()
    
    # 应用自定义函数
    df['Max-Min'] = df.apply(max_minus_min, axis=1)
    print(df)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    运行结果:

       A  B  C  Max-Min
    0  1  4  7        6
    1  2  5  8        6
    2  3  6  9        6
    
    • 1
    • 2
    • 3
    • 4

    这个例子中,max_minus_min 函数计算每行的最大值与最小值的差,并将结果存储在新列 Max-Min 中。

    自定义函数与 applymap()

    applymap() 方法用于对 DataFrame 的每一个元素应用一个函数,适合需要元素级别变换的场景。

    示例代码:将所有数值乘以 2

    # 定义自定义函数
    def multiply_by_two(x):
        return x * 2
    
    # 应用自定义函数
    df_transformed = df.applymap(multiply_by_two)
    print(df_transformed)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    运行结果:

       A   B   C
    0  2   8  14
    1  4  10  16
    2  6  12  18
    
    • 1
    • 2
    • 3
    • 4

    这个例子中,multiply_by_two 函数将 DataFrame 的每个元素乘以 2。

    自定义函数与 groupby().apply()

    自定义函数可以与 groupby() 结合使用来对分组数据执行更复杂的操作。

    示例代码:对每个组的数据应用排序

    # 创建分组数据
    df = pd.DataFrame({
        'Group': ['A', 'A', 'B', 'B'],
        'Data': [4, 2, 3, 1]
    })
    
    # 定义自定义函数
    def sort_data(group):
        return group.sort_values(by='Data')
    
    # 应用自定义函数
    sorted_groups = df.groupby('Group').apply(sort_data)
    print(sorted_groups)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    运行结果:

         Group  Data
    Group             
    A     1      A     2
          0      A     4
    B     3      B     1
          2      B     3
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    这个例子中,sort_data 函数对每个组内的数据按 Data 列进行排序。

    常见问题及解决方案
    1. 如何处理 apply() 函数中的 NaN 值?

      • 在自定义函数中添加对 NaN 值的检查和处理逻辑。
      def custom_func(x):
          if pd.isna(x):
              return x  # 或设定默认值
          return x * 2
      
      • 1
      • 2
      • 3
      • 4
    2. apply() 函数运行慢怎么办?

      • 尽量使用矢量化操作或内置的 pandas 函数,这些通常比 apply() 快。
      • 如果非要使用 apply(), 考虑减少数据量或简化函数逻辑。
    3. applymap() 在使用时出错怎么办?

      • 确保传递给 applymap() 的函数适用于 DataFrame 中的每一个元素。
    4. 如何在 apply() 中访问行或列的索引?

      • 在自定义函数中使用 row.namecolumn.name 访问。

    5

    . 如何处理分组后的 apply() 中的分组键?

    • 分组键默认会成为索引,如果需要作为列处理,可以使用 as_index=False 选项。

    自定义函数在数据分析过程中极为有用,允许进行灵活和复杂的数据处理。正确使用这些技术可以极大地增强 pandas 的功能,使其适应更多样化的数据分析需求。

    更多问题可咨询

    Cos机器人

  • 相关阅读:
    【4】c++11新特性(稳定性和兼容性)—>final关键字
    老生常谈,equals和hashCode的暗操作
    Hive内置函数字典
    【面试题精讲】Java移位运算符
    leetCode 647.回文子串 动态规划 + 优化空间 / 中心扩展法 + 双指针
    u盘里的东西删除怎么还原,分享2个指南
    服务器环境的关键组成部分
    一个基于C#开发的轻量级OCR文字识别开源工具
    责任链模式与spring容器的搭配应用
    【2021最新版】Spring Cloud面试题总结(35道题含答案解析)
  • 原文地址:https://blog.csdn.net/weixin_47552266/article/details/138199313