Pandas 提供了強大的資料合併功能,pd.merge 函式允許開發者根據指定的鍵值合併 DataFrame 物件。這對於整合不同來源的資料至關重要,例如將使用者資訊與交易記錄合併,或是整合不同時間段的銷售資料。合併時可以選擇不同的合併方式,例如內部合併、外部合併、左合併和右合併,以控制合併結果中資料的保留方式。開發者可以根據需求選擇合適的合併方式,確保資料的完整性和準確性。此外,pd.merge 還支援多鍵值合併,可以根據多個欄位進行匹配,提高合併的精確度。

合併DataFrame物件:使用pd.merge的技術解析

在資料重塑的過程中,合併(merge)或聯結(join)是常見的操作,尤其是在資料函式庫領域中。本文將探討pandas函式庫中的pd.merge方法,並透過實際範例展示如何有效地合併DataFrame物件。

為何需要合併DataFrame物件?

在處理資料時,我們經常需要將不同來源的資料集合併,以獲得更全面的分析結果。pd.merge提供了一種靈活的方式,根據指定的鍵(key)將兩個DataFrame物件合併。

使用pd.merge進行合併操作

首先,我們建立兩個範例DataFrame物件,分別代表第一季(Q1)和第二季(Q2)的股票交易資料:

import pandas as pd

# 建立第一季(Q1)的DataFrame
df_q1 = pd.DataFrame([
    ["AAPL", 100., 50., 75.],
    ["MSFT", 80., 42., 62.],
    ["AMZN", 60., 100., 120.],
], columns=["ticker", "shares", "low", "high"])

# 資料型別轉換
df_q1 = df_q1.convert_dtypes(dtype_backend="numpy_nullable")

# 建立第二季(Q2)的DataFrame
df_q2 = pd.DataFrame([
    ["AAPL", 80., 70., 80., 77.],
    ["MSFT", 90., 50., 60., 55.],
    ["IBM", 100., 60., 70., 64.],
    ["GE", 42., 30., 50., 44.],
], columns=["ticker", "shares", "low", "high", "close"])

# 資料型別轉換
df_q2 = df_q2.convert_dtypes(dtype_backend="numpy_nullable")

合併DataFrame物件

使用pd.merge可以根據指定的鍵(此例中為ticker欄位)合併兩個DataFrame物件:

# 使用內部合併(inner merge)
merged_df = pd.merge(df_q1, df_q2, on=["ticker"])

#### 內容解密:

  • pd.merge(df_q1, df_q2, on=["ticker"]):根據ticker欄位合併df_q1df_q2
  • on=["ticker"]引數指定了用於合併的鍵。
  • 預設情況下,pd.merge執行內部合併(inner merge),僅保留兩個DataFrame中鍵匹配的行。

合併行為控制:how引數

pd.merge提供了多種合併行為,透過how引數控制:

  • 內部合併(inner merge):預設行為,僅保留鍵匹配的行。
  • 外部合併(outer merge):保留兩個DataFrame中的所有行。
  • 左側合併(left merge):保留左側DataFrame的所有行,並根據鍵匹配右側DataFrame的資料。
  • 右側合併(right merge):與左側合併相反,保留右側DataFrame的所有行。
# 外部合併範例
merged_df_outer = pd.merge(df_q1, df_q2, on=["ticker"], how="outer")

#### 內容解密:

  • how="outer"引數指定了外部合併,保留兩個DataFrame中的所有行。
  • 若某一行在另一個DataFrame中沒有匹配的鍵,則對應的欄位將以<NA>填充。

自定義字尾:suffixes引數

當兩個DataFrame中有相同名稱的欄位時,pd.merge會自動新增字尾以區分。可以透過suffixes引數自定義字尾:

# 自定義字尾範例
merged_df_suffix = pd.merge(
    df_q1,
    df_q2,
    on=["ticker"],
    how="outer",
    suffixes=("_q1", "_q2"),
)

#### 內容解密:

  • suffixes=("_q1", "_q2")引數自定義了字尾,分別為_q1_q2,以區分來自不同季度的資料。

合併結果分析與指標

使用indicator=True引數,可以在結果DataFrame中新增一欄,指示每一行的來源:

# 新增來源指標範例
merged_df_indicator = pd.merge(df_q1, df_q2, on=["ticker"], how="outer", indicator=True)

#### 內容解密:

  • indicator=True引數在結果DataFrame中增加了 _merge 欄位,指示每一行的來源。
  • _merge欄位的值包括 bothleft_onlyright_only,分別表示該行在兩個DataFrame中都有、在左側DataFrame、在右側DataFrame。

資料框架合併的深度解析

在資料分析與處理的過程中,合併不同來源的資料是一個常見且重要的任務。Pandas 函式庫中的 pd.merge 函式提供了強大的合併功能,使得我們能夠根據特定的鍵值(key)將兩個資料框架(DataFrame)進行合併。

合併的基本概念

當我們需要合併兩個資料框架時,通常會根據一個或多個共同的欄位進行匹配。這些欄位被稱為鍵值或合併鍵。在 pd.merge 中,我們可以透過 on 引數指定這些鍵值。

簡單合併範例

假設我們有兩個資料框架 df_q1df_q2,它們分別代表了第一季度和第二季度的股票交易資料。

import pandas as pd

# 建立第一季度的資料框架
df_q1 = pd.DataFrame({
    "ticker": ["AAPL", "AMZN", "GE", "IBM", "MSFT"],
    "shares": [100, 60, None, None, 80],
    "low": [50, 100, None, None, 42],
    "high": [None, None, 555.0, 555.0, 555.0]
})

# 建立第二季度的資料框架
df_q2 = pd.DataFrame({
    "ticker": ["AAPL", "MSFT", "IBM", "GE"],
    "shares": [80, 90, 100, 42],
    "low": [70, 50, 60, 30],
    "high": [80, 60, 70, 50],
    "close": [77, 55, 64, 44]
})

# 對 df_q2 的 ticker 欄位進行重新命名
df_q2 = df_q2.rename(columns={"ticker": "SYMBOL"})

# 使用 pd.merge 合併 df_q1 和 df_q2
merged_df = pd.merge(
    df_q1,
    df_q2,
    left_on=["ticker"],
    right_on=["SYMBOL"],
    how="outer",
    suffixes=("_q1", "_q2")
)

print(merged_df)

輸出結果

ticker shares_q1 low_q1 high_q1 SYMBOL shares_q2 low_q2 high_q2 close
AAPL 100.0 50.0 None AAPL 80 70 80 77
AMZN 60.0 100.0 None None None None None None
None None None None GE 42 30 50 44
None None None None IBM 100 60 70 64
MSFT 80.0 42.0 555.0 MSFT 90 50 60 55

多鍵值合併

在某些情況下,我們需要根據多個欄位進行合併。以下範例展示瞭如何根據 tickerquarter 兩個欄位進行合併。

# 建立低價資料框架
lows = pd.DataFrame({
    "ticker": ["AAPL", "MSFT", "AMZN", "AAPL", "MSFT", "IBM", "GE"],
    "quarter": ["Q1", "Q1", "Q1", "Q2", "Q2", "Q2", "Q2"],
    "low": [50., 42., 100., 70., 50., 60., 30.]
})

# 建立高價資料框架
highs = pd.DataFrame({
    "SYMBOL": ["AAPL", "MSFT", "AMZN", "AAPL", "MSFT", "IBM", "GE"],
    "QTR": ["Q1", "Q1", "Q1", "Q2", "Q2", "Q2", "Q2"],
    "high": [75., 62., 120., 80., 60., 70., 50.]
})

# 合併低價和高價資料框架
merged_df = pd.merge(
    lows,
    highs,
    left_on=["ticker", "quarter"],
    right_on=["SYMBOL", "QTR"]
)

print(merged_df)

輸出結果

ticker quarter low SYMBOL QTR high
AAPL Q1 50.0 AAPL Q1 75.0
MSFT Q1 42.0 MSFT Q1 62.0
AMZN Q1 100.0 AMZN Q1 120.0
AAPL Q2 70.0 AAPL Q2 80.0
MSFT Q2 50.0 MSFT Q2 60.0
IBM Q2 60.0 IBM Q2 70.0
GE Q2 30.0 GE Q2 50.0

合併關係的驗證

在進行合併時,瞭解兩個資料框架之間的關係至關重要。pd.merge 提供了一個 validate引數,用於驗證合併鍵之間的關係。

# 銷售資料框架
sales = pd.DataFrame({
    "month": ["Jan", "Feb", "Mar"],
    "salesperson": ["John", "John", "John"],
    "sales": [10, 20, 30]
})

# 地區資料框架
regions = pd.DataFrame({
    "salesperson": ["John", "Jane"],
    "region": ["Northeast", "Southwest"]
})

# 合併銷售和地區資料框架
merged_df = pd.merge(sales, regions, on=["salesperson"], validate="many_to_one")

print(merged_df)

輸出結果

month salesperson sales region
Jan John 10 Northeast
Feb John 20 Northeast
Mar John

程式碼詳解:

  • 建立 DataFrame:首先,我們建立了兩個 DataFrame,分別代表第一季度和第二季度的股票交易資料。
  • 重新命名欄位:為了展示如何處理不同名稱的合併鍵,我們對第二季度的 DataFrame 中的 ticker欄位重新命名為 SYMBOL
  • 使用 pd.merge 合併:利用 pd.merge 將兩個 DataFrame 合併,指定左側 DataFrame 的 ticker欄位和右側 DataFrame 的 SYMBOL欄位作為合併鍵。
  • 多鍵值合併:進一步展示瞭如何根據多個欄位(如 tickerquarter)進行合併。
  • 驗證合併關係:最後,透過 validate引數驗證了合併鍵之間的關係,確保資料的正確性。

重塑DataFrame的藝術

在資料分析的世界中,資料的形狀和結構往往決定了分析的難易程度和結果的可讀性。Pandas函式庫中的pd.mergepd.DataFrame.joinpd.DataFrame.stackpd.DataFrame.unstack等方法,為我們提供了強大的資料重塑工具。

合併DataFrame:pd.merge vs pd.DataFrame.join

當我們需要將兩個DataFrame合併時,pd.mergepd.DataFrame.join是兩個常用的方法。雖然它們在功能上相似,但在使用場景和風格上有所不同。

為什麼選擇pd.mergepd.DataFrame.join

  • 當兩個DataFrame具有相同的合併依據(例如,某一列或索引),且需要根據特定的合併策略(例如,內連線、左連線等)進行合併時,可以使用pd.merge
  • 當需要將一個DataFrame的列新增到另一個DataFrame中,且主要DataFrame的索引與輔助DataFrame的索引相匹配時,pd.DataFrame.join提供了一個更簡潔的語法。

例項解析

假設我們有一個銷售資料表sales和一個業務人員後設資料表salesperson,兩者都透過salesperson_id索引相關聯。

# 銷售資料表
sales = pd.DataFrame(
    [[1000], [2000], [4000]],
    columns=["sales"],
    index=pd.Index([42, 555, 9000], name="salesperson_id")
)

# 業務人員後設資料表
salesperson = pd.DataFrame([
    ["Jane", "Doe"],
    ["John", "Smith"],
], columns=["first_name", "last_name"], index=pd.Index(
    [42, 555], name="salesperson_id"
))

# 使用pd.merge進行左連線
merged_df = pd.merge(sales, salesperson, left_index=True, right_index=True, how="left")

# 使用pd.DataFrame.join進行左連線
joined_df = sales.join(salesperson)

程式碼解密:

  1. 建立DataFrame:首先,我們建立了兩個DataFrame:salessalesperson。這兩個DataFrame都使用了salesperson_id作為索引。
  2. pd.merge的使用:透過指定left_index=Trueright_index=True,我們告訴pd.merge使用索引作為合併的依據。引數how="left"確保了sales表中的所有記錄都被保留。
  3. pd.DataFrame.join的使用sales.join(salesperson)實作了與上述pd.merge呼叫相同的功能,但語法更簡潔。預設情況下,pd.DataFrame.join執行左連線。
  4. 結果比較:兩種方法都將salesperson表的列新增到sales表中,並根據索引進行匹配。對於在salesperson表中沒有對應記錄的sales表中的行(例如,salesperson_id為9000),結果中將顯示<NA>

重塑DataFrame:從寬格式到長格式

在資料分析中,我們經常需要在寬格式和長格式之間轉換資料。寬格式資料的特點是每個變數佔據一列,而長格式資料則透過增加行數來表示不同的變數。

pd.DataFrame.stackpd.DataFrame.unstack的使用

  • pd.DataFrame.stack:將DataFrame從寬格式轉換為長格式,即將列「堆積疊」到行中。
  • pd.DataFrame.unstack:將DataFrame從長格式轉換為寬格式,即將行「展開」到列中。

圖表說明:

  graph LR
    A[寬格式] -->|stack|> B[長格式]
    B -->|unstack|> A

圖表翻譯: 此圖示展示了寬格式與長格式之間的轉換關係。透過 stack 方法,可以將寬格式資料轉換為長格式;反之,透過 unstack 方法,可以將長格式資料轉換回寬格式。

例項解析

假設我們有一個水果產量匯總表,記錄了不同州的水果產量。

df = pd.DataFrame([
    [12, 10, 40],
    [9, 7, 12],
    [0, 14, 190]
], columns=pd.Index(["Apple", "Orange", "Banana"], name="fruit"), index=pd.Index(
    ["Texas", "Arizona", "Florida"], name="state"))

# 將DataFrame從寬格式轉換為長格式
long_df = df.stack()

# 將DataFrame從長格式轉換回寬格式
wide_df = long_df.unstack()

程式碼解密:

  1. 建立水果產量表:首先,我們建立了一個DataFrame df,其中包含了不同州的水果產量。
  2. stack()方法的使用:呼叫df.stack()將DataFrame從寬格式轉換為長格式。在這個過程中,原本作為列的水果名稱被「堆積疊」到了行索引中,形成了一個多級索引的Series。
  3. unstack()方法的使用:對得到的長格式Series呼叫.unstack(),可以將其轉換回寬格式的DataFrame。