MinAI - Về trang chủ
Lý thuyết
6/154 giờ
Đang tải...

Pandas — Xử Lý Dữ Liệu Dạng Bảng

DataFrame, Series, Selection, Transformation, Groupby, Merge và Pivot Table

0

🎯 Mục tiêu bài học

TB5 min

Sau bài học này, bạn sẽ:

✅ Tạo và khám phá DataFrame từ nhiều nguồn dữ liệu

✅ Chọn, lọc, sắp xếp dữ liệu với loc, iloc và Boolean Indexing

✅ Biến đổi dữ liệu với apply, map, assign

✅ Nhóm và tổng hợp dữ liệu với Groupby

✅ Kết hợp bảng dữ liệu với Merge, Concat

✅ Tạo Pivot Table và chuyển đổi Wide ↔ Long format

Thời gian: 4 giờ | Độ khó: Beginner → Intermediate | Yêu cầu: NumPy cơ bản (Bài 4-5)

1

📖 Bảng Thuật Ngữ Quan Trọng

TB5 min
Thuật ngữTiếng ViệtMô tả
DataFrameKhung dữ liệuBảng 2D có labels (giống Excel/SQL table)
SeriesChuỗiMảng 1D có labels — 1 cột của DataFrame
IndexChỉ mụcNhãn dòng (row labels)
locChọn theo nhãnTruy cập dữ liệu bằng tên cột/index
ilocChọn theo vị tríTruy cập bằng số thứ tự (0, 1, 2...)
GroupbyNhómChia nhóm → Tính toán → Gộp kết quả
MergeKết hợp bảngGiống SQL JOIN — nối theo key
Pivot TableBảng tổng hợpTổng hợp dữ liệu theo dòng/cột
AggregationTổng hợpHàm gộp: sum, mean, count, max, min
Boolean IndexingLọc điều kiệnLọc dữ liệu bằng mảng True/False

Checkpoint

Bạn có thể giải thích sự khác biệt giữa lociloc không? Khi nào dùng cái nào?

2

📚 Giới thiệu Pandas

TB5 min

Pandas là gì?

Pandas là thư viện xử lý dữ liệu #1 trong Python. Hãy tưởng tượng Pandas như Excel được nâng cấp bằng code — bạn có thể đọc file, lọc dữ liệu, tính toán, và vẽ biểu đồ, nhưng với triệu dòng thay vì bị giới hạn bởi Excel. Pandas cung cấp:

  • DataFrame: Bảng 2D (giống Excel/SQL table)
  • Series: Mảng 1D với labels
Python
1import pandas as pd
2import numpy as np
3
4print(pd.__version__) # 2.x.x

DataFrame vs NumPy Array

Đặc điểmNumPy ArrayPandas DataFrame
Kiểu dữ liệuĐồng nhấtHỗn hợp (mixed)
LabelsKhôngCó (tên cột, index)
Missing valuesNaN (limited)NaN, NA (full support)
Đọc fileKhôngCSV, Excel, SQL, JSON...
SQL-likeKhônggroupby, merge, pivot

Polars là thư viện mới hơn, nhanh hơn Pandas cho big data. Tuy nhiên Pandas vẫn là tiêu chuẩn ngành và bắt buộc phải biết. Sau khi thành thạo Pandas, bạn có thể tìm hiểu thêm Polars.

3

🧱 Tạo DataFrame

TB5 min

Từ Dictionary

Python
1data = {
2 "name": ["Alice", "Bob", "Charlie"],
3 "age": [25, 30, 35],
4 "city": ["Hanoi", "HCMC", "Danang"]
5}
6df = pd.DataFrame(data)
7print(df)
8# name age city
9# 0 Alice 25 Hanoi
10# 1 Bob 30 HCMC
11# 2 Charlie 35 Danang

Từ List of Dicts

Python
1data = [
2 {"name": "Alice", "age": 25},
3 {"name": "Bob", "age": 30},
4 {"name": "Charlie", "age": 35}
5]
6df = pd.DataFrame(data)

Từ File (Quan trọng nhất!)

Python
1# CSV
2df = pd.read_csv("data.csv")
3df = pd.read_csv("data.csv", sep=";", encoding="utf-8")
4
5# Excel
6df = pd.read_excel("data.xlsx", sheet_name="Sheet1")
7
8# JSON
9df = pd.read_json("data.json")
10
11# SQL
12import sqlite3
13conn = sqlite3.connect("database.db")
14df = pd.read_sql("SELECT * FROM users", conn)
15
16# Parquet (hiệu quả cho big data)
17df = pd.read_parquet("data.parquet")

Đọc file lớn? Dùng các tham số để tối ưu:

Python
1df = pd.read_csv("big_file.csv",
2 usecols=["col1", "col2"], # Chỉ đọc cột cần
3 nrows=10000, # Limit dòng
4 dtype={"id": "int32"}, # Tiết kiệm RAM
5 parse_dates=["date_col"] # Parse ngày tháng
6)

Checkpoint

Tạo DataFrame từ dict chứa 5 sinh viên (name, score, major). In .shape.info().

4

🔍 Khám Phá Dữ Liệu

TB5 min

Xem tổng quan

Python
1df.shape # (rows, columns)
2df.head() # 5 dòng đầu
3df.head(10) # 10 dòng đầu
4df.tail() # 5 dòng cuối
5df.sample(5) # 5 dòng random
6
7df.info() # Kiểu dữ liệu, null count
8df.describe() # Thống kê mô tả (numeric)
9df.dtypes # Kiểu dữ liệu các cột
10df.columns # Tên các cột
11df.index # Index

Unique và Value Counts

Python
1df['city'].unique() # Array unique values
2df['city'].nunique() # Số lượng unique
3
4# Đếm tần suất
5df['city'].value_counts()
6# Hanoi 100
7# HCMC 80
8# Danang 50
9
10# Với tỷ lệ %
11df['city'].value_counts(normalize=True)

Workflow khám phá dữ liệu chuẩn:

  1. df.shape → biết kích thước
  2. df.head() → xem dữ liệu mẫu
  3. df.info() → kiểm tra kiểu dữ liệu + null
  4. df.describe() → thống kê cơ bản
  5. df[col].value_counts() → phân phối categorical

Checkpoint

Khi nhận 1 dataset mới, 5 dòng lệnh đầu tiên bạn chạy là gì?

5

📌 Selection — Chọn Dữ Liệu

TB5 min

Selection là gì? Là cách chọn ra đúng dữ liệu bạn cần từ bảng lớn — giống như câu lệnh SELECT ... WHERE ... trong SQL. Đây là thao tác bạn làm nhiều nhất khi phân tích dữ liệu.

Chọn cột

Python
1# Một cột → Series
2df['name']
3df.name # Shorthand (tránh nếu trùng method name)
4
5# Nhiều cột → DataFrame
6df[['name', 'age']]
7
8# Filter cột
9df.filter(like='name') # Cột chứa 'name'
10df.filter(regex='^col_') # Cột bắt đầu với 'col_'

loc — Chọn theo Label

Python
1df.loc[0] # Dòng có index 0
2df.loc[0:5] # Dòng 0 đến 5 (INCLUSIVE!)
3df.loc[0, 'name'] # Ô [dòng 0, cột 'name']
4df.loc[:, 'name':'age'] # Tất cả dòng, cột từ name đến age

iloc — Chọn theo Position

Python
1df.iloc[0] # Dòng đầu tiên
2df.iloc[0:5] # Dòng 0 đến 4 (EXCLUSIVE!)
3df.iloc[0, 0] # Ô [dòng 0, cột 0]
4df.iloc[:, 0:2] # Tất cả dòng, 2 cột đầu

loc vs iloc — Điểm khác quan trọng:

  • df.loc[0:5] → 6 dòng (0, 1, 2, 3, 4, 5) — inclusive
  • df.iloc[0:5] → 5 dòng (0, 1, 2, 3, 4) — exclusive

Giống Python slicing, iloc EXCLUSIVE đầu cuối. Nhưng loc INCLUSIVE cả hai!

Boolean Indexing (Rất quan trọng!)

Boolean Indexing là cách lọc dữ liệu bằng điều kiện. Khi viết df[df['age'] > 30], Python tạo một mảng True/False cho mỗi dòng, rồi chỉ giữ những dòng True. Đây là kỹ thuật bạn sẽ dùng hàng ngày!

Python
1# Lọc đơn giản
2df[df['age'] > 30]
3
4# Nhiều điều kiện (dùng & | ~, PHẢI có ngoặc)
5df[(df['age'] > 25) & (df['city'] == 'Hanoi')] # AND
6df[(df['age'] > 30) | (df['city'] == 'HCMC')] # OR
7df[~(df['age'] > 30)] # NOT
8
9# isin — lọc danh sách
10df[df['city'].isin(['Hanoi', 'HCMC'])]
11
12# between — lọc khoảng
13df[df['age'].between(25, 35)]
14
15# String methods
16df[df['name'].str.contains('A')]
17df[df['name'].str.startswith('A')]

Query Method (SQL-like)

Python
1df.query('age > 30')
2df.query('age > 25 and city == "Hanoi"')
3df.query('city in ["Hanoi", "HCMC"]')
4
5# Dùng biến Python
6min_age = 25
7df.query('age > @min_age')

Checkpoint

Cho DataFrame 100 dòng. Lấy ra các dòng có age > 25 VÀ city là "Hanoi" hoặc "HCMC". Viết bằng 2 cách: boolean indexing và query.

6

🔄 Transformations — Biến Đổi Dữ Liệu

TB5 min

Thêm/Sửa cột

Python
1# Thêm cột mới
2df['country'] = 'Vietnam'
3df['age_group'] = df['age'].apply(lambda x: 'Young' if x < 30 else 'Adult')
4
5# Tính toán
6df['total'] = df['price'] * df['quantity']
7
8# assign — thêm nhiều cột (trả về df mới, không thay đổi gốc)
9df = df.assign(
10 total = df['price'] * df['quantity'],
11 tax = df['price'] * 0.1
12)

Apply và Map

Python
1# apply — áp dụng function lên Series
2df['age_squared'] = df['age'].apply(lambda x: x ** 2)
3
4# apply cho cả dòng (axis=1)
5def calculate_score(row):
6 return row['score1'] + row['score2'] * 0.5
7
8df['final_score'] = df.apply(calculate_score, axis=1)
9
10# map — mapping giá trị
11city_code = {'Hanoi': 'HN', 'HCMC': 'HCM', 'Danang': 'DN'}
12df['city_code'] = df['city'].map(city_code)
13
14# replace — thay thế giá trị
15df['status'] = df['status'].replace({'active': 1, 'inactive': 0})

Sắp xếp

Python
1df.sort_values('age') # Tăng dần
2df.sort_values('age', ascending=False) # Giảm dần
3df.sort_values(['city', 'age'], ascending=[True, False]) # Nhiều cột
4df.sort_index() # Theo index

Rename

Python
1df.rename(columns={'old_name': 'new_name'})
2df.rename(columns=str.lower) # lowercase
3df.columns = df.columns.str.replace(' ', '_') # Replace spaces

Khi nào dùng apply vs vectorized?

  • Vectorized (df['a'] + df['b']): Nhanh — ưu tiên dùng
  • apply: Chậm hơn nhưng linh hoạt — dùng khi logic phức tạp
  • Quy tắc: Nếu làm được bằng vectorized → KHÔNG dùng apply

Checkpoint

Tạo cột grade dựa trên score: A (≥90), B (≥80), C (≥70), D (≥60), F (dưới 60). Dùng apply hoặc np.where.

7

📊 Groupby — Nhóm và Tổng Hợp

TB5 min

Groupby là gì? Giống GROUP BY trong SQL — chia dữ liệu thành nhóm, rồi tính toán cho mỗi nhóm. Ví dụ: tính tổng doanh thu theo thành phố, điểm trung bình theo lớp, số đơn theo ngày. Groupby theo dòng chảy: Split (điều kiện tách) → Apply (tính) → Combine (gộp kết quả).

Basic Groupby

Python
1# Groupby một cột
2df.groupby('city')['revenue'].sum()
3df.groupby('city')['revenue'].mean()
4
5# Groupby nhiều cột
6df.groupby(['city', 'category'])['revenue'].sum()

Multiple Aggregations

Python
1# Named aggregation (cách mới, rõ ràng nhất)
2df.groupby('city').agg(
3 total_revenue = ('revenue', 'sum'),
4 avg_revenue = ('revenue', 'mean'),
5 max_revenue = ('revenue', 'max'),
6 order_count = ('order_id', 'count'),
7 unique_products = ('product_id', 'nunique')
8)
9
10# Dictionary style
11df.groupby('city').agg({
12 'revenue': ['sum', 'mean', 'std'],
13 'quantity': 'sum',
14 'customers': 'count'
15})
16
17# Custom aggregation
18df.groupby('city')['revenue'].agg(lambda x: x.max() - x.min())

Transform và Filter

Python
1# transform — giữ nguyên shape (broadcast kết quả groupby)
2df['city_mean'] = df.groupby('city')['revenue'].transform('mean')
3
4# Tính % so với group
5df['pct_of_group'] = df['revenue'] / df.groupby('city')['revenue'].transform('sum')
6
7# filter — lọc groups thỏa điều kiện
8df.groupby('city').filter(lambda x: x['revenue'].sum() > 10000)

Groupby workflow: Split → Apply → Combine

  1. Split: Chia DataFrame thành groups theo key
  2. Apply: Áp dụng function lên mỗi group
  3. Combine: Gộp kết quả lại

Tương đương SQL: SELECT city, SUM(revenue) FROM df GROUP BY city

Checkpoint

Cho dataset bán hàng. Tính: tổng doanh thu, số đơn hàng, giá trị trung bình đơn hàng — theo từng thành phố. Dùng .agg().

8

🔗 Merge, Join và Concat

TB5 min

Merge (như SQL JOIN)

Python
1orders = pd.DataFrame({
2 'order_id': [1, 2, 3],
3 'customer_id': [101, 102, 101],
4 'amount': [100, 200, 150]
5})
6customers = pd.DataFrame({
7 'customer_id': [101, 102, 103],
8 'name': ['Alice', 'Bob', 'Charlie']
9})
10
11# Inner join (default)
12pd.merge(orders, customers, on='customer_id')
13
14# Left join — giữ tất cả từ bảng trái
15pd.merge(orders, customers, on='customer_id', how='left')
16
17# Right join — giữ tất cả từ bảng phải
18pd.merge(orders, customers, on='customer_id', how='right')
19
20# Outer join — giữ tất cả
21pd.merge(orders, customers, on='customer_id', how='outer')
22
23# Khác tên cột
24pd.merge(orders, customers, left_on='cust_id', right_on='customer_id')

Concat — Nối DataFrame

Python
1# Nối dọc (thêm dòng) — giống SQL UNION
2df_all = pd.concat([df1, df2, df3], ignore_index=True)
3
4# Nối ngang (thêm cột)
5df_wide = pd.concat([df1, df2], axis=1)

Merge pitfalls:

  • Duplicate keys → tạo Cartesian product (dòng nhiều hơn dự kiến!)
  • Luôn kiểm tra .shape trước và sau merge
  • Dùng validate='one_to_many' để catch lỗi sớm:
Python
1pd.merge(orders, customers, on='customer_id', validate='many_to_one')

Checkpoint

Merge 2 bảng: orders (order_id, product_id, qty) + products (product_id, name, price). Tính total = qty × price.

9

📐 Pivot Table và Melt

TB5 min

Pivot Table — Bảng tổng hợp

Python
1pivot = df.pivot_table(
2 values='revenue', # Giá trị tính toán
3 index='city', # Dòng
4 columns='month', # Cột
5 aggfunc='sum', # Hàm tổng hợp
6 fill_value=0 # Thay NaN
7)
8
9# Nhiều aggregations
10pivot = df.pivot_table(
11 values='revenue',
12 index='city',
13 columns='month',
14 aggfunc=['sum', 'mean', 'count']
15)

Melt — Wide → Long format

Python
1# Chuyển từ wide format sang long format
2df_long = df.melt(
3 id_vars=['name', 'city'], # Cột giữ nguyên
4 value_vars=['jan', 'feb', 'mar'], # Cột "unpivot"
5 var_name='month', # Tên cột mới chứa tên cột cũ
6 value_name='revenue' # Tên cột mới chứa giá trị
7)

Khi nào dùng Pivot vs Melt?

  • Pivot: Long → Wide (tóm tắt báo cáo, dashboards)
  • Melt: Wide → Long (chuẩn tidy data cho phân tích/visualization)
  • Quy tắc tidy data: Mỗi biến là 1 cột, mỗi quan sát là 1 dòng

Checkpoint

Tạo pivot table: doanh thu theo city (dòng) × month (cột). Thêm tổng hàng và tổng cột bằng margins=True.

10

💾 Export Dữ Liệu

TB5 min
Python
1# CSV
2df.to_csv("output.csv", index=False)
3df.to_csv("output.csv", index=False, encoding="utf-8-sig") # Excel-friendly
4
5# Excel
6df.to_excel("output.xlsx", sheet_name="Data", index=False)
7
8# JSON
9df.to_json("output.json", orient="records")
10
11# Parquet (hiệu quả cho big data)
12df.to_parquet("output.parquet")

Parquet nhanh hơn CSV 5-10x và nhỏ hơn 3-5x. Ưu tiên dùng cho file > 100MB.

11

📝 Tổng Kết

TB5 min

Tóm tắt kiến thức

Chủ đềHàm/Method chính
Tạo DFpd.DataFrame(), read_csv(), read_excel(), read_sql()
Khám pháshape, head(), info(), describe(), value_counts()
Selectionloc[], iloc[], boolean indexing, query()
Transformapply(), map(), assign(), sort_values(), rename()
Groupbygroupby().agg(), transform(), filter()
Mergepd.merge(), pd.concat()
Pivotpivot_table(), melt()
Exportto_csv(), to_excel(), to_parquet()

Quick Reference

Python
1import pandas as pd
2
3# Read
4df = pd.read_csv("data.csv")
5
6# Explore
7df.shape, df.info(), df.describe(), df.head()
8
9# Select
10df[df['col'] > 10]
11df.loc[0:5, 'name':'age']
12df.query('age > 25')
13
14# Transform
15df['new'] = df['a'] + df['b']
16df.groupby('city')['revenue'].agg(['sum', 'mean'])
17
18# Merge
19pd.merge(df1, df2, on='key', how='left')
20
21# Export
22df.to_csv("out.csv", index=False)

Bài tiếp theo: Thực hành Pandas với dataset thực tế — phân tích dữ liệu bán hàng! 📊

Câu hỏi tự kiểm tra

  1. loc[]iloc[] khác nhau như thế nào khi truy cập dữ liệu trong DataFrame?
  2. GroupBy trong Pandas hoạt động theo mô hình nào? Cho ví dụ tính tổng doanh thu theo thành phố.
  3. Sự khác biệt giữa merge() với how='inner'how='left' là gì?
  4. Pivot table và melt dùng trong trường hợp nào? Khi nào chuyển từ long sang wide format?

🎉 Tuyệt vời! Bạn đã hoàn thành bài học Pandas!

Tiếp theo: Thực hành Pandas với dataset thực tế để nắm vững kỹ năng xử lý dữ liệu dạng bảng!