Appearance
🧠 Case Study — Python Basics
Từ click chuột thủ công đến script tự động — Python cơ bản thay đổi cách Data Analyst làm việc như thế nào?
Tổng quan
Trong Buổi 7, bạn đã học các nền tảng Python: data types (int, float, str, list, dict), control flow (if/else, for loop), functions, và file handling (CSV, JSON). Đây là những khái niệm "nhỏ" nhưng tạo nên sức mạnh lớn — mỗi script tự động hóa, mỗi pipeline ETL, mỗi hệ thống báo cáo đều được xây dựng từ chính những building blocks này.
Ba case study dưới đây minh họa cách Python cơ bản được áp dụng ở 3 quy mô khác nhau — từ một DA tự động hóa báo cáo cá nhân, một team DA tại tập đoàn công nghệ lớn nhất Việt Nam xây ETL pipeline, đến startup chuyển đổi từ Google Sheets sang Python pipeline. Mỗi case trả lời 3 câu hỏi: (1) Vấn đề dữ liệu gì cần giải quyết? (2) Python cơ bản giải quyết bằng cách nào? (3) Kết quả đo lường được là gì?
| # | Case Study | Vấn đề | Python Concepts chính |
|---|---|---|---|
| 1 | Automate the Boring Stuff | Báo cáo Excel thủ công mất 30 phút/ngày | CSV reading, functions, list, for loop |
| 2 | FPT Software | ETL từ 20+ nguồn dữ liệu cho 50 dự án | File handling (CSV, JSON, Excel), dict, loop, functions |
| 3 | Startup Việt Nam (DataMart) | Google Sheets + copy-paste thủ công → pipeline | Functions, automation, list/dict, control flow |
Case Study 1: Automate the Boring Stuff — Tự động hóa báo cáo KPI hàng ngày
🏷️ Thông tin
| Tiêu chí | Chi tiết |
|---|---|
| Bối cảnh | Công ty FMCG (Fast-Moving Consumer Goods) tại TP.HCM, ~500 nhân viên |
| Ngành | Bán lẻ — Hàng tiêu dùng nhanh |
| Quy mô dữ liệu | ~2,000–5,000 dòng giao dịch/ngày từ 15 cửa hàng |
| Nhân vật | Minh — Junior Data Analyst, mới vào nghề 6 tháng |
| Chủ đề DA | CSV file reading, functions, list operations, for loop, basic calculations |
📋 Bối cảnh
Minh là Junior DA tại một công ty FMCG có 15 cửa hàng tại TP.HCM và Hà Nội. Mỗi sáng, hệ thống POS (Point of Sale) xuất file CSV chứa toàn bộ giao dịch ngày hôm trước — mỗi dòng gồm: mã giao dịch, cửa hàng, sản phẩm, số lượng, đơn giá, thời gian mua. Nhiệm vụ của Minh: tổng hợp file CSV này thành báo cáo KPI hàng ngày gửi cho quản lý trước 9h sáng.
⚡ Vấn đề
Quy trình cũ hoàn toàn thủ công:
- Mở file CSV bằng Excel (~2 phút chờ load 5,000 dòng)
- Tạo PivotTable tính tổng doanh thu theo cửa hàng (~5 phút)
- Tính các KPI: tổng doanh thu, số đơn hàng, giá trị đơn trung bình (AOV), top 5 sản phẩm bán chạy (~8 phút)
- So sánh với ngày hôm trước (mở thêm 1 file cũ, copy số liệu) (~5 phút)
- Format bảng đẹp, copy vào email gửi sếp (~10 phút)
Tổng: ~30 phút mỗi sáng — lặp lại 365 ngày/năm. Nếu sai 1 ô PivotTable → sai cả báo cáo → sếp mất niềm tin.
⚠️ Pain Points
- Tốn thời gian: 30 phút × 250 ngày làm việc = 125 giờ/năm chỉ cho 1 báo cáo
- Dễ sai sót: Copy-paste sai ô, quên filter, PivotTable chọn nhầm range
- Không scale: Nếu thêm 5 cửa hàng mới → phải sửa lại PivotTable thủ công
- Không version control: Không biết ai sửa gì, lúc nào
🛠️ Giải pháp
Minh học Python cơ bản trong 2 tuần và viết script tự động hóa toàn bộ quy trình.
Bước 1: Đọc file CSV bằng Python
python
import csv
def doc_du_lieu_csv(file_path):
"""Đọc file CSV và trả về list of dictionaries"""
du_lieu = []
with open(file_path, mode='r', encoding='utf-8') as file:
reader = csv.DictReader(file)
for dong in reader:
# Chuyển đổi kiểu dữ liệu
dong['so_luong'] = int(dong['so_luong'])
dong['don_gia'] = float(dong['don_gia'])
dong['thanh_tien'] = dong['so_luong'] * dong['don_gia']
du_lieu.append(dong)
return du_lieu
# Sử dụng
giao_dich = doc_du_lieu_csv('sales_2026-02-17.csv')
print(f"Tổng số giao dịch: {len(giao_dich)}")
# Output: Tổng số giao dịch: 4,832🔍 Python Basics tại đây
- Function (
def doc_du_lieu_csv): Đóng gói logic thành khối tái sử dụng - List (
du_lieu = []): Lưu trữ tất cả giao dịch - Dictionary (
dong— mỗi dòng CSV là 1 dict với key là tên cột): Truy cập dữ liệu bằng tên cột thay vì index - For loop (
for dong in reader): Duyệt qua từng dòng dữ liệu - Type conversion:
int(),float()— chuyển đổi string sang số
Bước 2: Tính KPI bằng functions
python
def tinh_kpi(giao_dich):
"""Tính các KPI chính từ danh sách giao dịch"""
tong_doanh_thu = 0
doanh_thu_theo_cua_hang = {}
san_pham_count = {}
for gd in giao_dich:
# Tổng doanh thu
tong_doanh_thu += gd['thanh_tien']
# Doanh thu theo cửa hàng — dùng dict
cua_hang = gd['cua_hang']
if cua_hang not in doanh_thu_theo_cua_hang:
doanh_thu_theo_cua_hang[cua_hang] = 0
doanh_thu_theo_cua_hang[cua_hang] += gd['thanh_tien']
# Đếm số lượng bán theo sản phẩm
sp = gd['san_pham']
if sp not in san_pham_count:
san_pham_count[sp] = 0
san_pham_count[sp] += gd['so_luong']
# Tính AOV (Average Order Value)
so_don = len(giao_dich)
aov = tong_doanh_thu / so_don if so_don > 0 else 0
# Top 5 sản phẩm bán chạy — sort dict by value
top_5_sp = sorted(san_pham_count.items(),
key=lambda x: x[1], reverse=True)[:5]
return {
'tong_doanh_thu': tong_doanh_thu,
'so_don_hang': so_don,
'aov': round(aov, 0),
'doanh_thu_cua_hang': doanh_thu_theo_cua_hang,
'top_5_san_pham': top_5_sp
}
kpi = tinh_kpi(giao_dich)
print(f"Tổng doanh thu: {kpi['tong_doanh_thu']:,.0f} VNĐ")
print(f"Số đơn hàng: {kpi['so_don_hang']}")
print(f"AOV: {kpi['aov']:,.0f} VNĐ")
# Output:
# Tổng doanh thu: 892,450,000 VNĐ
# Số đơn hàng: 4,832
# AOV: 184,720 VNĐBước 3: So sánh với ngày hôm trước
python
def so_sanh_ngay(kpi_hom_nay, kpi_hom_qua):
"""So sánh KPI hôm nay vs hôm qua, trả về % thay đổi"""
thay_doi = {}
for key in ['tong_doanh_thu', 'so_don_hang', 'aov']:
gia_tri_nay = kpi_hom_nay[key]
gia_tri_qua = kpi_hom_qua[key]
if gia_tri_qua > 0:
phan_tram = ((gia_tri_nay - gia_tri_qua) / gia_tri_qua) * 100
thay_doi[key] = round(phan_tram, 1)
else:
thay_doi[key] = 0
return thay_doi
# So sánh
giao_dich_hom_qua = doc_du_lieu_csv('sales_2026-02-16.csv')
kpi_hom_qua = tinh_kpi(giao_dich_hom_qua)
thay_doi = so_sanh_ngay(kpi, kpi_hom_qua)
print(f"Doanh thu thay đổi: {thay_doi['tong_doanh_thu']:+.1f}%")
# Output: Doanh thu thay đổi: +12.3%📊 Kết quả
| Chỉ số | Trước (thủ công) | Sau (Python script) | Cải thiện |
|---|---|---|---|
| Thời gian/báo cáo | 30 phút | 3 phút (chạy script) | -90% |
| Thời gian/năm | 125 giờ | 12.5 giờ | Tiết kiệm 112.5 giờ/năm |
| Tỷ lệ lỗi | ~5% (sai ô, nhầm filter) | ~0% (logic cố định) | Gần như loại bỏ lỗi |
| Mở rộng cửa hàng mới | Sửa PivotTable 15 phút | 0 phút (tự động detect) | 100% tự động |
| Consistency | Tùy ngày (mệt = sai) | 100% nhất quán | — |
💡 Bài học quan trọng
Script chỉ dùng 4 khái niệm Python cơ bản: đọc CSV, for loop, dictionary, function. Không cần Pandas, không cần thư viện phức tạp. Đây là "80/20 rule" — 20% kiến thức Python giải quyết 80% vấn đề lặp đi lặp lại.
🎓 Bài học cho DA
- Bắt đầu từ pain point nhỏ: Đừng cố tự động hóa mọi thứ cùng lúc. Minh chỉ tự động 1 báo cáo — nhưng tiết kiệm 112.5 giờ/năm.
- Function = tái sử dụng: Hàm
tinh_kpi()có thể dùng cho bất kỳ file CSV nào cùng format — hôm nay, tuần trước, tháng trước. - Dictionary là cấu trúc dữ liệu core cho DA: Gom nhóm theo cửa hàng, đếm theo sản phẩm — dict làm được tất cả.
- Script > spreadsheet khi dữ liệu lặp lại: Nếu bạn làm cùng 1 thao tác > 3 lần → viết script.
Case Study 2: FPT Software — Python ETL từ 20+ nguồn dữ liệu
🏷️ Thông tin
| Tiêu chí | Chi tiết |
|---|---|
| Công ty | FPT Software — công ty công nghệ lớn nhất Việt Nam |
| Ngành | IT Services & Outsourcing |
| Quy mô | 30,000+ nhân viên, doanh thu >$1 tỷ (2025), hoạt động tại 30+ quốc gia |
| Team | Data Analytics Center of Excellence — 15 DA/DE phục vụ 50+ dự án nội bộ |
| Chủ đề DA | File handling (CSV, JSON, Excel), dictionary, nested loops, functions, error handling |
📋 Bối cảnh
FPT Software có hơn 50 dự án phần mềm chạy song song cho khách hàng toàn cầu (Nhật Bản, Mỹ, Châu Âu). Mỗi dự án tạo ra dữ liệu từ nhiều hệ thống khác nhau: Jira (quản lý task), GitLab (source code), Confluence (tài liệu), Timesheet (chấm công), HR system (nhân sự), Finance (chi phí dự án). Ban lãnh đạo cần báo cáo tổng hợp hiệu suất dự án hàng tuần — nhưng dữ liệu nằm rải rác ở 20+ nguồn, mỗi nguồn 1 format khác nhau.
Team Data Analytics Center of Excellence (DA CoE) gồm 15 người chịu trách nhiệm thu thập, chuẩn hóa và phân tích dữ liệu từ tất cả nguồn. Trước khi dùng Python, mọi thứ là thủ công: download file, mở Excel, copy-paste, chỉnh format, ghép lại.
⚡ Vấn đề
20+ nguồn dữ liệu, mỗi nguồn 1 format:
| Nguồn | Format | Tần suất | Dữ liệu |
|---|---|---|---|
| Jira Cloud | JSON (API response) | Real-time | Tasks, bugs, story points |
| GitLab | JSON | Daily export | Commits, merge requests |
| Timesheet | CSV | Weekly export | Giờ làm việc theo dự án |
| HR System | Excel (.xlsx) | Monthly | Nhân sự, phòng ban, level |
| Finance | CSV | Monthly | Budget, actual cost |
| Client Survey | Excel | Quarterly | CSAT scores |
Quy trình cũ: 1 DA mất 2 ngày (16 giờ) mỗi tuần chỉ để thu thập và chuẩn hóa dữ liệu từ 20 nguồn. Còn chưa kể lỗi: nhầm format ngày (MM/DD vs DD/MM), encoding UTF-8 bị lỗi tiếng Việt, cột bị lệch khi copy-paste giữa các file.
❌ Hậu quả của ETL thủ công
- 32 giờ/tháng (2 ngày/tuần × 4 tuần) chỉ cho data collection
- Trung bình 3 lỗi dữ liệu/tuần (nhầm format, thiếu dòng, sai encoding)
- Báo cáo trễ deadline 40% thời gian vì phụ thuộc vào 1 người
- Không reproducible: Nếu DA nghỉ phép → không ai biết các bước thủ công
🛠️ Giải pháp
Team DA CoE xây dựng bộ Python scripts sử dụng kiến thức Python cơ bản — không dùng Pandas trong phase đầu, chỉ dùng csv, json modules có sẵn trong Python.
Script 1: Đọc và chuẩn hóa nhiều loại file
python
import csv
import json
def doc_csv(file_path):
"""Đọc file CSV, trả về list of dict"""
ket_qua = []
with open(file_path, mode='r', encoding='utf-8') as f:
reader = csv.DictReader(f)
for dong in reader:
ket_qua.append(dong)
return ket_qua
def doc_json(file_path):
"""Đọc file JSON, trả về list hoặc dict"""
with open(file_path, mode='r', encoding='utf-8') as f:
du_lieu = json.load(f)
return du_lieu
def chuan_hoa_ngay(ngay_str):
"""Chuẩn hóa các format ngày khác nhau về DD/MM/YYYY"""
# Xử lý các format: 2026-02-17, 02/17/2026, 17-02-2026
if '-' in ngay_str and len(ngay_str.split('-')[0]) == 4:
# Format: YYYY-MM-DD (từ Jira, GitLab)
parts = ngay_str.split('-')
return f"{parts[2]}/{parts[1]}/{parts[0]}"
elif '/' in ngay_str and len(ngay_str.split('/')[2]) == 4:
# Format: MM/DD/YYYY (từ hệ thống Mỹ)
parts = ngay_str.split('/')
return f"{parts[1]}/{parts[0]}/{parts[2]}"
return ngay_str # Đã đúng format DD/MM/YYYY
# Sử dụng
timesheet = doc_csv('exports/timesheet_week07.csv')
jira_tasks = doc_json('exports/jira_sprint_42.json')
print(f"Timesheet: {len(timesheet)} records")
print(f"Jira tasks: {len(jira_tasks)} records")
# Output:
# Timesheet: 3,240 records
# Jira tasks: 1,856 recordsScript 2: Gom dữ liệu từ nhiều nguồn vào 1 cấu trúc thống nhất
python
def tao_bao_cao_du_an(jira_tasks, timesheet_data, hr_data):
"""
Gom dữ liệu từ 3 nguồn thành báo cáo theo dự án.
Dùng dict để gom nhóm — key là mã dự án.
"""
du_an = {}
# Gom task từ Jira (JSON) — đếm theo trạng thái
for task in jira_tasks:
ma_da = task['project_key']
if ma_da not in du_an:
du_an[ma_da] = {
'ten_du_an': task['project_name'],
'tasks_done': 0,
'tasks_in_progress': 0,
'tasks_todo': 0,
'total_story_points': 0,
'tong_gio_lam': 0,
'so_nhan_su': 0
}
# Đếm task theo trạng thái
trang_thai = task['status'].lower()
if trang_thai == 'done':
du_an[ma_da]['tasks_done'] += 1
elif trang_thai == 'in progress':
du_an[ma_da]['tasks_in_progress'] += 1
else:
du_an[ma_da]['tasks_todo'] += 1
du_an[ma_da]['total_story_points'] += int(task.get('story_points', 0))
# Gom giờ làm từ Timesheet (CSV)
for ts in timesheet_data:
ma_da = ts['project_code']
if ma_da in du_an:
du_an[ma_da]['tong_gio_lam'] += float(ts['hours'])
# Đếm nhân sự từ HR Data
nhan_su_theo_da = {}
for nv in hr_data:
ma_da = nv['project_code']
if ma_da not in nhan_su_theo_da:
nhan_su_theo_da[ma_da] = set()
nhan_su_theo_da[ma_da].add(nv['employee_id'])
for ma_da in du_an:
if ma_da in nhan_su_theo_da:
du_an[ma_da]['so_nhan_su'] = len(nhan_su_theo_da[ma_da])
return du_an
# Chạy gom dữ liệu
hr_data = doc_csv('exports/hr_assignment.csv')
bao_cao = tao_bao_cao_du_an(jira_tasks, timesheet, hr_data)
# In kết quả
for ma, info in bao_cao.items():
ti_le_done = 0
tong_task = info['tasks_done'] + info['tasks_in_progress'] + info['tasks_todo']
if tong_task > 0:
ti_le_done = round(info['tasks_done'] / tong_task * 100, 1)
print(f"[{ma}] {info['ten_du_an']}: "
f"{ti_le_done}% done, "
f"{info['tong_gio_lam']:.0f}h logged, "
f"{info['so_nhan_su']} members")Kết quả ví dụ:
[FPT-JP01] Toyota Connected Platform: 78.5% done, 2,840h logged, 45 members
[FPT-US03] Healthcare Analytics: 65.2% done, 1,560h logged, 28 members
[FPT-EU07] Banking Data Migration: 42.8% done, 3,200h logged, 52 membersScript 3: Ghi kết quả ra file CSV tổng hợp
python
def xuat_bao_cao_csv(du_an_dict, output_path):
"""Ghi báo cáo tổng hợp ra file CSV"""
headers = ['ma_du_an', 'ten_du_an', 'tasks_done', 'tasks_in_progress',
'tasks_todo', 'ti_le_hoan_thanh', 'tong_gio_lam', 'so_nhan_su']
with open(output_path, mode='w', encoding='utf-8', newline='') as f:
writer = csv.DictWriter(f, fieldnames=headers)
writer.writeheader()
for ma, info in du_an_dict.items():
tong_task = info['tasks_done'] + info['tasks_in_progress'] + info['tasks_todo']
ti_le = round(info['tasks_done'] / tong_task * 100, 1) if tong_task > 0 else 0
writer.writerow({
'ma_du_an': ma,
'ten_du_an': info['ten_du_an'],
'tasks_done': info['tasks_done'],
'tasks_in_progress': info['tasks_in_progress'],
'tasks_todo': info['tasks_todo'],
'ti_le_hoan_thanh': f"{ti_le}%",
'tong_gio_lam': info['tong_gio_lam'],
'so_nhan_su': info['so_nhan_su']
})
print(f"✅ Đã xuất báo cáo: {output_path}")
xuat_bao_cao_csv(bao_cao, 'reports/weekly_report_2026_W07.csv')
# Output: ✅ Đã xuất báo cáo: reports/weekly_report_2026_W07.csv🔍 Python Basics tại đây
- File handling đa format:
csv.DictReadercho CSV,json.load()cho JSON — cùng trả về list/dict - Nested dictionary:
du_an[ma_da]— mỗi dự án là 1 dict chứa nhiều KPI - Nested loops: Loop qua tasks → loop qua timesheet → gom vào cùng dict theo
project_key - Functions làm building blocks: Mỗi function xử lý 1 nguồn dữ liệu → ghép lại thành pipeline
- set(): Đếm unique employees — tránh trùng khi 1 nhân sự log timesheet nhiều lần
📊 Kết quả
| Chỉ số | Trước (thủ công) | Sau (Python scripts) | Cải thiện |
|---|---|---|---|
| Thời gian ETL/tuần | 16 giờ (2 ngày) | 2 giờ (chạy scripts + review) | -87.5% |
| Lỗi dữ liệu/tuần | ~3 lỗi (format, encoding, thiếu dòng) | < 0.5 lỗi (chỉ edge case) | -83% |
| Số nguồn xử lý được | 8 nguồn (giới hạn sức người) | 20+ nguồn (thêm nguồn = thêm function) | +150% |
| Bus factor | 1 người (nghỉ = tê liệt) | Bất kỳ ai chạy script được | Loại bỏ rủi ro |
| Tổng tiết kiệm/năm | — | 728 giờ/năm (14h × 52 tuần) | ~$15,000 giá trị nhân lực |
🎓 Bài học cho DA
- Python cơ bản đủ để xây ETL pipeline: Chỉ dùng
csv,json— 2 modules có sẵn trong Python, không cần install thêm gì. - Dictionary là trung tâm của data aggregation: Gom nhóm theo project, đếm theo trạng thái, merge nhiều nguồn — tất cả dùng dict.
- Mỗi function = 1 data source: Thiết kế
doc_csv(),doc_json()riêng biệt → dễ maintain, dễ test, dễ thêm nguồn mới. - Chuẩn hóa dữ liệu trước khi gom: Hàm
chuan_hoa_ngay()giải quyết vấn đề format ngày khác nhau giữa các hệ thống — bước nhỏ nhưng critical.
Case Study 3: DataMart (Startup VN) — Từ Google Sheets + Manual đến Python Pipeline
🏷️ Thông tin
| Tiêu chí | Chi tiết |
|---|---|
| Công ty | DataMart — startup SaaS quản lý bán hàng đa kênh tại Việt Nam |
| Ngành | E-commerce SaaS — Nền tảng quản lý bán hàng |
| Quy mô | 12 nhân sự, 500+ merchants sử dụng platform, Series A (~$2M) |
| Team Data | 2 người: 1 DA (Linh) + 1 backend dev hỗ trợ part-time |
| Chủ đề DA | Functions, list/dict processing, control flow (if/else), automation, CSV/JSON |
📋 Bối cảnh
DataMart là startup Việt Nam cung cấp SaaS cho các shop bán hàng trên Shopee, Lazada, TikTok Shop. Platform giúp merchants quản lý đơn hàng, tồn kho, và khách hàng từ nhiều sàn TMĐT trên một giao diện. Có 500+ merchants đang sử dụng, tổng ~150,000 đơn hàng/tháng.
Linh — DA duy nhất của DataMart — chịu trách nhiệm tạo báo cáo cho CEO, investors, và đội Sales. Vì startup nhỏ, không có Data Engineer, không có data warehouse — mọi dữ liệu nằm trong Google Sheets và database exports (CSV).
⚡ Vấn đề
Quy trình "data analysis" cũ tại DataMart:
- Export dữ liệu từ database admin → file CSV (~5 phút)
- Import vào Google Sheets → chờ load (~3 phút nếu >50,000 dòng)
- Copy-paste dữ liệu từ 3 sheets (đơn hàng, merchants, sản phẩm) vào 1 sheet tổng hợp (~15 phút)
- Viết VLOOKUP ghép thông tin merchant vào đơn hàng (~10 phút)
- Tạo charts trong Google Sheets (~10 phút)
- Copy charts vào Google Slides cho meeting (~5 phút)
Tổng: ~48 phút cho 1 báo cáo. Linh phải làm 3 báo cáo/tuần: (1) Weekly Metrics cho CEO, (2) Monthly Cohort cho Investors, (3) Sales Performance cho team Sales.
⚠️ Giới hạn Google Sheets
- 10 triệu ô limit: Với 150,000 đơn/tháng × 15 cột = 2.25 triệu ô/tháng → chỉ lưu được ~4 tháng lịch sử
- Chậm khi >50,000 dòng: VLOOKUP trên 100,000 dòng → Sheets đơ 30 giây
- Không version control: "Sheet tổng hợp v2 FINAL (copy)" — rất quen thuộc
- Không tự động: Mỗi tuần lặp lại y hệt — nhưng phải làm tay
🛠️ Giải pháp
Linh dành 3 tuần cuối tuần học Python cơ bản (theo đúng nội dung Buổi 7), sau đó bắt đầu chuyển đổi dần từ Google Sheets sang Python scripts.
Script 1: Đọc và ghép dữ liệu từ nhiều file CSV (thay thế VLOOKUP)
python
import csv
def doc_csv_thanh_dict(file_path, key_field):
"""
Đọc CSV và tạo lookup dictionary — thay thế VLOOKUP.
Key: giá trị của cột key_field
Value: toàn bộ dòng (dict)
"""
lookup = {}
with open(file_path, mode='r', encoding='utf-8') as f:
reader = csv.DictReader(f)
for dong in reader:
key = dong[key_field]
lookup[key] = dong
return lookup
def ghep_du_lieu(don_hang_list, merchant_lookup, san_pham_lookup):
"""
Ghép 3 nguồn dữ liệu: đơn hàng + merchant + sản phẩm.
Tương đương VLOOKUP trong Google Sheets — nhưng nhanh hơn 100x.
"""
ket_qua = []
loi_khong_tim_thay = 0
for don in don_hang_list:
merchant_id = don['merchant_id']
product_id = don['product_id']
# Lookup merchant info
merchant = merchant_lookup.get(merchant_id, None)
san_pham = san_pham_lookup.get(product_id, None)
if merchant is None or san_pham is None:
loi_khong_tim_thay += 1
continue # Skip nếu không tìm thấy
# Ghép dữ liệu thành 1 record hoàn chỉnh
record = {
'order_id': don['order_id'],
'ngay_dat': don['order_date'],
'kenh_ban': don['channel'], # shopee, lazada, tiktok
'merchant_name': merchant['name'],
'merchant_tier': merchant['tier'], # gold, silver, bronze
'san_pham': san_pham['product_name'],
'danh_muc': san_pham['category'],
'so_luong': int(don['quantity']),
'doanh_thu': float(don['revenue']),
'trang_thai': don['status']
}
ket_qua.append(record)
print(f"✅ Ghép thành công: {len(ket_qua)} records")
if loi_khong_tim_thay > 0:
print(f"⚠️ Không tìm thấy: {loi_khong_tim_thay} records")
return ket_qua
# Chạy pipeline
don_hang = doc_csv_thanh_dict('data/orders_feb2026.csv', 'order_id')
merchant_lookup = doc_csv_thanh_dict('data/merchants.csv', 'merchant_id')
san_pham_lookup = doc_csv_thanh_dict('data/products.csv', 'product_id')
don_hang_list = list(don_hang.values())
du_lieu_ghep = ghep_du_lieu(don_hang_list, merchant_lookup, san_pham_lookup)
# Output:
# ✅ Ghép thành công: 148,523 records
# ⚠️ Không tìm thấy: 1,477 recordsScript 2: Tính metrics theo kênh bán hàng và tier merchant
python
def tinh_metrics_theo_nhom(du_lieu, group_field):
"""
Tính tổng doanh thu và số đơn theo 1 trường phân nhóm.
Linh hoạt: group theo 'kenh_ban', 'merchant_tier', 'danh_muc', v.v.
"""
nhom = {}
for record in du_lieu:
key = record[group_field]
if key not in nhom:
nhom[key] = {
'so_don': 0,
'doanh_thu': 0,
'san_pham_list': []
}
if record['trang_thai'] == 'completed':
nhom[key]['so_don'] += 1
nhom[key]['doanh_thu'] += record['doanh_thu']
nhom[key]['san_pham_list'].append(record['san_pham'])
# Tính AOV cho mỗi nhóm
for key in nhom:
so_don = nhom[key]['so_don']
nhom[key]['aov'] = round(nhom[key]['doanh_thu'] / so_don, 0) if so_don > 0 else 0
# Đếm unique sản phẩm
nhom[key]['unique_products'] = len(set(nhom[key]['san_pham_list']))
del nhom[key]['san_pham_list'] # Giải phóng memory
return nhom
# Phân tích theo kênh bán hàng
metrics_kenh = tinh_metrics_theo_nhom(du_lieu_ghep, 'kenh_ban')
for kenh, data in sorted(metrics_kenh.items(),
key=lambda x: x[1]['doanh_thu'], reverse=True):
print(f"{kenh:12s} | {data['so_don']:>8,} đơn | "
f"{data['doanh_thu']:>15,.0f} VNĐ | AOV: {data['aov']:>10,.0f}")Kết quả:
shopee | 72,450 đơn | 38,520,000,000 VNĐ | AOV: 531,677
lazada | 41,280 đơn | 25,180,000,000 VNĐ | AOV: 610,078
tiktok_shop | 34,793 đơn | 15,240,000,000 VNĐ | AOV: 438,003Script 3: Tự động detect anomalies
python
def detect_anomaly(du_lieu, nguong_phan_tram=50):
"""
Phát hiện merchants có doanh thu giảm đột ngột.
So sánh tuần này vs tuần trước — nếu giảm > ngưỡng → cảnh báo.
"""
canh_bao = []
# Gom doanh thu theo merchant + tuần
merchant_weekly = {}
for record in du_lieu:
m_name = record['merchant_name']
tuan = record['ngay_dat'][:7] # YYYY-MM (demo đơn giản)
if m_name not in merchant_weekly:
merchant_weekly[m_name] = {}
if tuan not in merchant_weekly[m_name]:
merchant_weekly[m_name][tuan] = 0
merchant_weekly[m_name][tuan] += record['doanh_thu']
# So sánh 2 tuần gần nhất
for merchant, tuan_data in merchant_weekly.items():
cac_tuan = sorted(tuan_data.keys())
if len(cac_tuan) >= 2:
tuan_truoc = tuan_data[cac_tuan[-2]]
tuan_nay = tuan_data[cac_tuan[-1]]
if tuan_truoc > 0:
phan_tram_thay_doi = ((tuan_nay - tuan_truoc) / tuan_truoc) * 100
if phan_tram_thay_doi < -nguong_phan_tram:
canh_bao.append({
'merchant': merchant,
'tuan_truoc': tuan_truoc,
'tuan_nay': tuan_nay,
'thay_doi': round(phan_tram_thay_doi, 1)
})
return canh_bao
alerts = detect_anomaly(du_lieu_ghep, nguong_phan_tram=40)
for alert in alerts:
print(f"🚨 {alert['merchant']}: {alert['thay_doi']}% "
f"({alert['tuan_truoc']:,.0f} → {alert['tuan_nay']:,.0f})")
# Output:
# 🚨 ShopTrangSuc99: -62.3% (45,200,000 → 17,050,000)
# 🚨 MayTinhPhuKien: -48.1% (28,400,000 → 14,740,000)🔍 Python Basics trong toàn bộ pipeline
| Concept | Sử dụng | Ví dụ |
|---|---|---|
| Function | Mỗi bước pipeline là 1 function riêng | ghep_du_lieu(), tinh_metrics_theo_nhom() |
| Dictionary | Lookup table (thay VLOOKUP), gom nhóm | merchant_lookup, nhom[key] |
| List | Lưu danh sách records, sản phẩm | du_lieu_ghep, san_pham_list |
| For loop | Duyệt qua mỗi đơn hàng, mỗi merchant | for record in du_lieu |
| If/else | Filter trạng thái, detect anomaly | if record['trang_thai'] == 'completed' |
| CSV module | Đọc/ghi file dữ liệu | csv.DictReader, csv.DictWriter |
| set() | Đếm unique products | len(set(san_pham_list)) |
| String methods | Parse ngày, format output | ngay[:7], f-string formatting |
📊 Kết quả
| Chỉ số | Trước (Google Sheets) | Sau (Python pipeline) | Cải thiện |
|---|---|---|---|
| Thời gian/báo cáo | 48 phút (thủ công) | 5 phút (chạy script) | -90% |
| Tổng thời gian/tuần | 2.4 giờ (3 báo cáo) | 15 phút | -90% |
| Dung lượng dữ liệu xử lý | 50,000 dòng (Sheets lag) | 500,000+ dòng (không giới hạn) | 10x |
| Lịch sử dữ liệu | ~4 tháng (limit ô Sheets) | Không giới hạn (file-based) | ∞ |
| Anomaly detection | Không có (nhìn bằng mắt) | Tự động alert khi giảm >40% | Mới hoàn toàn |
| Reproducibility | 0% (thủ công) | 100% (script = tài liệu) | — |
💡 Growth Story
Sau 3 tháng dùng Python pipeline, Linh có thời gian phân tích sâu hơn thay vì chỉ tổng hợp số liệu. Linh phát hiện pattern: merchants tier Gold trên Shopee có AOV cao hơn 40% so với TikTok Shop → CEO điều chỉnh pricing strategy → tăng 18% revenue Q2/2026. Insight này không thể có nếu Linh vẫn dành 7+ giờ/tuần copy-paste trên Google Sheets.
🎓 Bài học cho DA
- Google Sheets tốt cho prototype, Python tốt cho production: Khi dữ liệu > 50,000 dòng hoặc quy trình lặp > 3 lần/tuần → chuyển sang Python.
- Dictionary thay thế VLOOKUP hoàn hảo:
merchant_lookup.get(id)nhanh hơn VLOOKUP trên 100,000 dòng hàng trăm lần — và không bao giờ sai. - Function = reusable logic: Hàm
tinh_metrics_theo_nhom(du_lieu, group_field)dùng cho bất kỳ field nào — kênh bán, merchant tier, danh mục — không cần viết lại. - Script = documentation: Code Python chính là tài liệu — ai đọc cũng hiểu quy trình. Google Sheets workflow chỉ nằm trong đầu 1 người.
So sánh & Tổng hợp
| Tiêu chí | Case 1: Automate the Boring Stuff | Case 2: FPT Software | Case 3: DataMart Startup |
|---|---|---|---|
| Quy mô | 1 người, 1 báo cáo | 15 người, 50+ dự án | 2 người, 500+ merchants |
| Vấn đề chính | Báo cáo thủ công lặp lại | ETL từ 20+ nguồn đa format | Google Sheets bottleneck |
| Python concepts | CSV, function, loop | CSV + JSON, nested dict/loop | Dict lookup, if/else, functions |
| Thời gian tiết kiệm | 90% (30→3 phút) | 87.5% (16→2 giờ) | 90% (48→5 phút) |
| Dữ liệu xử lý | 5,000 dòng/ngày | 20+ nguồn, 100,000+ records | 150,000 đơn/tháng |
| Skill level cần | Beginner (1-2 tuần học) | Intermediate (team collab) | Beginner-Intermediate |
| ROI | 112.5 giờ/năm | 728 giờ/năm (~$15,000) | ~100 giờ/năm + revenue insight |
📌 Pattern chung
Cả 3 case study đều chứng minh 1 điều: Python cơ bản (data types, loops, functions, file handling) đủ để giải quyết phần lớn vấn đề dữ liệu thực tế. Bạn không cần Pandas, không cần Machine Learning, không cần framework phức tạp — chỉ cần hiểu rõ list, dict, for, def, csv, json.
Progression:
- Case 1: 1 file → 1 báo cáo (automation đơn giản)
- Case 2: 20+ files × nhiều format → 1 báo cáo tổng hợp (ETL pipeline)
- Case 3: Multi-source → metrics + anomaly detection (full analytics pipeline)
Bài tập tư duy
Câu 1: Áp dụng vào công việc hiện tại
Hãy nghĩ về công việc hiện tại (hoặc công việc mong muốn) của bạn:
- Bạn có quy trình nào lặp đi lặp lại mỗi ngày/tuần mà đang làm thủ công (Excel, Google Sheets)?
- Ước tính: mỗi lần mất bao nhiêu phút? Bao nhiêu lần/tuần?
- Nếu viết Python script, bạn cần những concepts nào (CSV reading? dictionary? loop? function?)?
- Tính ROI: tiết kiệm bao nhiêu giờ/năm?
Câu 2: Thiết kế mini pipeline
Giả sử bạn là DA tại một chuỗi cafe có 10 cửa hàng. Mỗi ngày bạn nhận file CSV giao dịch từ mỗi cửa hàng (10 files). Hãy thiết kế pipeline bằng Python cơ bản:
- Đọc 10 file CSV → gộp thành 1 list
- Tính KPI: tổng doanh thu, số đơn hàng, AOV — theo từng cửa hàng (dùng dict)
- Tìm cửa hàng có doanh thu cao nhất và thấp nhất
- Ghi kết quả ra file CSV tổng hợp
Gợi ý: Bạn cần dùng for loop (duyệt 10 files), dictionary (gom theo cửa hàng), function (tái sử dụng), csv module (đọc/ghi).
Câu 3: So sánh công cụ
So sánh 3 công cụ cho cùng 1 tác vụ — "tính tổng doanh thu theo khu vực từ file 100,000 dòng":
| Tiêu chí | Excel/Google Sheets | SQL | Python (csv + dict) |
|---|---|---|---|
| Tốc độ setup | ? | ? | ? |
| Xử lý 100K dòng | ? | ? | ? |
| Tự động chạy lại | ? | ? | ? |
| Kết hợp nhiều nguồn | ? | ? | ? |
| Sharing kết quả | ? | ? | ? |
Hãy điền và giải thích — không có công cụ nào "tốt nhất" cho mọi tình huống. Khi nào nên dùng công cụ nào?