Lập trình
xử lý dữ liệu

Học kì 1, năm học 2026–2027

Viện Trí tuệ nhân tạo, Trường ĐH Công nghệ, ĐHQGHN

Bài 6
Kết nối & truy xuất
dữ liệu ngoài

Đọc file, gọi API và truy vấn SQL.

Bài trước

Đã biết chọn hàng, tính theo nhóm và ghép bảng bằng pandas.

Bài này đưa dữ liệu từ file, API và cơ sở dữ liệu vào các phép xử lý đó.

Tổng quan

  1. Đọc và lưu file
  2. Lấy dữ liệu qua API
  3. SQL và DuckDB

1.
Đọc và lưu file

Đọc đúng dữ liệu và lưu bảng để dùng lại.

CSV không lưu kiểu dữ liệu

Giá giả lập (USD/đêm); ? là chưa có giá.

File gốc


id,khu,gia
001,A,100
002,B,80
003,A,200
004,B,120
005,A,?

Đọc bằng pandas

Mã 001 thành 1; cột gia vẫn là chuỗi vì có ?.

Khai báo cách đọc

dtype đặt kiểu cột; na_values khai báo chuỗi nào là thiếu.

Mặc định pandas coi các chuỗi như NA, null, N/A và ô trống là thiếu; keep_default_na=False tắt danh sách này.

Bài tập 1: Đọc bảng giá

File gia_theo_khu.csv (giả lập, USD/đêm):


khu,gia
NA,100
TB,80
NA,
TB,0

NA là mã khu hợp lệ; ô trống là chưa có giá; 0 là giá đã ghi nhận.

Viết mã tính giá trung bình từng khu từ file này.

Lưu bảng để dùng lại

Bảng đã đọc đúng mã, kiểu cột và giá trị thiếu; cần lưu lại để lần sau không phải khai báo lại.

Parquet là định dạng file nhị phân dành cho dữ liệu dạng bảng.

Nhu cầuCách Parquet lưu dữ liệu
Giữ kiểu cột đã xác địnhLưu kiểu cùng dữ liệu
Chỉ đọc các cột cần dùngTổ chức dữ liệu theo cột
Giảm dung lượng lưu trữNén dữ liệu theo từng cột

Lưu bảng bằng Parquet

Lưu df đã đọc đúng ở đầu mục, rồi đọc lại:

Mã 001 vẫn là chuỗi; gia vẫn là số.

Giữ file gốc trong raw/, ghi kết quả vào processed/.

Áp dụng cho dữ liệu Santiago

Bản CSV rút gọn ngày 29/06/2026: 19 cột; price đã là số, đơn vị CLP/đêm.

id là mã, không dùng để tính: đọc thành chuỗi. usecols chỉ đọc bốn cột cần dùng.

File Parquet này dùng lại ở mục 3.

2.
Lấy dữ liệu qua API

Tự động lấy dữ liệu từ dịch vụ theo yêu cầu.

Tự động lấy dữ liệu từ dịch vụ

Dữ liệu nằm trên hệ thống của nhà cung cấp và thay đổi theo thời gian, như dự báo thời tiết.

  • Chương trình cần cập nhật dữ liệu tự động.
  • Mỗi lần chỉ cần một phần dữ liệu: một địa điểm, vài ngày tới, một mã sản phẩm.

Nhà cung cấp cần quy định cách chương trình gửi yêu cầu và nhận đúng phần dữ liệu đó.

Trao đổi dữ liệu qua API

API (giao diện lập trình ứng dụng) quy định cách các chương trình tương tác với nhau.

Web API trao đổi yêu cầu và phản hồi qua HTTP, giao thức truyền dữ liệu trên web.

Chương trình
Cần lấy dữ liệu
Yêu cầuĐịa chỉ, tham số
Phản hồiMã trạng thái, dữ liệu
Dịch vụ
Xử lý yêu cầu

Ví dụ: lấy dự báo thời tiết

Tra tài liệu Open-Meteo để lấy endpoint (địa chỉ nhận yêu cầu):


https://api.open-meteo.com/v1/forecast
Yêu cầuTham sốGiá trị
Vị trí Santiagolatitude, longitude-33.45, -70.66
Nhiệt độ tối đa ngàydailytemperature_2m_max
Ba ngày kể từ hôm nayforecast_days3
Ngày theo giờ SantiagotimezoneAmerica/Santiago

Gửi yêu cầu bằng Python

requests.get() gửi yêu cầu HTTP; params là các tham số ở slide trước.

r chứa phản hồi; mã 200 cho biết yêu cầu thành công.

Đọc dữ liệu trong phản hồi

Open-Meteo trả nội dung dạng JSON: văn bản chứa các cặp tên–giá trị và mảng.

raise_for_status() báo lỗi HTTP trước khi đọc dữ liệu.

json() chuyển đối tượng JSON thành dict, mảng thành list: ở đây là dict có 9 khoá.

Chọn phần JSON để tạo bảng

Bản rút gọn còn ba khoá cần dùng; số liệu giả lập:


{
  "timezone": "America/Santiago",
  "daily_units": {"temperature_2m_max": "°C"},
  "daily": {
    "time": ["2026-10-01", "2026-10-02", "2026-10-03"],
    "temperature_2m_max": [22.0, 26.0, 24.0]
  }
}

Hai danh sách trong daily khớp theo vị trí, mỗi vị trí một ngày.

daily_units cho biết đơn vị; timezone cho biết múi giờ.

Tạo bảng theo ngày

mau là dict đọc từ JSON giả lập ở slide trước.

Mỗi hàng là một ngày; nhiệt độ tính bằng °C.

Giữ lại bản dự báo đã lấy

Gọi lại API có thể nhận được dự báo khác. Lưu nguyên phản hồi để phân tích lại cùng dữ liệu.

Đọc lại file này lúc nào cũng ra đúng bảng trên.

Bài tập 2: Lọc ngày nóng

Phản hồi giả lập:


{
  "timezone": "America/Phoenix",
  "daily_units": {"temperature_2m_max": "°F"},
  "daily": {
    "time": ["2026-10-01", "2026-10-02", "2026-10-03"],
    "temperature_2m_max": [95, 100, 88]
  }
}

Đổi đơn vị: °C = (°F − 32) / 1,8.

Lấy các ngày có nhiệt độ tối đa từ 35°C trở lên.

3.
SQL và DuckDB

Truy vấn dữ liệu tại nguồn, lấy kết quả về phân tích.

Lấy kết quả từ cơ sở dữ liệu

Bảng chỗ ở nằm trong cơ sở dữ liệu (CSDL) trên máy chủ; báo cáo chỉ cần giá trung bình từng khu.

pandas
CSDL
Lưu bảng
chỗ ở
cả bảng
Python
Nạp vào RAM
rồi groupby
SQL
CSDL
Tính theo
truy vấn SQL
một hàng mỗi khu
Python
Nhận
bảng kết quả

SQL mô tả kết quả cần lấy; hệ quản trị CSDL tính ngay tại nơi lưu dữ liệu.

Dùng DuckDB trong Python

Dữ liệu của bài là file và DataFrame trên máy; cần chạy SQL ngay trong Python.

DuckDB là hệ quản trị cơ sở dữ liệu dành cho phân tích:

  • Chạy cùng chương trình, không cần máy chủ riêng.
  • Truy vấn trực tiếp file CSV, Parquet hoặc DataFrame.
  • Lấy kết quả về pandas bằng .df().

Lọc hàng bằng SQL

duckdb.sql() chạy câu SQL. FROM df là DataFrame df của mục 1: DuckDB tìm bảng theo tên biến Python.

WHERE lọc hàng; ORDER BY … DESC sắp xếp giảm dần.

Tính theo nhóm bằng SQL

Khu A có ba chỗ ở nhưng chỉ hai giá đã biết.

NaN của pandas thành NULL trong SQL; AVG và COUNT(gia) bỏ qua NULL.

Lọc hàng và lọc nhóm

Giá trong df: khu A có 100, 200, NaN; khu B có 80, 120.

Trung bình các chỗ ở giá từ 150


SELECT khu, AVG(gia) AS tb
FROM df
WHERE gia >= 150
GROUP BY khu
  1. Lọc hàng: còn (A, 200); B hết hàng
  2. Tính theo khu: A 200

Các khu có giá trung bình từ 150


SELECT khu, AVG(gia) AS tb
FROM df
GROUP BY khu
HAVING AVG(gia) >= 150
  1. Tính theo khu: A 150, B 100
  2. Lọc nhóm: còn A 150; B bị loại

WHERE lọc hàng trước khi tính; HAVING lọc nhóm sau khi tính.

Bài tập 3: Đếm giá thiếu

idkhugia (USD/đêm)
001A100
002B80
003A200
004B120
005ANaN

Viết một truy vấn SQL đếm số chỗ ở chưa có giá của từng khu, kể cả khu không thiếu giá.

Ghép bảng bằng SQL

Bảng khu_vung có một hàng: khu A thuộc vùng Bắc.

LEFT JOIN giữ cả hai chỗ ở khu B dù chưa có vùng tương ứng.

Truy vấn file Parquet

Truy vấn thẳng file đã lưu; DuckDB chỉ đọc hai cột cần dùng.

Santiago 29/06/2026, CLP/đêm; khớp với groupby của pandas.

Trung vị cao nhất (Hotel room) chỉ dựa trên 56 giá.

Chọn SQL hay pandas?

Cùng lọc, nhóm, ghép được; khác ở nơi tính và cách viết.

SQLpandas
Nơi tínhTại CSDL, file; chỉ kết quả về PythonTrong RAM, sau khi nạp cả bảng
Cách viếtMô tả kết quả; hệ thống tự chọn cách đọc, cách tínhTừng bước; tự chọn cột cần đọc
Dùng ởHầu hết hệ quản trị CSDLChương trình Python
Hợp vớiLấy, lọc, gộp bảng lớn tại nguồnPhân tích tiếp, hàm tuỳ ý, vẽ biểu đồ

Thường dùng cả hai: SQL lấy, gộp tại nguồn; pandas xử lý tiếp.

Tổng kết

Nhu cầuCông cụ trong bài
Đọc bảng văn bản từ nguồnCSV: khai báo kiểu và giá trị thiếu
Lưu bảng đã xử lý để dùng lạiParquet: giữ kiểu, đọc theo cột
Lấy dữ liệu từ dịch vụ theo yêu cầuAPI: gửi yêu cầu, đọc phản hồi
Tính tại nơi lưu, chỉ lấy kết quả vềSQL; DuckDB thực hiện truy vấn

Làm việc với AI thì sao?

🤖 Làm việc với AI
AI làm tốtViết mã đọc file, gọi API và truy vấn SQL khi có file mẫu, cấu trúc JSON và quy ước dữ liệu.
AI hay saiBịa tên tham số API, đoán cấu trúc JSON, coi mã là số, bỏ qua đơn vị hoặc chọn sai tập hàng để tính.

Kiểm chứng thế nào?

  • Đối chiếu tên tham số với tài liệu API; xem r.url để biết yêu cầu đã gửi.
  • Tính tay trên bảng nhỏ có mã đặc biệt và giá trị thiếu.
  • Đối chiếu SQL với pandas trên cùng bản dữ liệu đã lưu.

Đọc thêm