Python 数据分析与机器学习入门 (四):精通 Pandas 数据聚合与合并
引言:从数据处理到数据洞察
在前面的文章中,我们掌握了使用 Pandas 加载和选择数据的基本技能。然而,数据分析的真正威力在于从原始数据中提炼出有意义的洞察。这通常需要两个关键步骤:
- 聚合(Aggregation): 按类别对数据进行汇总统计。
- 合并(Combining): 将来自不同来源的数据整合在一起。
例如,分析师可能需要计算“每个产品类别的平均销售额”,或者将“客户信息表”与“订单记录表”连接起来,以分析客户的购买行为。Pandas 提供了 groupby()、merge() 和 join() 等强大的功能来轻松实现这些复杂操作。本篇将深入探讨这些高级技巧。
分组与聚合:Split-Apply-Combine 策略
“Split-Apply-Combine”(拆分-应用-合并)是数据分析中的一种经典模式,由著名统计学家 Hadley Wickham 提出。Pandas 的
.groupby()方法完美地实现了这一模式。
- 拆分 (Split): 根据一个或多个键将数据分成若干组。
- 应用 (Apply): 对每个组独立地应用一个函数(如求和、计算均值等)。
- 合并 (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():堆叠数据
与 merge 和 join 的数据库式逻辑不同,pd.concat() 主要用于**堆叠(stacking)**数据。它可以沿着一个轴将多个 DataFrame 或 Series 拼接在一起。
-
垂直堆叠 (默认,
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 中一样整合来自不同来源的数据。
至此,我们已经具备了强大的数据处理能力。然而,数字和表格往往难以直观地揭示数据背后的故事。在下一部分,我们将进入数据可视化的世界,学习如何使用 Matplotlib 和 Seaborn 将我们的分析结果以图形化的方式呈现出来,从而更直观地发现模式和趋势。
更多推荐



所有评论(0)