Khi làm việc với dữ liệu trong Pandas, bạn sẽ thường gộp nhiều bảng dữ liệu khác khác nhau lại với nhau. Trong Pandas, hàm merge cho phép bạn làm điều đó từ hai DataFrame dựa trên một hoặc nhiều cột khoá chung, nó giống phép ‘JOIN’ trong SQL. Trong bài viết này mình sẽ hướng dẫn cách sử dụng hàm merge một cách hiệu quả, các tip và những điều cần lưu ý khi sử dụng. Bắt đầu nào!
Cơ bản về hàm merge
Hàm merge trong Pandas cơ bản giống phép ‘JOIN’ trong SQL, cú pháp như sau:
pd.merge(
left,
right,
how='inner',
on = None,
left_on = None,
right_on = None,
left_index = False,
right_index = False,
sort = False,
suffixes = ('_x', '_y'),
copy = True,
indicator = False,
validate = None
)
Giải thích các tham số trong hàm merge
- left và right: Hai DataFrame cần kết hợp.
- how: Loại phép gộp (‘inner’, ‘outer’, ‘left’, ‘right’).
- on: Cột hoặc danh sách cột để kết hợp giữa hai DataFrame.
- left_on và right_on: Các cột tương ứng để kết hợp nếu hai DataFrame có tên cột khác nhau.
- left_index và right_index: Sử dụng chỉ mục để kết hợp.
- suffixes: Hậu tố thêm vào khi có cột trùng tên giữa hai DataFrame.
- indicator: Thêm cột chỉ ra nguồn của mỗi bản ghi (‘both’, ‘left_only’, ‘right_only’).
Ví dụ minh hoạ
Giả sử bạn có 2 DataFrame df1, df2
DataFrame 1 (df1): có 2 cột dữ liệu id và name
import pandas as pd
data1 = {
"id": [1, 2, 3],
"name": ["Alice", "Bob", "Charlie"]
}
df1 = pd.DataFrame(data1)
DataFrame 2 (df2): có 2 cột dữ liệu id và age
data2 = {
"id": [2, 3, 4],
"age": [25, 30, 35]
}
df2 = pd.DataFrame(data2)
Nội dung của df1 và df2
# df1
id name
0 1 Alice
1 2 Bob
2 3 Charlie
# df2
id age
0 2 25
1 3 30
2 4 35
Cách sử dụng hàm merge
Chúng ta sẽ bắt đầu tìm hiểu các cách join khác nhau nhé
1. Phép ‘inner join’
Gộp hai bảng lại với nhau dựa trên các giá trị chung của cột id.
result_inner = pd.merge(df1, df2, on="id", how="inner") print(result_inner)
Kết quả
id name age
0 2 Bob 25
1 3 Charlie 30
Inner join dựa trên giá trị chung của cột id trong hai DataFrame. Ở đây, cả hai DataFrame đều có chứa id 2 và 3, vì thế kết quả là sự kết hợp dữ liệu từ cả hai DataFrame dựa trên các id 2 và 3.
2. Phép ‘left join’
Khách với ‘inner join’, ‘left join’ sẽ giữ lại tất cả dữ liệu từ df1 và kết hợp dữ liệu từ df2 dựa trên id.
result_left = pd.merge(df1, df2, on="id", how="left")
print(result_left)
Kết quả ‘left join’ giữ lại tất cả dữ liệu ở df1 và kết hợp với dữ liệu từ df2 dựa trên giá trị chung của cột id. Trong trường hợp này, df1 và df2 đều có id 2 và 3, nên chỉ có id 2 và 3 từ df2 được giữ lại.
id name age
0 1 Alice NaN
1 2 Bob 25.0
2 3 Charlie 30.0
Và một điều lưu ý, hãy quay lại dữ liệu ở df1 và df2:
- df1: có 2 cột dữ liệu là ‘id’ và ‘name’
- df2: có 2 cột dữ liệu là ‘id’ và ‘age’
Bạn để ý kết quả sau khi merge, hai id 2 và 3 đều xuất hiện ở hai bảng, nên dữ liệu được kết hợp để cung cấp đầy đủ thông tin id, name, và age. Tuy nhiên, id 1 chỉ có ở df1, nên trong kết quả chỉ chứa id và name, còn cột age được gán là NaN (Not a Number) biểu diễn dữ liệu trống trong Pandas.
3. Phép ‘right join’
Phép ‘right join’ ngược lại với ‘left join’ chỉ giữ lại dữ liệu DataFrame df2 bên phải và kết hợp dữ liệu df1 ở cột dữ liệu chung là ‘id’
result_right = pd.merge(df1, df2, on="id", how="right")
print(result_right)
Kết quả
id name age
0 2 Bob 25
1 3 Charlie 30
2 4 NaN 35
Bạn để ý ở đây dữ liệu của 2 id 2 và 3 đều xuất hiện ở cả hai df1 và df2 nên dữ liệu sẽ được kết hợp lại và có đầy đủ thông tin id, name, age. Tuy nhiên id 4 chỉ có ở df2, nên trong kết quả chỉ chứa id và age, còn cột name được gán là NaN.
4. Phép ‘outer join’
Với ‘outer join’ tất cả dữ liệu từ cả hai DataFrame được giữ lại và gộp dựa trên id.
result_outer = pd.merge(df1, df2, on="id", how="outer")
print(result_outer)
Kết quả
id name age
0 1 Alice NaN
1 2 Bob 25.0
2 3 Charlie 30.0
3 4 NaN 35.0
Tất cả dữ liệu sẽ được giữ lại ở cả hai DataFrame, với những id xuất hiện ở cả hai DataFrame sẽ được kết hợp đầy đủ thông tin id, name, và age. Và những id chỉ xuất hiện ở 1 DataFrame sẽ được gán NaN cho các cột dữ liệu thiếu.
Một số điểm cần lưu ý khi sử dụng hàm merge trong Pandas
1. Kiểm tra dữ liệu trước khi kết hợp
Trùng lặp giá trị trong cột khóa:
- Đảm bảo cột khóa (on, left_on, right_on) không có dữ liệu trùng lặp nếu bạn mong muốn kết hợp dữ liệu độc nhất.
- Sử dụng .drop_duplicates() hoặc .unique() để kiểm tra và loại bỏ các giá trị trùng lặp.
import pandas as pd
# Tạo hai DataFrame
df1 = pd.DataFrame({'id': [1, 2, 2, 3], 'name': ['Alice', 'Bob', 'Bob', 'Charlie']})
df2 = pd.DataFrame({'id': [2, 3, 4, 4], 'age': [25, 30, 40, 40]})
# Kiểm tra dữ liệu trùng lặp
if df1.duplicated(['id']).any() or df2.duplicated(['id']).any():
print("Có dữ liệu trùng lặp trong cột khóa")
else:
print("Không có dữ liệu trùng lặp trong cột khóa")
- duplicated(): Kiểm tra xem có giá trị nào trùng lặp trong cột được chỉ định hay không.
- any(): Trả về True nếu có bất kỳ giá trị trùng lặp nào.
2. Xử lý dữ liệu thiếu (NaN)
- Dữ liệu kết hợp có thể chứa giá trị NaN, đặc biệt khi sử dụng how=’left’, how=’right’ hoặc how=’outer’.
- Kiểm tra và xử lý các giá trị thiếu (NaN) bằng cách dùng .fillna() hoặc .dropna().
# Tạo hai DataFrame
df1 = pd.DataFrame({'id': [1, 2, 3], 'name': ['Alice', 'Bob', 'Charlie']})
df2 = pd.DataFrame({'id': [2, 3, 4], 'age': [25, 30, 40]})
# Kết hợp hai DataFrame bằng outer join
df_merged = pd.merge(df1, df2, on='id', how='outer')
# Điền giá trị mặc định cho các giá trị thiếu
df_merged.fillna({'age': 0, 'name': 'Unknown'}, inplace=True)
print(df_merged)
# Kết quả
id name age
0 1 Alice 0.0
1 2 Bob 25.0
2 3 Charlie 30.0
3 4 Unknown 40.0
- pd.merge(): Kết hợp hai DataFrame dựa trên cột id với phương thức outer để giữ lại tất cả dữ liệu từ cả hai DataFrame.
- fillna(): Điền giá trị mặc định cho các giá trị thiếu (NaN):
- age: Điền giá trị ‘0’.
- name: Điền giá trị ‘Unknown’.
- inplace=True: Áp dụng thay đổi trực tiếp trên DataFrame.
3. Hậu tố khi có cột trùng tên
Sử dụng tham số suffixes để đặt hậu tố phân biệt nếu hai DataFrame có các cột trùng tên.
import pandas as pd
# Tạo hai DataFrame với cột trùng tên
df1 = pd.DataFrame({'id': [1, 2, 3], 'name': ['Alice', 'Bob', 'Charlie'], 'value': [10, 20, 30]})
df2 = pd.DataFrame({'id': [2, 3, 4], 'name': ['Bobby', 'Charles', 'David'], 'value': [200, 300, 400]})
# Kết hợp hai DataFrame sử dụng inner join với hậu tố khác nhau
result = pd.merge(df1, df2, on='id', how='inner', suffixes=('_from_df1', '_from_df2'))
print(result)
# Kết quả
id name_from_df1 value_from_df1 name_from_df2 value_from_df2
0 2 Bob 20 Bobby 200
1 3 Charlie 30 Charles 300
4. Kiểm tra sự tương thích của khóa kết hợp
Sử dụng tham số validate để đảm bảo đúng loại kết hợp như mong muốn (‘one_to_one’, ‘one_to_many’, ‘many_to_one’, ‘many_to_many’).
import pandas as pd
# Tạo hai DataFrame với cột khóa 'id'
df1 = pd.DataFrame({'id': [1, 2, 3], 'name': ['Alice', 'Bob', 'Charlie']})
df2 = pd.DataFrame({'id': [2, 3, 1], 'age': [25, 30, 22]})
# Kết hợp hai DataFrame với kiểm tra loại kết hợp một-một
try:
result = pd.merge(df1, df2, on='id', how='inner', validate='one_to_one')
print(result)
except pd.errors.MergeError as e:
print("MergeError:", e)
Giải thích:
- validate: Tham số này kiểm tra loại kết hợp dự kiến giữa hai DataFrame.
- one_to_one: Xác nhận rằng mỗi giá trị trong cột khóa chỉ xuất hiện một lần ở cả hai DataFrame.
- Nếu dữ liệu không thỏa mãn điều kiện one_to_one, sẽ có lỗi MergeError.
5. Chỉ định rõ các cột kết hợp
Đặc biệt khi các DataFrame có tên cột khác nhau, hãy sử dụng left_on và right_on.
import pandas as pd
# Tạo hai DataFrame
df1 = pd.DataFrame({'id1': [1, 2, 3], 'name': ['Alice', 'Bob', 'Charlie']})
df2 = pd.DataFrame({'id2': [2, 3, 4], 'age': [25, 30, 40]})
# Kết hợp hai DataFrame khi cột trong df1 là 'id1' và trong df2 là 'id2'
result = pd.merge(df1, df2, left_on='id1', right_on='id2', how='inner')
print(result)
# Kết quả
id1 name id2 age
0 2 Bob 2 25
1 3 Charlie 3 30
Giải thích:
- left_on: Cột dùng để nối trong df1.
- right_on: Cột dùng để nối trong df2.
- how=’inner’: Chỉ giữ lại các hàng có giá trị chung giữa id1 và id2.
6. Sử dụng indicator để biết nguồn gốc của bản ghi
Thêm cột indicator để biết dữ liệu đến từ DataFrame nào.
import pandas as pd
# Tạo hai DataFrame
df1 = pd.DataFrame({'id': [1, 2, 3], 'name': ['Alice', 'Bob', 'Charlie']})
df2 = pd.DataFrame({'id': [2, 3, 4], 'age': [25, 30, 40]})
# Sử dụng indicator để xác định nguồn gốc của hàng
result = pd.merge(df1, df2, on='id', how='outer', indicator=True)
print(result)
# Kết quả
id name age _merge
0 1 Alice NaN left_only
1 2 Bob 25.0 both
2 3 Charlie 30.0 both
3 4 NaN 40.0 right_only
Giải thích:
- indicator: Tham số này tạo thêm một cột mới trong kết quả, mặc định là ‘_merge’, để chỉ ra nguồn gốc của từng hàng dữ liệu:
- left_only: Hàng chỉ có trong df1.
- right_only: Hàng chỉ có trong df2.
- both: Hàng xuất hiện ở cả hai DataFrame.
Lời khuyên nâng cao sau đây khi sử dụng hàm merge trong Pandas
Tối ưu hiệu suất với khóa có chỉ mục
Sử dụng chỉ mục (index) khi thực hiện merge để tối ưu hiệu suất. Thiết lập chỉ mục trên các cột khóa kết hợp trước khi sử dụng merge giúp tận dụng cấu trúc chỉ mục, tăng tốc độ truy xuất dữ liệu.
# Thiết lập chỉ mục trên cột khóa
df1.set_index('id', inplace=True)
df2.set_index('id', inplace=True)
# Sử dụng left_index và right_index để merge
result = pd.merge(df1, df2, left_index=True, right_index=True, how='inner')
Chỉ kết hợp các cột cần thiết
Nếu DataFrame có nhiều cột nhưng bạn chỉ cần một vài cột cho việc kết hợp, bạn chỉ nên chọn những cột cần thiết để tăng hiệu suất và giảm bộ nhớ sử dụng.
# Chỉ chọn các cột cần thiết từ mỗi DataFrame
result = pd.merge(df1[['id', 'name']], df2[['id', 'age']], on='id', how='inner')
Tránh kết hợp dữ liệu quá lớn không cần thiết
Nếu dữ liệu quá lớn, hãy chia nhỏ hoặc lọc trước khi kết hợp. Xem xét sử dụng chunksize hoặc query trước khi merge để tăng hiệu suất.
# Chia nhỏ DataFrame để kết hợp theo từng phần
chunks = pd.read_csv('large_dataset.csv', chunksize=10000)
result = pd.DataFrame()
for chunk in chunks:
partial_result = pd.merge(chunk, df2, on='id', how='inner')
result = pd.concat([result, partial_result])
Giải thích:
- chunksize: Đọc file CSV theo từng phần, giúp xử lý tập dữ liệu lớn mà không cần tải toàn bộ vào bộ nhớ.
- ‘for chunk in chunks‘: Duyệt qua từng phần dữ liệu.
- pd.merge(): Kết hợp dữ liệu từng phần với df2.
- pd.concat(): Kết hợp các kết quả từng phần thành một DataFrame đầy đủ.
Tối ưu bộ nhớ với ‘Categorical’ dtypes
Khi cột kết hợp có nhiều giá trị lặp lại, sử dụng kiểu dữ liệu Categorical giúp tối ưu bộ nhớ.
# Chuyển cột 'id' thành kiểu dữ liệu Categorical
df1['id'] = df1['id'].astype('category')
df2['id'] = df2['id'].astype('category')
# Tiến hành merge
result = pd.merge(df1, df2, on='id', how='inner')
Sử dụng query hoặc eval để lọc dữ liệu kết hợp
Sử dụng query hoặc eval để thực hiện các phép lọc và tính toán nhanh hơn sau khi kết hợp.
# Sử dụng query để lọc dữ liệu sau khi merge
result = pd.merge(df1, df2, on='id', how='inner')
filtered_result = result.query('age > 25')
# Sử dụng eval để tính toán thêm các cột mới
result.eval('age_ratio = age / value1', inplace=True)
- query: Lọc dữ liệu dựa trên biểu thức điều kiện.
- eval: Thực hiện các phép tính toán nhanh và hiệu quả hơn, hỗ trợ thêm các cột mới.
Hy vọng với những chia sẽ trong nội dung bài viết này, bạn sẽ hiểu và sử dụng hiệu quả hàm merge trong phân tích dữ liệu trong Pandas.
Với vai trò một Performance Marketer, mình cũng rất hay sử dụng hàm này khi kết hợp dữ liệu từ nhiều bảng để phân tích hiệu quả và tối ưu quảng cáo Google Ads, Facebook Ads. Nhưng để có đủ dữ liệu để phân tích, trước tiên cần lên kế hoạch tracking đầy đủ những dữ liệu bạn cần.
Hãy đăng ký nhận thông tin mới để cập nhật những nội dung hữu ích:
- Chiến lược triển khai tracking: Cách lên kế hoạch và thiết lập tracking dữ liệu phù hợp.
- Thu thập dữ liệu tự động: Sử dụng APIs, Webhooks, và các công cụ khác để thu thập dữ liệu nhanh chóng và hiệu quả.
- Phân tích data để có insight tối ưu quảng cáo.
Bạn có thể quan tâm:
- Làm sạch dữ liệu là gì? Hướng dẫn làm sạch dữ liệu với Pandas
- Checklist quan trọng để thiết kế landing page đem lại hiệu quả tối ưu cho các chiến dịch quảng cáo Google.
- Hướng dẫn sử dụng hiệu quả Google Tag Manager
- Điểm chất lượng là gì? 3 cách tối ưu điểm chất lượng quảng cáo Google Ads
- 7 lý do dẫn đến quảng cáo Google Ads hoạt động không tốt