
Chuyển đổi bất kỳ tệp CSV nào thành Báo cáo điều hành bằng Python và AI
Tìm hiểu cách triển khai quy trình lặp lại để làm sạch tệp CSV, tìm ra câu chuyện và viết báo cáo.
Chuyển đổi bất kỳ tệp CSV nào thành báo cáo điều hành bằng Python và AI - KDnuggets
**Vượt xa phân tích thủ công**
Mọi nhà phân tích đều đã từng thực hiện công việc này bằng tay. Một tệp CSV đến hộp thư đến của bạn, ai đó hỏi "chúng ta đã làm được gì", và bạn dành cả buổi chiều để làm sạch các cột, xây dựng một vài biểu đồ và gõ ra ý nghĩa của chúng.
Chúng ta có thể tự động hóa hầu hết các công việc đó. Trong hướng dẫn này, chúng ta sẽ xây dựng một quy trình nhỏ bằng Python để lấy một tệp CSV bán hàng thô, làm sạch nó, chạy các con số, vẽ biểu đồ và yêu cầu AI soạn thảo các thông tin chi tiết. AI ở đây là Claude Opus 4.8. Mô hình này viết bản nháp đầu tiên của câu chuyện trong vài giây. Chúng ta vẫn quyết định điều gì là đúng.
Trước tất cả những điều đó, báo cáo cần một câu hỏi. Câu hỏi của chúng ta là: chúng ta đã giữ được bao nhiêu doanh thu trong năm tuần này, và phần còn lại đã đi đâu? Mỗi bước dưới đây trả lời một phần của câu hỏi đó. Bước làm sạch quyết định những hàng nào được tính là tiền. Các tổng hợp cho biết chúng ta đã mất nó ở đâu và khi nào. Bước AI biến những con số đó thành một bản tóm tắt mà một giám đốc điều hành sẽ đọc.
Tất cả mã đều ở bên dưới để bạn có thể tái tạo nó, và các bước tương tự cho hầu hết mọi tập dữ liệu:
CSV → làm sạch → khám phá → biểu đồ → thông tin chi tiết AI → khuyến nghị → báo cáo
**Dữ liệu**
Chúng ta sử dụng tệp product_sales.csv, chứa 45 hàng giao dịch. Đây là một tập dữ liệu được sử dụng trong câu hỏi phỏng vấn này. Lưu ý rằng trong bài viết này, chúng ta không giải quyết vấn đề gốc. Mỗi hàng là một sự kiện thanh toán: một giao dịch mua hoặc hoàn tiền, với quốc gia, ngày, số tiền và trạng thái.
Dưới đây là bản xem trước bảng thô.
transaction_id
product_id
country
transaction_date
amount
status
type
original_transaction_id
TXN-10001
PROD-2891
US
2025-04-15
449.99
completed
purchase
TXN-10002
PROD-2891
US
2025-04-15
449.99
completed
purchase
TXN-10003
PROD-2891
CA
2025-04-15
449.99
completed
purchase
TXN-10004
PROD-2891
US
2025-04-17
449.99
completed
purchase
…
…
…
…
…
…
…
…
TXN-10045
PROD-2891
US
2025-05-11
-449.99
completed
refund
TXN-10044
Hai điều đã nổi bật. Các khoản hoàn tiền được lưu trữ dưới dạng số tiền âm, và không phải mọi hàng đều là một giao dịch bán hàng đã hoàn tất. Cả hai đều quan trọng đối với các con số chúng ta báo cáo.
Chúng ta tải nó bằng Pandas:
import pandas as pd
df = pd.read_csv("product_sales.csv")
**Làm sạch dữ liệu**
Bước làm sạch quyết định liệu tổng số có đúng hay không. Ba hàng đang chờ xử lý hoặc thất bại, vì vậy chúng chưa phải là tiền. Chúng ta sửa các loại và chỉ giữ lại các giao dịch đã hoàn tất:
df["transaction_date"] = pd.to_datetime(df["transaction_date"])
df["amount"] = pd.to_numeric(df["amount"], errors="coerce")
# Các giao dịch đang chờ xử lý và thất bại chưa phải là doanh thu.
settled = df[df["status"] == "completed"].copy()
settled["is_refund"] = settled["type"].eq("refund")
Điều này loại bỏ 3 trong số 45 hàng và còn lại 42 giao dịch đã hoàn tất. Nếu báo cáo trực tiếp từ tệp thô, chúng ta sẽ tính một khoản thanh toán không thành công là một giao dịch bán hàng.
# Phân tích khám phá
Phần đầu tiên của câu hỏi: chúng ta đã giữ lại được bao nhiêu? Tách các giao dịch mua khỏi các khoản hoàn tiền và các số liệu chính sẽ xuất hiện. Các khoản hoàn tiền đã là số âm, vì vậy doanh thu thuần chỉ là tổng của cột số tiền.
gross = settled.loc[~settled["is_refund"], "amount"].sum()
refunds = settled.loc[settled["is_refund"], "amount"].sum() # negative
net = settled["amount"].sum()
refund_rate = -refunds / gross
print(f"gross {gross:,.0f}")
print(f"refunds {refunds:,.0f}")
print(f"net {net:,.0f}")
print(f"refund rate (value) {refund_rate:.0%}")
Kết quả:
gross 12.975
refunds -4.875
net 8.100
refund rate (value) 38%
Đây là toàn bộ câu chuyện trong bốn dòng. Chúng ta đã bán được khoảng 13.000 USD và hoàn lại 4.875 USD, do đó doanh thu thuần là 8.100 USD. Tỷ lệ hoàn tiền 38% là cao, và đây là loại số liệu không bao giờ xuất hiện nếu chỉ cộng các số dương.
Điều đó cho biết tổng số. Nửa sau của câu hỏi là tiền đã đi đâu, vì vậy chúng ta phân tích dữ liệu theo hai cách. Theo quốc gia, để xem thị trường nào đóng góp vào con số thuần:
by_country = (settled.groupby("country")["amount"]
.agg(net_revenue="sum", transactions="count")
.sort_values("net_revenue", ascending=False))
print(by_country)
country
net_revenue
transactions
US
7199.84
38
GB
449.99
1
MX
449.99
1
CA
0.00
2
Canada là một bất ngờ. Hai đơn hàng đã hoàn tất, cả hai đều được hoàn tiền, vì vậy doanh thu thuần của quốc gia này chính xác bằng 0.
Sau đó theo tuần, tách các giao dịch mua khỏi các khoản hoàn tiền:
settled["week"] = settled["transaction_date"].dt.to_period("W").dt.start_time
weekly = settled.pivot_table(index="week", columns="is_refund",
values="amount", aggfunc="sum").fillna(0)
weekly.columns = ["purchases", "refunds"]
weekly["net"] = weekly.sum(axis=1)
print(weekly)
week
purchases
refunds
net
2025-04-14
4649.89
-449.99
4199.90
2025-04-21
4274.90
-299.99
3974.91
2025-04-28
3599.92
0.00
3599.92
2025-05-05
449.99
-1799.96
-1349.97
2025-05-12
0.00
-1424.96
-1424.96
2025-05-19
0.00
-899.98
-899.98
Ba tuần đầu tiên có doanh thu thuần dương. Ba tuần cuối cùng có doanh thu thuần âm. Các giao dịch mua dừng lại vào đầu tháng 5 trong khi các khoản hoàn tiền vẫn tiếp tục.
Một con số nữa giải thích khoảng cách này. Sử dụng original_transaction_id, chúng ta đo lường thời gian sau khi mua hàng mà mỗi khoản hoàn tiền được thực hiện.
purch_dates = (settled.loc[~settled["is_refund"], ["transaction_id", "transaction_date"]]
.set_index("transaction_id")["transaction_date"])
ref = settled[settled["is_refund"]].copy()
ref["lag_day
Nguồn tin: KDnuggets — Tác giả: Nate Rosidi. Bản dịch tiếng Việt do AI thực hiện, có thể có sai sót.