Dự báo chuỗi thời gian là một trong những công cụ mạnh mẽ nhất để lập kế hoạch kinh doanh – và điều bất ngờ là nó lại khá đơn giản. Trong bài viết này, chúng ta sẽ cùng tìm hiểu cách dự báo doanh số dựa trên chuỗi thời gian với Prophet, một thư viện Python được thiết kế để vừa dễ dùng vừa chính xác. Phương pháp này không đòi hỏi các mô hình phức tạp hay kiến thức chi tiết về các yếu tố bên ngoài như chiến dịch marketing hay tình hình kinh tế.
Cách tiếp cận này phù hợp nhất với những môi trường doanh số tương đối ổn định, nơi mà yếu tố mùa vụ và xu hướng là nhân tố chính ảnh hưởng, còn các yếu tố bên ngoài không biến động quá lớn.
Bạn sẽ được hướng dẫn cách:
- Làm sạch và chuẩn bị dữ liệu lịch sử thô
- Khám phá các xu hướng theo tháng
- Dự báo doanh số chỉ dựa trên dữ liệu thời gian
- Thêm các yếu tố mùa vụ tùy chỉnh để nâng cao độ chính xác khi dự báo với Prophet
Bước 1: Tải và kết hợp dữ liệu doanh số
Chúng ta bắt đầu bằng việc tải nhiều file Excel, mỗi file chứa một phần dữ liệu lịch sử doanh số, để chuẩn bị cho việc dự báo doanh số với Prophet.
import pandas as pd
import numpy as np
from datetime import datetime
from prophet import Prophet
import plotly.graph_objects as go
DF2024 = pd.read_excel('/content/drive/MyDrive/D&I /Website Contents/Blogs/Data/Sales Prediction Project/DF_2024.xlsx')
DF2025_1 = pd.read_excel('/content/drive/MyDrive/D&I /Website Contents/Blogs/Data/Sales Prediction Project/DFforRCOECSJan.xlsx')
DF2025_2 = pd.read_excel('/content/drive/MyDrive/D&I /Website Contents/Blogs/Data/Sales Prediction Project/DFforRCOECSFeb.xlsx')
DF2025_3 = pd.read_excel('/content/drive/MyDrive/D&I /Website Contents/Blogs/Data/Sales Prediction Project/DFforRCOECSMar.xlsx')
DF2023 = pd.read_excel('/content/drive/MyDrive/D&I /Website Contents/Blogs/Data/Sales Prediction Project/DF_FY2023.xlsx')
Chúng ta chỉ trích xuất những cột dữ liệu cần thiết cho phân tích:
DF2024_extract = DF2024[["Sales Document", 'Document Date (Date Received/Sent)', 'Sales Organization', 'Initial Order Quantity',
'Order quantity in EB'
]]
DF2023_extract = DF2023[["Sales Document", 'Document Date (Date Received/Sent)', 'Sales Organization', 'Initial Order Quantity',
'Order quantity in EB'
]]
DF2025_1_extract = DF2025_1[["Sales Document", 'Document Date (Date Received/Sent)', 'Sales Organization', 'Initial Order Quantity',
'Order quantity in EB'
]]
DF2025_2_extract = DF2025_2[["Sales Document", 'Document Date (Date Received/Sent)', 'Sales Organization', 'Initial Order Quantity',
'Order quantity in EB'
]]
DF2025_3_extract = DF2025_3[["Sales Document", 'Document Date (Date Received/Sent)', 'Sales Organization', 'Initial Order Quantity',
'Order quantity in EB'
]]
Sau đó, chúng ta gộp các file lại thành một bộ dữ liệu hoàn chỉnh:
DF_concat = pd.concat([DF2024_extract, DF2023_extract, DF2025_1_extract, DF2025_2_extract, DF2025_3_extract], axis=0)
DF_concat.rename(columns = {'Sales Document':'Sales_Document', 'Document Date (Date Received/Sent)':'Document_Date'}, inplace = "True")
Tiếp theo, định dạng và trích xuất thông tin tháng/năm để nhóm dữ liệu theo thời gian:
DF_concat['Document_Date'] = pd.to_datetime(DF_concat['Document_Date'])
DF_concat['Document_Month'] = DF_concat['Document_Date'].dt.month
DF_concat['Document_Year'] = DF_concat['Document_Date'].dt.year
Bước 2: Nhóm và trực quan hóa xu hướng theo tháng
Bây giờ, chúng ta sẽ tổng hợp dữ liệu theo tháng và năm, đồng thời nhóm theo tổ chức bán hàng.
DF_concat_groupby= DF_concat.groupby(['Document_Month', 'Document_Year', 'Sales Organization']).agg({'Initial Order Quantity':'sum', 'Order quantity in EB':'sum', 'Sales_Document': pd.Series.nunique})
DF_concat_groupby = DF_concat_groupby.reset_index()
Hãy cùng tập trung vào Tổ chức Bán hàng tại Hồng Kông:
Dưới đây là biểu đồ thể hiện sự biến động số lượng báo cáo bán hàng theo từng tháng:
import plotly.express as px
# Group by Document_Year and Document_Month and sum Sales_Document
sub_organization = DF_concat_groupby[DF_concat_groupby['Sales Organization'] == 8601]
sales_by_month_year = sub_organization.groupby(['Document_Year', 'Document_Month'])['Sales_Document'].sum().reset_index()
# Create a new 'Month Year' column for labeling (format: Jan-2023, Feb-2023, etc.)
sales_by_month_year['Month Year'] = pd.to_datetime(
sales_by_month_year['Document_Year'].astype(str) + '-' +
sales_by_month_year['Document_Month'].astype(str) + '-01'
).dt.strftime('%b-%Y') # e.g., Jan-2023
# Sort values properly
sales_by_month_year = sales_by_month_year.sort_values(by=['Document_Year', 'Document_Month'])
# Plot interactive line chart
fig = px.line(
sales_by_month_year,
x='Month Year',
y='Sales_Document',
title='Sum of Sales Documents by Month-Year - HK',
labels={'Month Year': 'Month-Year', 'Sales_Document': 'Sum of Sales Documents'},
markers=True
)
fig.update_layout(xaxis_tickangle=-45)
fig.show()

Bước 3: Định dạng dữ liệu cho Prophet
Để dự báo doanh số với Prophet, dữ liệu cần có hai cột:
- ds: dấu thời gian (ngày tháng)
- y: giá trị cần dự đoán (doanh số)
Chúng ta sẽ chuyển đổi dữ liệu và chia thành bộ dữ liệu huấn luyện và kiểm tra:
sales_HK = DF_concat_groupby[DF_concat_groupby['Sales Organization'] == 8601]
sales_HK = sales_HK[['Document_Month', 'Document_Year', 'Sales_Document', 'Month Year']]
sales_HK_test = sales_HK[sales_HK['Document_Year'] == 2025]
sales_HK_test['ds'] = pd.to_datetime(sales_HK_test['Document_Year'].astype(str) + '-' + sales_HK_test['Document_Month'].astype(str) + '-01')
sales_HK_test = sales_HK_test.rename(columns={'Sales_Document': 'y'})
sales_HK_test = sales_HK_test[["ds", "y"]]
sales_HK_train = sales_HK[sales_HK['Document_Year'] != 2025]
sales_HK_train['ds'] = pd.to_datetime(sales_HK_train['Document_Year'].astype(str) + '-' + sales_HK_train['Document_Month'].astype(str) + '-01')
sales_HK_train = sales_HK_train.rename(columns={'Sales_Document': 'y'})
sales_HK_train = sales_HK_train[["ds", "y"]]
sales_HK_train.head()
sales_hk_all = pd.concat([sales_HK_train, sales_HK_test], axis=0)
Bước 4: Xây dựng dự báo cơ bản với Prophet
Chúng ta bắt đầu dự báo doanh số với Prophet bằng cách huấn luyện mô hình đầu tiên:
model = Prophet(yearly_seasonality=True)
model.fit(sales_HK_train)
future = model.make_future_dataframe(periods=6, freq='MS') # MS = Month Start
forecast = model.predict(future)
Hãy cùng so sánh giá trị thực tế với giá trị dự báo:
forecast_result = forecast[['ds', 'yhat']].merge(sales_hk_all[['ds', 'y']], on='ds', how='left')
# Plot actual vs forecast
fig = go.Figure()
# Actuals
fig.add_trace(go.Scatter(x=forecast_result['ds'], y=forecast_result['y'],
mode='lines+markers', name='Actual'))
# Forecast
fig.add_trace(go.Scatter(x=forecast_result['ds'], y=forecast_result['yhat'],
mode='lines+markers', name='Forecast (yhat)',
line=dict(dash='dash')))
fig.update_layout(title='Actual vs Forecast of Sales_Document',
xaxis_title='Date',
yaxis_title='Sales_Document',
xaxis_tickformat='%b-%Y')
fig.show()

Bước 5: Thêm yếu tố mùa vụ tùy chỉnh
Để cải thiện mô hình, chúng ta sẽ thêm các yếu tố mùa vụ đặc thù theo lĩnh vực kinh doanh. Ví dụ như:
- Đỉnh điểm doanh số vào tháng 12 (giai đoạn cao điểm cuối năm)
december_peak = pd.DataFrame({
'holiday': 'december_peak',
'ds': pd.date_range(start='2023-12-01', end='2025-12-01', freq='12MS'), # Dec 1 each year
'lower_window': 0,
'upper_window': 0
})
model_season = Prophet(
yearly_seasonality=True,
holidays=december_peak
)
model_season.add_country_holidays(country_name='HK')
model_season.fit(sales_HK_train)
future_season = model_season.make_future_dataframe(periods=6, freq='MS') # 6 future months
forecast_season = model_season.predict(future_season)
Bước 6: Vẽ biểu đồ dự báo cuối cùng
Hãy cùng so sánh kết quả dự báo đã được cải thiện:
forecast_season_result = forecast_season[['ds', 'yhat']].merge(sales_hk_all[['ds', 'y']], on='ds', how='left')
# Plot actual vs forecast_season
fig = go.Figure()
# Actuals
fig.add_trace(go.Scatter(x=forecast_season_result['ds'], y=forecast_season_result['y'],
mode='lines+markers', name='Actual'))
# forecast_season
fig.add_trace(go.Scatter(x=forecast_season_result['ds'], y=forecast_season_result['yhat'],
mode='lines+markers', name='Forecast (yhat)',
line=dict(dash='dash')))
fig.update_layout(title='Actual vs Forecast of Sales_Document',
xaxis_title='Date',
yaxis_title='Sales_Document',
xaxis_tickformat='%b-%Y')
fig.show()

Để đánh giá độ chính xác và tính thực tiễn của mô hình Prophet đã điều chỉnh, tôi đã so sánh kết quả của nó với hai phương pháp dự báo khác: công cụ dự báo tích hợp sẵn trong Excel và mô hình SARIMA.
Dự báo của Excel, mặc dù nhanh và dễ sử dụng, lại có xu hướng dự báo quá cao so với doanh số thực tế trong giai đoạn giữa đến cuối năm 2025 – chủ yếu do nó dựa nhiều vào tính mùa vụ lịch sử mà không kịp thích ứng với xu hướng giảm doanh số gần đây.

Mô hình SARIMA thể hiện tốt hơn ở điểm này, khi nắm bắt chính xác hơn xu hướng giảm vào đầu năm 2025 và cung cấp các khoảng tin cậy giúp lập kế hoạch có tính đến rủi ro. Tuy nhiên, mô hình này vẫn có xu hướng dự báo thấp hơn thực tế trong một số tháng và có thể khó tiếp cận hơn với những người không chuyên về kỹ thuật.

In contrast, the adjusted Prophet model struck the best balance: it incorporated both trend shifts and seasonal effects, including holidays, and tracked actual 2025 sales more closely. This highlights how tailored, domain-aware forecasting models can outperform generic tools, especially in dynamic retail environments.
Ngược lại, mô hình Prophet đã điều chỉnh đạt được sự cân bằng tốt nhất khi tích hợp cả sự thay đổi xu hướng và hiệu ứng mùa vụ (bao gồm cả ngày lễ), đồng thời bám sát hơn vào doanh số thực tế năm 2025. Điều này cho thấy các mô hình dự báo được tùy chỉnh theo đặc thù lĩnh vực có thể vượt trội hơn các công cụ chung chung, đặc biệt trong môi trường bán lẻ biến động mạnh
Tổng kết
Toàn bộ phương pháp này dựa trên dự đoán chuỗi thời gian, tức là chúng ta hoàn toàn dựa vào các mẫu dữ liệu trong quá khứ về thời gian và khối lượng – không cần đến dữ liệu chi tiết về sản phẩm, giá cả, khuyến mãi hay kênh phân phối.
Chính vì vậy, dự báo doanh số với Prophet rất phù hợp cho:
- Môi trường bán lẻ hoặc B2B có các mẫu đặt hàng đều đặn
- Dự báo doanh số trong những trường hợp các sự kiện bên ngoài (quảng cáo, biến động kinh tế vĩ mô, v.v.) không ảnh hưởng lớn
- Doanh nghiệp muốn đạt được kết quả nhanh chóng từ dự báo mà không cần xây dựng các mô hình phức tạp
Tất nhiên, phương pháp này sẽ không bắt được các yếu tố như chiến dịch marketing đột ngột, ra mắt sản phẩm mới hay sự bùng nổ nhu cầu bất ngờ. Nhưng khi dòng doanh số của bạn khá ổn định và có tính mùa vụ rõ ràng, các mô hình dựa trên thời gian như Prophet chính là lựa chọn hoàn hảo.
Tham khảo thêm thông tin chi tiết về Prophet tại website chính thức.