返回文章列表

Pandas合併DataFrame物件技術解析

本文探討 Pandas 中 pd.merge 的使用方法,以及如何合併 DataFrame 物件。文章涵蓋了合併方法的選擇、多鍵值合併、合併關係的驗證等方面,並以實際案例說明如何使用 pd.merge 函式進行高效的資料合併操作。同時也比較了 pd.merge 與 pd.DataFrame.join

資料科學 Python

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)

輸出結果

tickershares_q1low_q1high_q1SYMBOLshares_q2low_q2high_q2close
AAPL100.050.0NoneAAPL80708077
AMZN60.0100.0NoneNoneNoneNoneNoneNone
NoneNoneNoneNoneGE42305044
NoneNoneNoneNoneIBM100607064
MSFT80.042.0555.0MSFT90506055

多鍵值合併

在某些情況下,我們需要根據多個欄位進行合併。以下範例展示瞭如何根據 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)

輸出結果

tickerquarterlowSYMBOLQTRhigh
AAPLQ150.0AAPLQ175.0
MSFTQ142.0MSFTQ162.0
AMZNQ1100.0AMZNQ1120.0
AAPLQ270.0AAPLQ280.0
MSFTQ250.0MSFTQ260.0
IBMQ260.0IBMQ270.0
GEQ230.0GEQ250.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從長格式轉換為寬格式,即將行「展開」到列中。

圖表說明:

@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam rectangleBackgroundColor #F5F5F5
skinparam rectangleBorderColor #333333
skinparam arrowColor #333333

title 圖表說明:

rectangle "stack" as node1
rectangle "unstack" as node2

node1 --> node2

@enduml

圖表翻譯: 此圖示展示了寬格式與長格式之間的轉換關係。透過 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。