引言:从数据处理到数据洞察

在前面的文章中,我们掌握了使用 Pandas 加载和选择数据的基本技能。然而,数据分析的真正威力在于从原始数据中提炼出有意义的洞察。这通常需要两个关键步骤:

  • 聚合(Aggregation): 按类别对数据进行汇总统计。
  • 合并(Combining): 将来自不同来源的数据整合在一起。

例如,分析师可能需要计算“每个产品类别的平均销售额”,或者将“客户信息表”与“订单记录表”连接起来,以分析客户的购买行为。Pandas 提供了 groupby()merge()join() 等强大的功能来轻松实现这些复杂操作。本篇将深入探讨这些高级技巧。

分组与聚合:Split-Apply-Combine 策略

“Split-Apply-Combine”(拆分-应用-合并)是数据分析中的一种经典模式,由著名统计学家 Hadley Wickham 提出。Pandas 的 .groupby() 方法完美地实现了这一模式。

  1. 拆分 (Split): 根据一个或多个键将数据分成若干组。
  2. 应用 (Apply): 对每个组独立地应用一个函数(如求和、计算均值等)。
  3. 合并 (Combine): 将应用函数后的结果合并成一个新的数据结构。

使用 .groupby()

.groupby() 的核心思想是基于某一列(或多列)的数值,将 DataFrame 拆分成多个小的 DataFrame 组。

import pandas as pd

# 创建一个示例 DataFrame
data = {'Company': ['GOOG', 'GOOG', 'MSFT', 'MSFT', 'FB', 'FB'],
        'Person': ['Sam', 'Charlie', 'Amy', 'Vanessa', 'Carl', 'Sarah'],
        'Sales': [200, 120, 124, 340, 243, 350]}
df = pd.DataFrame(data)

# 按 'Company' 列进行分组
by_company = df.groupby('Company')

注意: 调用 df.groupby('Company') 后,by_company 并不是一个 DataFrame,而是一个 DataFrameGroupBy 对象。你可以把它想象成一个包含了三个小 DataFrame(一个对应 GOOG,一个对应 MSFT,一个对应 FB)的集合。在应用聚合函数之前,这个对象本身不会显示太多信息。

应用聚合函数

一旦有了 GroupBy 对象,就可以对其应用各种聚合函数。

  • 单个聚合:

    # 计算每个公司的平均销售额
    print(by_company.mean(numeric_only=True))
    # 输出:
    #             Sales
    # Company          
    # FB          296.5
    # GOOG        160.0
    # MSFT        232.0
    

    你也可以选择特定列进行聚合:

    # 计算每个公司的销售额总和
    print(by_company['Sales'].sum())
    # 输出:
    # Company
    # FB      593
    # GOOG    320
    # MSFT    464
    # Name: Sales, dtype: int64
    
  • 多个聚合: 使用 .agg() 方法可以同时应用多个聚合函数。

    # 对每个公司同时计算销售额的均值、总和和最大值
    print(by_company['Sales'].agg(['mean', 'sum', 'max']))
    # 输出:
    #           mean  sum  max
    # Company                   
    # FB       296.5  593  350
    # GOOG     160.0  320  200
    # MSFT     232.0  464  340
    

合并数据集:merge, join 与 concat

在实际项目中,数据往往分散在多个文件或数据库表中。Pandas 提供了类似 SQL 的接口来合并这些数据。

pd.merge():功能最强大的合并工具

pd.merge() 是最灵活、最常用的合并函数,它允许你根据一个或多个键将不同的 DataFrame 连接起来。

其核心参数包括:

  • left, right: 要合并的两个 DataFrame
  • how: 合并的方式,决定了如何处理键的匹配。
    • 'inner' (默认): 内连接。只保留两个 DataFrame 中键都存在的行。
    • 'outer': 外连接。保留两个 DataFrame 中所有的行,不匹配的地方用 NaN 填充。
    • 'left': 左连接。保留左边 DataFrame 的所有行,只合并右边 DataFrame 中匹配的行。
    • 'right': 右连接。保留右边 DataFrame 的所有行,只合并左边 DataFrame 中匹配的行。
  • on: 用于连接的列名。这个列名必须在两个 DataFrame 中都存在。
  • left_on, right_on: 当两个 DataFrame 中的连接键列名不同时,分别指定左右 DataFrame 的连接列。
left = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'],
                     'A': ['A0', 'A1', 'A2', 'A3'],
                     'B': ['B0', 'B1', 'B2', 'B3']})

right = pd.DataFrame({'key': ['K0', 'K1', 'K4', 'K5'],
                      'C': ['C0', 'C1', 'C4', 'C5'],
                      'D': ['D0', 'D1', 'D4', 'D5']})

# 内连接 (Inner Join)
inner_join = pd.merge(left, right, how='inner', on='key')
print("Inner Join:\n", inner_join)
# 输出:
# Inner Join:
#   key   A   B   C   D
# 0  K0  A0  B0  C0  D0
# 1  K1  A1  B1  C1  D1

# 左连接 (Left Join)
left_join = pd.merge(left, right, how='left', on='key')
print("\nLeft Join:\n", left_join)
# 输出:
# Left Join:
#   key   A   B    C    D
# 0  K0  A0  B0   C0   D0
# 1  K1  A1  B1   C1   D1
# 2  K2  A2  B2  NaN  NaN
# 3  K3  A3  B3  NaN  NaN

df.join():基于索引的便捷合并

df.join() 是一个便利方法,主要用于基于索引来合并 DataFrame。当你要合并的两个 DataFrame 的连接键就是它们的索引时,使用 .join() 会比 pd.merge() 更简洁。

本质: .join() 在内部调用的就是 pd.merge()。可以认为 df1.join(df2)pd.merge(df1, df2, left_index=True, right_index=True, how='left') 的一个快捷方式。它是一个为特定、常见场景(基于索引的左连接)设计的专用工具。

何时使用 join vs merge?

  • 当需要根据一个或多个列来合并时,总是使用 pd.merge()
  • 当需要根据索引来合并时,可以使用 .join() 来简化代码(主要用于左连接)。
  • 当需要进行内连接、外连接或右连接时,使用 pd.merge() 并指定 how 参数。

pd.concat():堆叠数据

mergejoin 的数据库式逻辑不同,pd.concat() 主要用于**堆叠(stacking)**数据。它可以沿着一个轴将多个 DataFrameSeries 拼接在一起。

  • 垂直堆叠 (默认, axis=0): 将多个 DataFrame 的行追加在一起。

    df1 = pd.DataFrame({'A': ['A0'], 'B': ['B0']})
    df2 = pd.DataFrame({'A': ['A1'], 'B': ['B1']})
    
    concatenated_df = pd.concat([df1, df2], ignore_index=True)
    print(concatenated_df)
    # 输出:
    #     A   B
    # 0  A0  B0
    # 1  A1  B1
    
  • 水平堆叠 (axis=1): 将多个 DataFrame 的列并排拼接。

    concatenated_df_axis1 = pd.concat([df1, df2], axis=1)
    print(concatenated_df_axis1)
    # 输出:
    #     A   B   A   B
    # 0  A0  B0  A1  B1
    

总结与展望

在本篇中,我们学习了 Pandas 中进行数据聚合与合并的高级技巧。通过 .groupby(),我们能够实现强大的“拆分-应用-合并”分析模式;通过 pd.merge().join(),我们掌握了如何像在 SQL 中一样整合来自不同来源的数据。

至此,我们已经具备了强大的数据处理能力。然而,数字和表格往往难以直观地揭示数据背后的故事。在下一部分,我们将进入数据可视化的世界,学习如何使用 MatplotlibSeaborn 将我们的分析结果以图形化的方式呈现出来,从而更直观地发现模式和趋势。

Logo

脑启社区是一个专注类脑智能领域的开发者社区。欢迎加入社区,共建类脑智能生态。社区为开发者提供了丰富的开源类脑工具软件、类脑算法模型及数据集、类脑知识库、类脑技术培训课程以及类脑应用案例等资源。

更多推荐