Tin học - Bài 23: Làm sạch dữ liệu (Khoa học Dữ liệu & ML)

🔬 Bài 23: Làm sạch dữ liệu — bước không ai được bỏ qua

🎯 Sau bài này bạn sẽ: phát hiện ô thiếu bằng isna(), xử lý bằng dropna() hoặc fillna(), đổi kiểu với astype(), và bỏ trùng bằng drop_duplicates() — ngay trên trình duyệt.

💡 Ghi nhớ: Trong thực tế, dân phân tích dữ liệu thường dành phần lớn thời gian cho việc làm sạch, chứ không phải chạy mô hình. "Rác vào thì rác ra".

Dữ liệu BẨN Dữ liệu SẠCH tendiemtuoi An8.511 BinhNaN12 Chi9.2"11" Chi9.211 ↑ ô trống (NaN) sai kiểu ("11") hàng trùng làm sạch tendiemtuoi An8.511 Binh8.212 Chi9.211 đầy NaN, đổi kiểu, bỏ trùng "Rác vào thì rác ra" — dữ liệu bẩn sẽ làm mọi kết quả sai theo.
Làm sạch = xử lý ô thiếu (NaN), sửa sai kiểu, và bỏ hàng trùng.

1. Ô thiếu (NaN) — phát hiện trước đã

🟢 Lớp A · Trực giác

Trong bảng, ô thiếu là những chỗ bị bỏ trống — pandas gọi chúng là NaN (Not a Number). Nếu bạn cứ tính trung bình khi còn ô trống, kết quả có thể sai. Vì vậy việc đầu tiên là đếm xem thiếu bao nhiêu.

🔵 Lớp B · Cơ chế

df.isna() trả về bảng True/False (True = ô thiếu). Cộng dồn lại bằng df.isna().sum() cho ta số ô thiếu mỗi cột. Đây cũng là vector-hóa: pandas kiểm tra cả bảng cùng lúc.

# dem so o thieu moi cot
print(df.isna().sum())
🟣 Lớp C · Nghiên cứu

Không phải ô thiếu nào cũng giống nhau: thiếu ngẫu nhiên hay thiếu có hệ thống (ví dụ: cảm biến hỏng luôn thiếu ở nhiệt độ cao)? Cách bạn xử lý có thể đưa thêm thiên lệch (bias) vào dữ liệu, nên luôn ghi lại mình đã làm gì.

2. Bỏ hoặc điền ô thiếu

Gặp ô thiếu: bỏ hay điền? gốc 8.5 NaN 9.2 dropna() bỏ cả hàng thiếu 8.5 9.2 mất 1 hàng dữ liệu fillna(TB) điền giá trị thay thế 8.5 8.85 9.2 giữ số hàng, nhưng "đoán" Không có lựa chọn nào luôn đúng — phải cân nhắc theo bài toán.
dropna bỏ hàng thiếu; fillna điền giá trị thay thế. Mỗi cách có cái giá của nó.
🟢 Lớp A · Trực giác

Hai lựa chọn chính: bỏ những hàng thiếu (dropna) — gọn gàng nhưng mất dữ liệu; hoặc điền giá trị thay thế (fillna), thường là trung bình hoặc giá trị hay gặp nhất — giữ được số hàng nhưng là "đoán".

# cach 1: bo hang co o thieu
sach = df.dropna()
# cach 2: dien bang diem trung binh
tb = df["diem"].mean()
df["diem"] = df["diem"].fillna(tb)
🔵 Lớp B · Cơ chế

fillna không sửa bảng gốc trừ khi bạn gán lại (df["diem"] = ...) hoặc dùng inplace=True. Nhiều lỗi "sửa mà không thấy đổi" là do quên gán lại kết quả.

3. Sai kiểu và hàng trùng

🟢 Lớp A · Trực giác

Đôi khi số bị lưu thành chữ (ví dụ "11" thay vì 11) nên không tính toán được — ta dùng astype để đổi về số. Còn khi có hàng bị lặp lại y hệt, drop_duplicates giữ lại một bản.

🟣 Lớp C · Nghiên cứu

Hàng trùng rất nguy hiểm: nếu một mẫu bị lặp, mô hình sẽ "học thuộc" mẫu đó nhiều hơn, làm sai kết quả đánh giá. Đây là một dạng rò rỉ dữ liệu ta sẽ học kỹ ở Chặng 8.

# doi cot tuoi ve so nguyen
df["tuoi"] = df["tuoi"].astype(int)
# bo hang trung lap
df = df.drop_duplicates()

4. Bảng ghi nhớ: công cụ làm sạch

ViếtÝ nghĩa
df.isna().sum()Đếm số ô thiếu mỗi cột
df.dropna()Bỏ các hàng có ô thiếu
df["c"].fillna(x)Điền ô thiếu bằng giá trị x
df["c"].astype(int)Đổi kiểu dữ liệu của cột
df.drop_duplicates()Bỏ các hàng trùng lặp
df.dtypesXem kiểu dữ liệu từng cột

✎ Kiểm tra nhanh (5 câu)

1. Trong pandas, một ô bị bỏ trống (thiếu dữ liệu) thường hiển là:

NaN = Not a Number, ký hiệu ô thiếu. Lưu ý NaN khác với số 0.

2. Để đếm xem mỗi cột thiếu bao nhiêu ô, ta dùng:

isna() cho bảng True/False, sum() cộng True (=1) theo từng cột.

3. Viết df.dropna() sẽ làm gì?

dropna = drop N/A: loại bỏ hàng có giá trị thiếu.

4. Cột "tuoi" đang lưu dưới dạng chữ (ví dụ "11"). Để đổi về số nguyên, ta viết:

astype(int) đổi kiểu của cả cột về số nguyên.

5. Có hai hàng giống hệt nhau trong bảng. Cách gọn gàng nhất để chỉ giữ lại một bản là:

drop_duplicates() bỏ hàng trùng, giữ lại bản đầu tiên.

💻 Thực hành: làm sạch dữ liệu thật

🔬 Phòng thí nghiệm làm sạch. Bấm ▶ Khởi động Python để nạp pandas, rồi ▶ Chạy. Bảng bên dưới có ô thiếu, sai kiểu và hàng trùng — hãy xem từng bước dọn dẹp.

🔌 Python chưa khởi động. Bấm "Khởi động Python" để bắt đầu.

(kết quả sẽ hiện ở đây sau khi chạy)
💡 Thử thách: Thay vì fillna(mean), hãy thử dropna() và xem bảng còn lại mấy hàng. Bạn thích cách nào hơn cho bộ dữ liệu nhỏ này?