好的,让我们把组合 DataFrames 的方法付诸实践。本节提供使用 pd.concat、pd.merge 和 .join() 方法的实际操作示例。我们将使用小型、清晰的数据集来说明每种技术的工作方式。首先,确保已导入 Pandas。我们将使用约定俗成的别名 pd。import pandas as pd import numpy as np # 通常与 Pandas 一起使用准备示例 DataFrame为了演示连接和合并,我们来创建几个简单的 DataFrame。# 用于连接的 DataFrame 示例 df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2'], 'B': ['B0', 'B1', 'B2'], 'C': ['C0', 'C1', 'C2']}, index=[0, 1, 2]) df2 = pd.DataFrame({'A': ['A3', 'A4', 'A5'], 'B': ['B3', 'B4', 'B5'], 'C': ['C3', 'C4', 'C5']}, index=[3, 4, 5]) df3 = pd.DataFrame({'D': ['D0', 'D1', 'D2'], 'E': ['E0', 'E1', 'E2'], 'F': ['F0', 'F1', 'F2']}, index=[0, 1, 2]) # 用于合并/连接的 DataFrame 示例 left_df = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'], 'L_val': ['L0', 'L1', 'L2', 'L3']}) right_df = pd.DataFrame({'key': ['K0', 'K1', 'K4', 'K5'], 'R_val': ['R0', 'R1', 'R4', 'R5']}) # 用于基于索引连接的 DataFrame 示例 left_join_df = pd.DataFrame({'L_val': ['L0', 'L1', 'L2']}, index=pd.Index(['K0', 'K1', 'K2'], name='key')) right_join_df = pd.DataFrame({'R_val': ['R0', 'R1', 'R4']}, index=pd.Index(['K0', 'K1', 'K4'], name='key')) 我们来看看最初的 DataFrame:print("--- df1 ---") print(df1) print("\n--- df2 ---") print(df2) print("\n--- df3 ---") print(df3) print("\n--- left_df ---") print(left_df) print("\n--- right_df ---") print(right_df) print("\n--- left_join_df ---") print(left_join_df) print("\n--- right_join_df ---") print(right_join_df)实践:使用 pd.concat 进行连接连接类似于将 DataFrame 堆叠或拼接在一起。垂直连接(堆叠行)这是 pd.concat 的默认行为。它垂直堆叠 DataFrame,按名称对齐列。# 垂直连接 df1 和 df2 (axis=0 是默认值) vertical_concat = pd.concat([df1, df2]) print("--- 垂直连接(默认)---") print(vertical_concat)请注意 df2 是如何附加在 df1 下方的。原始 DataFrame 的索引被保留了。如果索引的唯一性很重要,或者你更喜欢一个整洁的从 0 开始的索引,请使用 ignore_index=True。# 连接 df1 和 df2,忽略原始索引 vertical_concat_new_index = pd.concat([df1, df2], ignore_index=True) print("\n--- 垂直连接 (ignore_index=True) ---") print(vertical_concat_new_index)水平连接(添加列)要根据 DataFrame 的索引将它们并排放置,请使用 axis=1。# 水平连接 df1 和 df3 (axis=1) horizontal_concat = pd.concat([df1, df3], axis=1) print("--- 水平连接 (axis=1) ---") print(horizontal_concat)这里,df1 和 df3 是根据匹配的索引标签(0, 1, 2)组合的。如果索引没有完美对齐,Pandas 将为缺失的匹配项引入 NaN 值(这是一种沿着索引的外连接行为)。实践:使用 pd.merge 进行合并合并根据公共列中的值组合 DataFrame,类似于 SQL 连接。内连接(默认)内连接只保留键在两个 DataFrame 中都存在的行。# 对列执行内连接 inner_merge = pd.merge(left_df, right_df, on='key', how='inner') # 'how=inner' 是默认值 print("--- 内连接 ---") print(inner_merge)只有同时存在于 left_df 和 right_df 中的键 'K0' 和 'K1' 出现在结果中。外连接外连接保留两个 DataFrame 中的所有行。如果一个键在其中一个 DataFrame 中不存在,则会为源自该 DataFrame 的列引入 NaN 值。# 对列执行外连接 outer_merge = pd.merge(left_df, right_df, on='key', how='outer') print("\n--- 外连接 ---") print(outer_merge)键 'K0'、'K1'、'K2'、'K3'、'K4' 和 'K5' 都存在。请注意,当键在其中一个原始 DataFrame 中缺失时(例如,'K2' 和 'K3' 的 R_val 为 NaN,'K4' 和 'K5' 的 L_val 为 NaN),会出现 NaN 值。左连接左连接保留左侧 DataFrame 中的所有行,并包含来自右侧 DataFrame 的匹配行。如果左侧 DataFrame 的键在右侧不存在,则右侧 DataFrame 的列将使用 NaN。# 对列执行左连接 left_merge = pd.merge(left_df, right_df, on='key', how='left') print("\n--- 左连接 ---") print(left_merge)left_df 中的所有键('K0'、'K1'、'K2'、'K3')都存在。'K2' 和 'K3' 的 R_val 为 NaN,因为它们不在 right_df 中。仅存在于 right_df 中的键('K4'、'K5')被排除。右连接右连接与左连接相反。它保留右侧 DataFrame 中的所有行,并包含来自左侧的匹配行。# 对列执行右连接 right_merge = pd.merge(left_df, right_df, on='key', how='right') print("\n--- 右连接 ---") print(right_merge)right_df 中的所有键('K0'、'K1'、'K4'、'K5')都存在。'K4' 和 'K5' 的 L_val 为 NaN。仅存在于 left_df 中的键('K2'、'K3')被排除。为了帮助可视化这些连接,可以将键视为集合:digraph G { rankdir=LR; node [shape=plaintext, fontsize=12]; subgraph cluster_0 { label = "内连接\n(双方都有的键)"; bgcolor="#e9ecef"; node [shape=circle, style=filled, fillcolor="#74c0fc", fontcolor=white]; a; b; node [shape=circle, style=solid, color="#adb5bd", fontcolor="#495057"]; c; d; e; f; a [label="K0"]; b [label="K1"]; c [label="K2"]; d [label="K3"]; e [label="K4"]; f [label="K5"]; edge [style=invis]; a -> b -> c -> d -> e -> f; } subgraph cluster_1 { label = "左连接\n(左侧所有键)"; bgcolor="#e9ecef"; node [shape=circle, style=filled, fillcolor="#74c0fc", fontcolor=white]; g; h; i; j; node [shape=circle, style=solid, color="#adb5bd", fontcolor="#495057"]; k; l; g [label="K0"]; h [label="K1"]; i [label="K2"]; j [label="K3"]; k [label="K4"]; l [label="K5"]; edge [style=invis]; g -> h -> i -> j -> k -> l; } subgraph cluster_2 { label = "右连接\n(右侧所有键)"; bgcolor="#e9ecef"; node [shape=circle, style=filled, fillcolor="#74c0fc", fontcolor=white]; m; n; o; p; node [shape=circle, style=solid, color="#adb5bd", fontcolor="#495057"]; q; r; m [label="K0"]; n [label="K1"]; o [label="K4"]; p [label="K5"]; q [label="K2"]; r [label="K3"]; edge [style=invis]; m -> n -> o -> p -> q -> r; } subgraph cluster_3 { label = "外连接\n(双方所有键)"; bgcolor="#e9ecef"; node [shape=circle, style=filled, fillcolor="#74c0fc", fontcolor=white]; s; t; u; v; w; x; s [label="K0"]; t [label="K1"]; u [label="K2"]; v [label="K3"]; w [label="K4"]; x [label="K5"]; edge [style=invis]; s -> t -> u -> v -> w -> x; } }基于键 'K0'-'K5' 的不同连接类型的图示。蓝色实心圆表示每种连接类型的结果中包含的键,假设 left_df 的键是 K0-K3,right_df 的键是 K0, K1, K4, K5。基于不同列名进行合并如果 DataFrame 中的列具有不同的名称,请使用 left_on 和 right_on。# 临时重命名 right_df 中的 'key',用于演示 right_df_renamed = right_df.rename(columns={'key': 'common_key'}) print("\n--- right_df_renamed ---") print(right_df_renamed) # 使用 left_on 和 right_on 进行合并 merge_diff_names = pd.merge(left_df, right_df_renamed, left_on='key', right_on='common_key', how='inner') print("\n--- 使用不同名称合并 (left_on, right_on) ---") print(merge_diff_names)结果中包含两个原始列(left_df 中的 key 和 right_df_renamed 中的 common_key)。之后你可能需要删除其中一个。实践:使用 .join 进行基于索引的连接.join() 方法是一种基于 DataFrame 索引执行合并的便捷方式。它默认为左连接。# 对索引执行默认(左)连接 left_index_join = left_join_df.join(right_join_df, how='left') # 'how=left' 是默认值 print("--- 左索引连接(默认 .join())---") print(left_index_join)这会保留 left_join_df 中的所有索引值('K0'、'K1'、'K2'),并添加来自 right_join_df 的相应 R_val。'K2' 的 R_val 为 NaN,因为它不在 right_join_df 的索引中。你可以使用 how 参数指定其他连接类型,就像使用 pd.merge 一样。# 使用 .join() 对索引执行外连接 outer_index_join = left_join_df.join(right_join_df, how='outer') print("\n--- 外索引连接 (.join(how='outer')) ---") print(outer_index_join)这包含两个 DataFrame 的所有索引值('K0'、'K1'、'K2'、'K4'),并用 NaN 填充缺失值。你还可以使用 .join() 将 DataFrame 的索引与另一个 DataFrame 中的列进行连接,方法是将连接列临时设置为另一个 DataFrame 的索引,或者使用 .join() 中的 on 参数。# 将 left_df(使用列)与 right_join_df(使用其索引)连接 # 我们可以在 join 中使用 'on' 参数来指定 left_df 中的列 column_index_join = left_df.join(right_join_df, on='key', how='inner') print("\n--- 将列连接到索引 (right_join_df) ---") print(column_index_join)本次实践涵盖了在 Pandas 中组合 DataFrame 的主要方法。连接是堆叠数据,而合并和连接是根据共享键(在列或索引中)使用不同的逻辑规则(内、外、左、右)组合数据。请在你自己的数据集上试验这些技术,以巩固你的理解。