在資料分析領域,資料合併是一項不可或缺的技能。資料通常分散在不同的來源,格式也可能各異,需要我們有效地將它們整合起來才能進行分析。Python 的 Pandas 函式庫提供了強大的資料合併功能,讓我得以輕鬆應對各種資料整合的挑戰。
我經常使用 Pandas 的 concat()
和 merge()
方法來合併 DataFrame。concat()
就像拼接積木一樣,可以將 DataFrame 沿著行或列方向連線起來,實作聯集、交集等操作。merge()
則更像是資料函式庫中的 JOIN 操作,可以根據指定的鍵值將不同的 DataFrame 關聯起來。
基本資料合併示例
以下,我將用一些實際案例來示範如何使用這些方法。
首先,我們建立兩個 DataFrame,employees
和 salaries
,並使用 ID
作為共同鍵值:
# 匯入必要的函式庫
import pandas as pd
import numpy as np
# 建立 employees DataFrame,包含員工基本資訊
employees = pd.DataFrame({
'ID': [929, 446, 228, 299, 442, 321, 321, 882],
'Name': ['Gunter', 'Harbinger', 'Benito', 'Rudelich', 'Sirignano', 'Morrison', 'Morrison', 'Onieda'],
'Gender': ['M', 'M', 'F', 'M', 'F', 'M', 'M', 'F'],
'Dept': ['Mfg', 'Mfg', 'Mfg', 'Sales', 'Admin', 'Sales', 'Sales', 'Admin']
})
# 建立 salaries DataFrame,包含員工薪資資訊
salaries = pd.DataFrame({
'ID': [929, 446, 228, 299, 442, 871],
'Salary': [45650, 51290, 62000, 39800, 44345, 70000]
})
# 顯示建立的 DataFrame
print("Employees DataFrame:\n", employees)
print("\nSalaries DataFrame:\n", salaries)
這段程式碼首先匯入了 Pandas 和 NumPy 函式庫。然後,分別使用字典建立了 employees
和 salaries
兩個 DataFrame,包含員工的 ID、姓名、性別、部門和薪資等資訊。最後,將兩個 DataFrame 輸出到螢幕。
值得注意的是,employees
DataFrame 中,ID 為 321 的員工 Morrison 出現了兩次,這在實際資料中很常見,可能是同名同姓或者資料錄入錯誤。salaries
DataFrame 中,ID 為 871 的員工在 employees
DataFrame 中沒有對應的記錄,這也可能是資料不完整造成的。
Pandas 的不同合併方法
接下來,我們將使用不同的合併方法來整合這兩個 DataFrame。
# 使用 merge() 進行內連線(僅保留共同ID的資料)
merged_inner = pd.merge(employees, salaries, on='ID', how='inner')
print("\nInner Join:\n", merged_inner)
# 使用 merge() 進行左連線(保留所有employees資料)
merged_left = pd.merge(employees, salaries, on='ID', how='left')
print("\nLeft Join:\n", merged_left)
# 使用 merge() 進行右連線(保留所有salaries資料)
merged_right = pd.merge(employees, salaries, on='ID', how='right')
print("\nRight Join:\n", merged_right)
# 使用 merge() 進行外連線(保留所有資料)
merged_outer = pd.merge(employees, salaries, on='ID', how='outer')
print("\nOuter Join:\n", merged_outer)
這段程式碼示範了 merge()
方法的四種連線方式:內連線 (inner)、左連線 (left)、右連線 (right) 和外連線 (outer)。
- 內連線: 只保留兩個 DataFrame 中
ID
都存在的資料。 - 左連線: 保留
employees
DataFrame 中的所有資料,並將salaries
DataFrame 中比對的資料連線起來。如果employees
DataFrame 中的ID
在salaries
DataFrame 中不存在,則薪資欄位會顯示為NaN
。 - 右連線: 保留
salaries
DataFrame 中的所有資料,並將employees
DataFrame 中比對的資料連線起來。如果salaries
DataFrame 中的ID
在employees
DataFrame 中不存在,則其他欄位會顯示為NaN
。 - 外連線: 保留兩個 DataFrame 中的所有資料,並將比對的資料連線起來。如果某個
ID
只在其中一個 DataFrame 中存在,則另一個 DataFrame 對應的欄位會顯示為NaN
。
Pandas 的 concat() 方法
除了 merge(),另一個常用的合併方法是 concat():
# 使用 concat() 沿著列方向連線(垂直堆積疊)
concatenated_rows = pd.concat([employees, employees], ignore_index=True)
print("\nConcatenated Rows:\n", concatenated_rows)
# 使用 concat() 沿著列方向連線,並指定 keys 便於識別來源
concatenated_rows_keys = pd.concat([employees, employees], keys=['df1', 'df2'])
print("\nConcatenated Rows with Keys:\n", concatenated_rows_keys)
這段程式碼示範了 concat()
方法如何沿著列方向連線 DataFrame。ignore_index=True
會重新生成索引,keys
引數可以為每個 DataFrame 增加一個標籤,方便區分資料來源。
進階 Pivot Table 應用
pivot_table() 是另一個強大的資料重塑工具:
# 建立範例銷售資料
sales = pd.DataFrame({
'Year': [2022, 2022, 2022, 2023, 2023, 2023],
'ProductLine': ['Classic Cars', 'Motorcycles', 'Trucks and Buses', 'Classic Cars', 'Motorcycles', 'Trucks and Buses'],
'Territory': ['APAC', 'EMEA', 'NA', 'APAC', 'EMEA', 'NA'],
'Amount': [1000, 2000, 3000, 4000, 5000, 6000],
'Quantity': [10, 20, 30, 40, 50, 60]
})
# 漸漬複雜樞紐表,包含多個值和不同的聚合函式
pivot_table = pd.pivot_table(sales, values=['Amount', 'Quantity'],
columns='Territory',
index=['Year', 'ProductLine'],
fill_value=0,
aggfunc={'Amount': np.mean, 'Quantity': np.sum},
margins=True)
print("\nPivot Table:\n", pivot_table)
# 按年份和產品線彙總每個地區的銷售額
sales_by_year = pd.pivot_table(sales, values='Amount',
columns='Territory',
index=['Year', 'ProductLine'],
fill_value=0,
aggfunc=np.sum)
print("\nSales by Year:\n", sales_by_year)
這段程式碼示範了 pivot_table()
的一些進階用法。第一個 pivot_table()
使用了多個值欄位 (Amount
和 Quantity
),並對它們應用了不同的聚合函式 (np.mean
和 np.sum
)。fill_value=0
將缺失值填充為 0,margins=True
增加了行列總計。第二個 pivot_table()
根據年份和產品線彙總了每個地區的銷售額。
透過這些案例,我們可以看到 Pandas 提供了豐富的資料合併和處理功能,可以幫助我們高效地整合和分析資料。
選擇哪種合併方法取決於您的具體需求。理解每種方法的特性,才能在資料分析中做出最佳選擇。
資料合併流程圖示
以下流程圖展示了不同合併方法的應用場景:
graph LR D[D] H[H] A[Employees DataFrame] --> B(Merge) C[Salaries DataFrame] --> B B --> D{Merged DataFrame} E[Employees DataFrame] --> F(Concat) G[Employees DataFrame] --> F F --> H{Concatenated DataFrame} I[Sales DataFrame] --> J{Pivot Table}
實際應用:尋找未比對的資料
以下示例展示如何找出右表中未比對的鍵值:
# 建立範例資料進行未比對資料示範
import pandas as pd
# 建立左表資料(員工基本資料)
left = pd.DataFrame({'ID': [929, 446, 228, 299, 442, 321, 321, 882],
'Name': ['Gunter', 'Harbinger', 'Benito', 'Rudelich', 'Sirignano', 'Morrison', 'Morrison', 'Onieda'],
'Gender': ['M', 'M', 'F', 'M', 'F', 'M', 'M', 'F'],
'Dept': ['Mfg', 'Mfg', 'Mfg', 'Sales', 'Admin', 'Sales', 'Sales', 'Admin'],
'Salary': [45650, 51290, 62000, 39800, 44345, None, None, None]})
# 建立右表資料(薪資資料)
right = pd.DataFrame({'ID': [929, 446, 228, 299, 442, 871],
'Salary': [45650, 51290, 62000, 39800, 44345, 70000]})
# 執行 RIGHT JOIN 並使用 indicator 參數來標記資料來源
merged_df = pd.merge(left, right, on='ID', how='right', indicator=True)
# 過濾出僅出現在右表的資料(未比對的資料)
right_only_df = merged_df[merged_df['_merge'] == 'right_only']
# 顯示未比對的資料
print("未比對的資料:")
print(right_only_df)
這段程式碼首先建立了兩個 DataFrame,left
和 right
,用於模擬實際資料。接著,使用 pd.merge()
函式進行 RIGHT JOIN
操作。how='right'
引數指定了 RIGHT JOIN
,indicator=True
引數則會新增一個名為 _merge
的欄位,用於指示每一列的資料來源。最後,透過篩選 _merge
欄位的值為 'right_only'
,即可得到只存在於 right
DataFrame 中的資料列,也就是未比對的鍵值。
SAS 中的等效操作
對於同樣需求,在 SAS 中的操作方式:
/* 先對資料進行排序 */
proc sort data=left;
by id;
run;
proc sort data=right;
by id;
run;
/* 執行合併並找出未比對的鍵值 */
data r_join_nmk;
merge left(in=l) right(in=r);
by id;
if r=1 and l=0 then output;
run;
/* 顯示結果 */
proc print data=r_join_nmk;
run;
在 SAS 中,我們首先使用 PROC SORT
對 left
和 right
兩個資料集按照 ID
欄位進行排序。排序是 MERGE
操作的前提條件。接著,使用 DATA
步驟和 MERGE
陳述式進行 RIGHT JOIN
。in=l
和 in=r
選項分別建立了布林變數 l
和 r
,用於指示目前的觀察值是否來自 left
或 right
資料集。if r=1 and l=0
條件判斷篩選出只存在於 right
資料集(r=1
)與不存在於 left
資料集(l=0
)的資料列,也就是未比對的鍵值。最後,使用 PROC PRINT
顯示結果。
效能最佳化策略
高效能 JOIN
策略的選擇取決於資料集的大小、資料結構和具體的應用場景。理解不同 JOIN
方法的特性,並根據實際情況選擇合適的策略,才能最大程度地提升資料處理效率。
在資料量較大的情況下,索引的使用可以顯著提升 JOIN
操作的效能。在 pandas 中,可以利用 set_index()
方法將 JOIN
鍵設定為索引,從而加快合併速度。在 SAS 中,可以建立索引來最佳化 MERGE
操作的效能。
此外,針對不同的資料函式庫系統,還可以選擇使用特定的 JOIN
最佳化技巧,例如使用雜湊 JOIN
或排序合併 JOIN
等。
總之,選擇合適的 JOIN
策略和最佳化技巧,對於提升資料處理效能至關重要。
資料更新案例
在資料分析領域,資料合併是一項基礎與重要的技能。我經常需要合併來自不同來源的資料,例如使用者資訊、產品銷售記錄等等。不同的程式語言和工具提供了各種資料合併方法,其中 JOIN
操作是最常用的技術之一。本部分將深入比較 Python 的 Pandas 函式庫和 SAS 中的 JOIN
技術,並分享一些最佳實踐。
RIGHT JOIN:尋找未比對的資料
RIGHT JOIN
是一種特殊的合併方式,它保留右表的所有資料列,並比對左表中符合條件的資料列。如果左表中沒有比對的資料列,則用 NaN
填充。這種方法在我處理資料驗證和異常檢測時非常有用,例如找出未完成訂單的使用者,或識別未參與活動的客戶。
以下程式碼展示瞭如何在 Pandas 中使用 RIGHT JOIN
:
# 在Pandas中使用RIGHT JOIN示例
import pandas as pd
# 建立兩個測試資料框
left = pd.DataFrame({'ID': ['01', '02', '03'], 'Name': ['Alice', 'Bob', 'Charlie']})
right = pd.DataFrame({'ID': ['02', '03', '04'], 'Dept': ['Sales', 'Marketing', 'HR']})
# 執行RIGHT JOIN操作
merged_df = pd.merge(left, right, on='ID', how='right')
# 顯示合併結果
print("RIGHT JOIN結果:")
print(merged_df)
這段程式碼使用 pd.merge()
函式進行 RIGHT JOIN
。on='ID'
指定合併的鍵值欄位為 ‘ID’,how='right'
指定合併方式為 RIGHT JOIN
。
在 SAS 中,也可以使用 SQL 執行類別似操作:
/* 在SAS中使用PROC SQL執行RIGHT JOIN */
proc sql;
create table merged_table as
select coalesce(left.ID, right.ID) as ID, left.Name, right.Dept
from left
right join right on left.ID = right.ID;
quit;
在 SAS 中,我們使用 PROC SQL
執行 RIGHT JOIN
。coalesce
函式用於處理左表中缺失的 ID 值。
LEFT JOIN 與 OUTER JOIN:全方位資料合併
LEFT JOIN
保留左表的所有資料列,而 OUTER JOIN
則保留左右兩表的所有資料列。這兩種方法適用於需要保留所有資訊的場景,例如分析使用者行為或產品銷售趨勢。
Pandas 的 pd.merge()
函式同樣支援 LEFT JOIN
和 OUTER JOIN
,只需將 how
引數分別設定為 'left'
和 'outer'
即可。
SAS 中則需要調整 PROC SQL
中的 JOIN
型別。
效能最佳化:索引合併與資料驗證
在處理大型資料集時,效能最佳化至關重要。Pandas 的 join()
方法提供根據索引的合併,效率更高。此外,資料驗證也是確保合併結果準確性的關鍵步驟。
# 透過索引合併提高效能
# 建立兩個以索引為鍵的DataFrame
left = pd.DataFrame({'Name': ['Alice', 'Bob', 'Charlie']}, index=['01', '02', '03'])
right = pd.DataFrame({'Dept': ['Sales', 'Marketing', 'HR']}, index=['02', '03', '04'])
# 使用join方法根據索引合併
merged_df = left.join(right, how='outer')
# 顯示合併結果
print("根據索引的OUTER JOIN:")
print(merged_df)
此程式碼示範了 Pandas 根據索引的 OUTER JOIN
。
在 SAS 中,可以使用 PROC FREQ
或 PROC SQL
進行資料驗證,例如檢查鍵值的唯一性。
資料更新:Pandas 的 update
方法
除了合併資料,Pandas 的 update
方法可以根據索引或鍵值欄位更新 DataFrame 的值。這在我需要更新資料函式庫中的記錄時非常有用。
# 使用update方法更新DataFrame
# 建立原始DataFrame
df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})
# 建立包含更新值的DataFrame
new_df = pd.DataFrame({'A': [7, 8], 'B': [9, 10]}, index=[0, 2])
# 使用update方法更新值
df.update(new_df)
# 顯示更新後的DataFrame
print("更新後的DataFrame:")
print(df)
這段程式碼使用 new_df
更新 df
的值。
資料合併決策流程
以下流程圖說明了不同情境下的資料合併方法選擇:
graph LR B[B] D[D] A[資料準備] --> B{需要更新資料?}; B -- Yes --> C[使用 update 方法]; B -- No --> D{根據索引合併?}; D -- Yes --> E[使用 join 方法]; D -- No --> F[使用 merge 方法]; C --> G[資料更新完成]; E --> G; F --> G;
透過熟練運用 Pandas 和 SAS 中的 JOIN
和 update
方法,並結合效能最佳化和資料驗證的技巧,我們可以更有效率地處理資料合併任務,並確保資料的準確性和完整性。
本文探討了資料合併中的各種技巧,從基本的合併方法到進階的效能最佳化,希望能幫助讀者在實際資料分析中更得心應手。