Bộ dữ liệu “Orders_Sales_Data” là tập hợp toàn diện các giao dịch và thông tin khách hàng, được thu thập nhằm mục đích phân tích chuyên sâu hiệu suất bán hàng và hành vi mua sắm trong một khoảng thời gian cụ thể. Đây là nền tảng để đánh giá chiến lược kinh doanh, tối ưu hóa danh mục sản phẩm và đưa ra quyết định dựa trên dữ liệu.Phân tích bộ dữ liệu trên giúp các nhà đầu tư lựa chọn danh mục hàng hóa nên đầu tư mạnh và ngược lại.
# Đọc dữ liệu
data <- read.csv("C:/Users/adminn/Downloads/Sales_Orders_Data.csv", header = TRUE)
# Kiểm tra cấu trúc cơ bản của data
cat("=== THÔNG TIN CƠ BẢN VỀ BỘ DỮ LIỆU ===\n")## === THÔNG TIN CƠ BẢN VỀ BỘ DỮ LIỆU ===
## Kích thước bộ dữ liệu: 1048575 11
## Xem vài dòng đầu:
## Order_ID Customer_ID Customer_Type Product Category
## 1 ORD1 CUS1496 B2B Vio Wasser Water
## 2 ORD1 CUS1496 B2B Evian Water
## 3 ORD1 CUS1496 B2B Sprite Soft Drinks
## 4 ORD1 CUS1496 B2B Rauch Multivitamin Juices
## 5 ORD1 CUS1496 B2B Gerolsteiner Water
## 6 ORD2 CUS2847 B2C Sauvignon Blanc Alcoholic Beverages
## Unit_Price Quantity Discount Total_Price Region Order_Date
## 1 1.66 53 0.10 79.18 Baden-Württemberg 23/08/2023
## 2 1.56 90 0.10 126.36 Baden-Württemberg 23/08/2023
## 3 1.17 73 0.05 81.14 Baden-Württemberg 23/08/2023
## 4 3.22 59 0.10 170.98 Baden-Württemberg 23/08/2023
## 5 0.87 35 0.10 27.40 Baden-Württemberg 23/08/2023
## 6 9.09 2 0.00 18.18 Schleswig-Holstein 16/03/2023
## Xem vài dòng cuối:
## Order_ID Customer_ID Customer_Type Product Category
## 1048570 ORD349192 CUS25 B2C Havana Club Alcoholic Beverages
## 1048571 ORD349192 CUS25 B2C Bacardi Alcoholic Beverages
## 1048572 ORD349192 CUS25 B2C Fritz-Kola Soft Drinks
## 1048573 ORD349193 CUS2035 B2C Volvic Touch Water
## 1048574 ORD349193 CUS2035 B2C Vittel Water
## 1048575 ORD349193 CUS2035 B2C Fanta Soft Drinks
## Unit_Price Quantity Discount Total_Price Region Order_Date
## 1048570 12.96 9 0 116.64 Niedersachsen 27/08/2022
## 1048571 13.84 3 0 41.52 Niedersachsen 27/08/2022
## 1048572 2.05 2 0 4.10 Niedersachsen 27/08/2022
## 1048573 1.46 11 0 16.06 Sachsen-Anhalt 05/11/2023
## 1048574 0.59 2 0 1.18 Sachsen-Anhalt 05/11/2023
## 1048575 1.23 15 0 18.45 Sachsen-Anhalt 05/11/2023
## Số quan sát (dòng): 1048575
## Tên các biến: Order_ID Customer_ID Customer_Type Product Category Unit_Price Quantity Discount Total_Price Region Order_Date
## === CẤU TRÚC DỮ LIỆU ===
## 'data.frame': 1048575 obs. of 11 variables:
## $ Order_ID : chr "ORD1" "ORD1" "ORD1" "ORD1" ...
## $ Customer_ID : chr "CUS1496" "CUS1496" "CUS1496" "CUS1496" ...
## $ Customer_Type: chr "B2B" "B2B" "B2B" "B2B" ...
## $ Product : chr "Vio Wasser" "Evian" "Sprite" "Rauch Multivitamin" ...
## $ Category : chr "Water" "Water" "Soft Drinks" "Juices" ...
## $ Unit_Price : num 1.66 1.56 1.17 3.22 0.87 9.09 2.14 0.43 1.21 1.38 ...
## $ Quantity : int 53 90 73 59 35 2 44 13 92 3 ...
## $ Discount : num 0.1 0.1 0.05 0.1 0.1 0 0.1 0.05 0.1 0.05 ...
## $ Total_Price : num 79.2 126.4 81.1 171 27.4 ...
## $ Region : chr "Baden-Württemberg" "Baden-Württemberg" "Baden-Württemberg" "Baden-Württemberg" ...
## $ Order_Date : chr "23/08/2023" "23/08/2023" "23/08/2023" "23/08/2023" ...
## Order_ID Customer_ID Customer_Type Product
## Length:1048575 Length:1048575 Length:1048575 Length:1048575
## Class :character Class :character Class :character Class :character
## Mode :character Mode :character Mode :character Mode :character
##
##
##
## Category Unit_Price Quantity Discount
## Length:1048575 Min. : 0.320 Min. : 1.00 Min. :0.00000
## Class :character 1st Qu.: 1.050 1st Qu.: 6.00 1st Qu.:0.00000
## Mode :character Median : 1.750 Median : 11.00 Median :0.00000
## Mean : 5.847 Mean : 23.14 Mean :0.02973
## 3rd Qu.: 3.210 3rd Qu.: 30.00 3rd Qu.:0.05000
## Max. :160.440 Max. :100.00 Max. :0.15000
## Total_Price Region Order_Date
## Min. : 0.30 Length:1048575 Length:1048575
## 1st Qu.: 8.40 Class :character Class :character
## Median : 21.14 Mode :character Mode :character
## Mean : 130.98
## 3rd Qu.: 69.77
## Max. :12682.78
## Các biến định tính: 4
## Các biến định lượng: 7
library(knitr)
thong_tin_bien <- data.frame(
"Tên Biến" = c("Order_ID", "Customer_ID", "Customer_Type", "Product",
"Category", "Unit_Price", "Quantity", "Discount",
"Total_Price", "Region", "Order_Date"),
"Mô Tả" = c(
"Mã đơn hàng (định danh duy nhất cho mỗi đơn hàng)",
"Mã khách hàng (định danh khách hàng)",
"Phân loại khách hàng (B2B - Doanh nghiệp/B2C - Cá nhân)",
"Tên sản phẩm",
"Danh mục sản phẩm",
"Đơn giá sản phẩm",
"Số lượng sản phẩm trong đơn hàng",
"Tỷ lệ chiết khấu áp dụng (%)",
"Tổng giá trị đơn hàng (sau chiết khấu)",
"Khu vực địa lý",
"Ngày đặt hàng"
)
)
cat("=== Ý NGHĨA CÁC BIẾN TRONG DATASET ===\n")## === Ý NGHĨA CÁC BIẾN TRONG DATASET ===
| Tên.Biến | Mô.Tả |
|---|---|
| Order_ID | Mã đơn hàng (định danh duy nhất cho mỗi đơn hàng) |
| Customer_ID | Mã khách hàng (định danh khách hàng) |
| Customer_Type | Phân loại khách hàng (B2B - Doanh nghiệp/B2C - Cá nhân) |
| Product | Tên sản phẩm |
| Category | Danh mục sản phẩm |
| Unit_Price | Đơn giá sản phẩm |
| Quantity | Số lượng sản phẩm trong đơn hàng |
| Discount | Tỷ lệ chiết khấu áp dụng (%) |
| Total_Price | Tổng giá trị đơn hàng (sau chiết khấu) |
| Region | Khu vực địa lý |
| Order_Date | Ngày đặt hàng |
GIẢI THÍCH PHẦN 2:
Đoạn code R đầu tiên thực hiện các bước kiểm tra cơ bản để đánh giá chất lượng và quy mô của bộ dữ liệu. Kết quả từ các lệnh nrow, ncol, sum(duplicated(data)) và sapply(…) cho thấy:
## Số quan sát trùng lặp: 0
🔹 Giải thích:
Hàm duplicated(data) → tìm các dòng trùng lặp trong bộ dữ liệu.
Hàm sum() → đếm số dòng trùng đó.
Hàm cat() → in kết quả ra màn hình.
🔹 Ý nghĩa thống kê:
Giúp phát hiện và loại bỏ các quan sát trùng lặp, nhằm đảm bảo dữ liệu độc lập, chính xác, và tránh sai lệch trong phân tích thống kê.
## DỮ LIỆU THIẾU THEO TỪNG CỘT:
## Order_ID Customer_ID Customer_Type Product Category
## 0 0 0 0 0
## Unit_Price Quantity Discount Total_Price Region
## 0 0 0 0 0
## Order_Date
## 0
🔹 Giải thích:
Hàm is.na(x) → kiểm tra ô nào bị trống (NA).
Hàm sum(is.na(x)) → đếm bao nhiêu ô trống trong một cột.
Hàm sapply(data, …) → lặp qua tất cả các cột trong bảng data để tính số ô trống của từng cột.
Biến missing_summary → lưu kết quả đó lại.
Hàm print(missing_summary) → in kết quả ra màn hình.
🔹 Ý nghĩa thống kê:
Giúp phát hiện mức độ thiếu dữ liệu của từng biến, từ đó quyết định xử lý (loại bỏ hoặc điền giá trị) trước khi phân tích thống kê.
if (nrow(data) == 0) stop("⚠️ File CSV rỗng hoặc không đọc được! Kiểm tra lại đường dẫn và định dạng.")
date_col <- grep("Date", names(data), value = TRUE)
if (length(date_col) == 0) stop("⚠️ Không tìm thấy cột ngày trong dữ liệu!")
data$Order_Date <- as.Date(data[[date_col]], tryFormats = c("%d/%m/%Y", "%Y-%m-%d", "%m/%d/%Y"))
data$Order_Date <- as.Date(data$Order_Date, format = "%d/%m/%Y")
data$Customer_Type <- as.factor(data$Customer_Type)
data$Category <- as.factor(data$Category)
data$Region <- as.factor(data$Region)
# Kiểm tra lại cấu trúc sau khi chuyển đổi
cat("=== CẤU TRÚC DỮ LIỆU SAU KHI CHUYỂN ĐỔI ===\n")## === CẤU TRÚC DỮ LIỆU SAU KHI CHUYỂN ĐỔI ===
## 'data.frame': 1048575 obs. of 11 variables:
## $ Order_ID : chr "ORD1" "ORD1" "ORD1" "ORD1" ...
## $ Customer_ID : chr "CUS1496" "CUS1496" "CUS1496" "CUS1496" ...
## $ Customer_Type: Factor w/ 2 levels "B2B","B2C": 1 1 1 1 1 2 1 1 1 1 ...
## $ Product : chr "Vio Wasser" "Evian" "Sprite" "Rauch Multivitamin" ...
## $ Category : Factor w/ 4 levels "Alcoholic Beverages",..: 4 4 3 2 4 1 2 4 4 4 ...
## $ Unit_Price : num 1.66 1.56 1.17 3.22 0.87 9.09 2.14 0.43 1.21 1.38 ...
## $ Quantity : int 53 90 73 59 35 2 44 13 92 3 ...
## $ Discount : num 0.1 0.1 0.05 0.1 0.1 0 0.1 0.05 0.1 0.05 ...
## $ Total_Price : num 79.2 126.4 81.1 171 27.4 ...
## $ Region : Factor w/ 16 levels "Baden-Württemberg",..: 1 1 1 1 1 15 6 6 6 6 ...
## $ Order_Date : Date, format: "2023-08-23" "2023-08-23" ...
🔹 Giải thích:
Hàm nrow() → đếm số dòng trong data. Nếu số dòng = 0, hàm stop() sẽ dừng chương trình và báo lỗi “File CSV rỗng hoặc không đọc được”.
Hàm grep() → tìm trong tên cột (names(data)) cột nào có chữ “Date”, rồi lưu tên đó vào biến date_col. Nếu không tìm thấy, stop() sẽ báo lỗi “Không tìm thấy cột ngày”.
Hàm as.Date() → chuyển cột ngày sang kiểu dữ liệu ngày tháng, đồng thời thử nhiều định dạng ngày khác nhau (%d/%m/%Y, %Y-%m-%d, %m/%d/%Y) để tránh lỗi.
data\(Order_Date <- as.Date(data\)Order_Date, format = “%d/%m/%Y”) → đảm bảo toàn bộ cột ngày ở định dạng chuẩn ngày/tháng/năm.
Hàm as.factor() → chuyển các cột Customer_Type, Category, Region thành biến phân loại (factor) — cần thiết khi vẽ biểu đồ hoặc chạy mô hình thống kê.
Hàm str() → hiển thị cấu trúc dữ liệu gồm số dòng, số cột, và kiểu dữ liệu của từng biến (numeric, factor, Date…).
🔹 Ý nghĩa thống kê:
Đoạn code giúp kiểm tra dữ liệu đầu vào, xác định và chuẩn hóa cột ngày, đồng thời chuyển các biến định tính thành dạng phân loại (factor), → giúp chuẩn bị dữ liệu sạch, đúng định dạng, sẵn sàng cho phân tích và mô hình hóa thống kê.
library(dplyr)
data <- data %>%
mutate(
Month = format(Order_Date, "%Y-%m"),
Year = format(Order_Date, "%Y"),
Quarter = quarters(Order_Date),
Day_of_Week = weekdays(Order_Date),
Revenue_Before_Discount = Unit_Price * Quantity,
Discount_Amount = Revenue_Before_Discount * Discount)🔹 Giải thích:
Hàm mutate() → dùng để tạo thêm cột mới hoặc tính lại giá trị cột cũ trong bảng data.
Dấu %>% → là toán tử pipe, dùng để chuyển kết quả của bước trước sang bước sau.
Hàm format() → lấy tháng và năm từ cột ngày (Order_Date).
Hàm quarters() → cho biết quý của từng ngày.
Hàm weekdays() → trả về thứ trong tuần tương ứng với ngày đó.
Revenue_Before_Discount = Unit_Price * Quantity → tính doanh thu trước chiết khấu (đơn giá × số lượng).
Discount_Amount = Revenue_Before_Discount * Discount → tính số tiền chiết khấu (doanh thu × tỷ lệ giảm giá).
🔹 Ý nghĩa thống kê:
Đoạn code này giúp tạo thêm các biến về thời gian và doanh thu, từ đó dễ phân tích xu hướng bán hàng theo năm, quý, tháng, hoặc ngày, và đánh giá tác động của chiết khấu đến doanh thu.
library(dplyr)
data <- data %>%
mutate(
Is_High_Discount = Discount > 0.1,
Discount_Category = case_when(
Discount == 0 ~ "No Discount",
Discount <= 0.05 ~ "Low Discount",
Discount <= 0.1 ~ "Medium Discount",
TRUE ~ "High Discount"
))🔹 Giải thích:
Is_High_Discount = Discount > 0.1 → tạo cột logic (TRUE/FALSE):
TRUE nếu mức giảm giá > 10%
FALSE nếu ≤ 10%
Hàm case_when() → hoạt động giống câu lệnh if–else, dùng để phân loại dữ liệu theo nhiều điều kiện khác nhau, ở đây gán nhãn chuỗi chữ cho từng mức giảm giá:
Discount == 0 → “Không giảm giá”
Discount ≤ 0.1 → “Giảm nhẹ”
Discount > 0.1 → “Giảm mạnh”
🔹 Ý nghĩa thống kê:
Đoạn code giúp phân loại mức độ giảm giá của từng giao dịch, từ đó có thể so sánh doanh thu giữa các nhóm giảm giá, và phân tích hành vi khách hàng khi giảm giá cao hoặc thấp.
library(dplyr)
data <- data %>%
mutate(
Order_Size = case_when(
Total_Price < 100 ~ "Small",
Total_Price < 500 ~ "Medium",
Total_Price < 1000 ~ "Large",
TRUE ~ "Very Large"
)
)
head(data,5)## Order_ID Customer_ID Customer_Type Product Category Unit_Price
## 1 ORD1 CUS1496 B2B Vio Wasser Water 1.66
## 2 ORD1 CUS1496 B2B Evian Water 1.56
## 3 ORD1 CUS1496 B2B Sprite Soft Drinks 1.17
## 4 ORD1 CUS1496 B2B Rauch Multivitamin Juices 3.22
## 5 ORD1 CUS1496 B2B Gerolsteiner Water 0.87
## Quantity Discount Total_Price Region Order_Date Month Year
## 1 53 0.10 79.18 Baden-Württemberg 2023-08-23 2023-08 2023
## 2 90 0.10 126.36 Baden-Württemberg 2023-08-23 2023-08 2023
## 3 73 0.05 81.14 Baden-Württemberg 2023-08-23 2023-08 2023
## 4 59 0.10 170.98 Baden-Württemberg 2023-08-23 2023-08 2023
## 5 35 0.10 27.40 Baden-Württemberg 2023-08-23 2023-08 2023
## Quarter Day_of_Week Revenue_Before_Discount Discount_Amount Is_High_Discount
## 1 Q3 Wednesday 87.98 8.7980 FALSE
## 2 Q3 Wednesday 140.40 14.0400 FALSE
## 3 Q3 Wednesday 85.41 4.2705 FALSE
## 4 Q3 Wednesday 189.98 18.9980 FALSE
## 5 Q3 Wednesday 30.45 3.0450 FALSE
## Discount_Category Order_Size
## 1 Medium Discount Small
## 2 Medium Discount Medium
## 3 Low Discount Small
## 4 Medium Discount Medium
## 5 Medium Discount Small
🔹 Giải thích:
Hàm mutate() → giúp tạo thêm cột mới trong bảng dữ liệu, ở đây là cột Order_Size.
Hàm case_when() → hoạt động giống câu lệnh if–else, dùng để phân loại giá trị của Total_Price thành 4 nhóm:
< 100 → “Small”
< 500 → “Medium”
< 1000 → “Large”
Còn lại → “Very Large”
Hàm head(data, 5) → hiển thị 5 dòng đầu tiên để xem kết quả sau khi thêm cột mới.
🔹 Ý nghĩa thống kê:
Đoạn code giúp phân loại đơn hàng theo quy mô giá trị, từ đó có thể phân tích hành vi mua sắm của khách hàng theo từng nhóm (Small, Medium, Large, Very Large).
library(dplyr)
# Phân tích hiệu suất bán hàng theo loại khách hàng và khu vực
customer_region_summary <- data %>%
group_by(Customer_Type, Region) %>%
summarise(
Total_Orders = n_distinct(Order_ID), # Tổng số đơn hàng
Total_Revenue = sum(Total_Price), # Tổng doanh thu
Avg_Order_Value = mean(Total_Price), # Giá trị đơn hàng trung bình
.groups = 'drop'
)
cat("=== PHÂN TÍCH HIỆU SUẤT THEO LOẠI KHÁCH HÀNG VÀ KHU VỰC ===\n")## === PHÂN TÍCH HIỆU SUẤT THEO LOẠI KHÁCH HÀNG VÀ KHU VỰC ===
## # A tibble: 32 × 5
## Customer_Type Region Total_Orders Total_Revenue Avg_Order_Value
## <fct> <fct> <int> <dbl> <dbl>
## 1 B2B Baden-Württemberg 7399 6296401. 282.
## 2 B2B Bayern 7453 6426283. 286.
## 3 B2B Berlin 7725 6880328. 298.
## 4 B2B Brandenburg 7403 6525847. 292.
## 5 B2B Bremen 7977 5761768. 241.
## 6 B2B Hamburg 8705 7480221. 287.
## 7 B2B Hessen 8337 7249384. 289.
## 8 B2B Mecklenburg-Vorpomm… 8225 7227687. 295.
## 9 B2B Niedersachsen 7248 6109817. 278.
## 10 B2B Nordrhein-Westfalen 7523 6060823. 270.
## # ℹ 22 more rows
🔹 Giải thích:
Hàm group_by(Customer_Type, Region) → gom nhóm dữ liệu theo loại khách hàng và khu vực.
Hàm summarise() → tính các chỉ số tổng hợp cho từng nhóm:
Total_Orders: tổng số đơn hàng khác nhau (n_distinct(Order_ID))
Total_Revenue: tổng doanh thu (sum(Total_Price))
Avg_Order_Value: giá trị trung bình mỗi đơn hàng (mean(Total_Price))
.groups = ‘drop’ → bỏ nhóm sau khi tóm tắt, trả về bảng gọn hơn.
Hàm cat() và print() → in tiêu đề và kết quả ra màn hình.
🔹 Ý nghĩa thống kê:
Giúp so sánh hiệu suất bán hàng giữa các loại khách hàng (ví dụ: cá nhân, doanh nghiệp) và khu vực, qua đó xác định khu vực hoặc nhóm khách hàng mang lại doanh thu cao nhất.
# Phân tích xu hướng bán hàng theo danh mục và thời gian
category_monthly_summary <- data %>%
group_by(Category, Month) %>%
summarise(
Total_Quantity = sum(Quantity), # Tổng số lượng bán ra
Total_Revenue = sum(Total_Price), # Tổng doanh thu
Avg_Unit_Price = mean(Unit_Price), # Giá bán trung bình
.groups = 'drop'
)
cat("=== PHÂN TÍCH THEO DANH MỤC SẢN PHẨM VÀ THÁNG (10 DÒNG ĐẦU) ===\n")## === PHÂN TÍCH THEO DANH MỤC SẢN PHẨM VÀ THÁNG (10 DÒNG ĐẦU) ===
## # A tibble: 10 × 5
## Category Month Total_Quantity Total_Revenue Avg_Unit_Price
## <fct> <chr> <int> <dbl> <dbl>
## 1 Alcoholic Beverages 2021-01 170963 2973048. 17.4
## 2 Alcoholic Beverages 2021-02 156497 2683922. 17.8
## 3 Alcoholic Beverages 2021-03 168305 2812860. 17.7
## 4 Alcoholic Beverages 2021-04 170120 2815952. 17.6
## 5 Alcoholic Beverages 2021-05 167744 2865023. 17.5
## 6 Alcoholic Beverages 2021-06 172310 2910454. 17.4
## 7 Alcoholic Beverages 2021-07 171715 2841055. 17.3
## 8 Alcoholic Beverages 2021-08 170586 2948309. 17.5
## 9 Alcoholic Beverages 2021-09 162690 2784813. 17.3
## 10 Alcoholic Beverages 2021-10 170464 2906880. 17.7
🔹 Giải thích:
group_by(Category, Month) → gom nhóm dữ liệu theo danh mục sản phẩm và tháng bán hàng.
summarise() → tính toán các chỉ số cho từng nhóm:
Total_Quantity: tổng số lượng sản phẩm bán ra trong tháng.
Total_Revenue: tổng doanh thu trong tháng.
Avg_Unit_Price: giá bán trung bình của sản phẩm.
.groups = ‘drop’ → bỏ cấu trúc nhóm sau khi tóm tắt, giúp bảng gọn hơn.
head(…, 10) → hiển thị 10 dòng đầu tiên của kết quả.
🔹 Ý nghĩa thống kê:
Giúp phân tích xu hướng bán hàng theo thời gian và so sánh giữa các danh mục sản phẩm, từ đó nhận biết mùa cao điểm – thấp điểm, và danh mục mang lại doanh thu lớn nhất theo từng tháng.
# Phân tích hiệu quả của các mức chiết khấu khác nhau
discount_analysis <- data %>%
group_by(Discount_Group = cut(Discount,
breaks = c(-0.1, 0, 0.05, 0.1, 0.15, 1),
labels = c("0%", "0-5%", "5-10%", "10-15%", ">15%"))) %>%
summarise(
Number_of_Orders = n(), # Số lượng đơn hàng
Total_Revenue = sum(Total_Price), # Tổng doanh thu
Avg_Order_Value = mean(Total_Price), # Giá trị đơn hàng trung bình
.groups = 'drop'
)
cat("=== PHÂN TÍCH HIỆU QUẢ CHIẾT KHẤU ===\n")## === PHÂN TÍCH HIỆU QUẢ CHIẾT KHẤU ===
## # A tibble: 4 × 4
## Discount_Group Number_of_Orders Total_Revenue Avg_Order_Value
## <fct> <int> <dbl> <dbl>
## 1 0% 674968 32189768. 47.7
## 2 0-5% 168122 28801144. 171.
## 3 5-10% 161028 57373493. 356.
## 4 10-15% 44457 18976217. 427.
🔹 Giải thích:
Hàm cut() → chia biến Discount (tỷ lệ giảm giá) thành 5 nhóm mức chiết khấu:
0%, 0–5%, 5–10%, 10–15%, >15%.
group_by(Discount_Group) → gom nhóm dữ liệu theo từng mức chiết khấu.
summarise() → tính các chỉ số cho từng nhóm:
Number_of_Orders: tổng số đơn hàng.
Total_Revenue: tổng doanh thu.
Avg_Order_Value: giá trị trung bình mỗi đơn hàng.
.groups = ‘drop’ → loại bỏ cấu trúc nhóm khi xuất kết quả.
cat() và print() → hiển thị tiêu đề và kết quả ra màn hình.
🔹 Ý nghĩa thống kê:
Giúp đánh giá tác động của các mức chiết khấu đến doanh thu và giá trị đơn hàng, từ đó xác định mức chiết khấu tối ưu — vừa thu hút khách hàng, vừa đảm bảo lợi nhuận.
# Phân tổ doanh thu theo khu vực - Cơ bản
phan_to_doanh_thu <- data %>%
group_by(Region) %>%
summarise(
Tong_doanh_thu = sum(Total_Price, na.rm = TRUE),
Doanh_thu_trung_binh = mean(Total_Price, na.rm = TRUE),
So_don_hang = n(),
.groups = 'drop'
) %>%
arrange(desc(Tong_doanh_thu))
print(phan_to_doanh_thu)## # A tibble: 16 × 4
## Region Tong_doanh_thu Doanh_thu_trung_binh So_don_hang
## <fct> <dbl> <dbl> <int>
## 1 Hamburg 9619253. 137. 70310
## 2 Hessen 9181452. 145. 63475
## 3 Mecklenburg-Vorpommern 9120188. 142. 64038
## 4 Saarland 9020347. 136. 66260
## 5 Rheinland-Pfalz 9011789. 133. 67849
## 6 Berlin 8879189. 139. 64014
## 7 Thüringen 8734228. 134. 64979
## 8 Bayern 8430479. 130. 64643
## 9 Brandenburg 8402955. 136. 61977
## 10 Niedersachsen 8320694. 123. 67657
## 11 Sachsen-Anhalt 8251296. 128. 64333
## 12 Baden-Württemberg 8237277. 128. 64249
## 13 Sachsen 8213791. 123. 66721
## 14 Schleswig-Holstein 8193415. 124. 65841
## 15 Nordrhein-Westfalen 8139463. 124. 65772
## 16 Bremen 7584805. 114. 66457
🔹 Giải thích:
group_by(Region) → gom nhóm dữ liệu theo khu vực bán hàng.
summarise() → tính các chỉ số tóm tắt cho từng khu vực:
Tong_doanh_thu: tổng doanh thu (bỏ qua giá trị thiếu bằng na.rm = TRUE).
Doanh_thu_trung_binh: doanh thu trung bình mỗi đơn hàng.
So_don_hang: số lượng đơn hàng trong khu vực.
arrange(desc(Tong_doanh_thu)) → sắp xếp kết quả theo doanh thu giảm dần.
print() → in kết quả ra màn hình.
🔹 Ý nghĩa thống kê:
Giúp so sánh mức doanh thu giữa các khu vực, xác định khu vực mạnh – yếu, từ đó hỗ trợ ra quyết định phân bổ nguồn lực và chiến lược bán hàng hiệu quả hơn.
## === THỐNG KÊ MÔ TẢ BIẾN TOTAL_PRICE ===
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.30 8.40 21.14 130.98 69.77 12682.78
## Trung bình: 130.9783
## Trung vị: 21.14
## Phương sai: 261024.3
## Độ lệch chuẩn: 510.9054
## Khoảng tứ phân vị: 61.37
## Phân vị 10% & 90%: 3.67 212.28
🔹 Giải thích:
summary(data$Total_Price) → hiển thị các chỉ tiêu mô tả cơ bản gồm: giá trị nhỏ nhất, trung vị, trung bình, tứ phân vị và lớn nhất.
mean() → tính trung bình doanh thu, phản ánh mức doanh thu điển hình.
median() → tính trung vị, giúp đánh giá xu hướng trung tâm ít bị ảnh hưởng bởi giá trị ngoại lệ.
var() → tính phương sai, đo độ biến động của doanh thu quanh giá trị trung bình.
sd() → tính độ lệch chuẩn, cho biết doanh thu dao động nhiều hay ít.
IQR() → tính khoảng tứ phân vị (Q3 - Q1), thể hiện phạm vi tập trung của 50% dữ liệu giữa.
quantile(…, probs = c(0.1, 0.9)) → lấy phân vị 10% và 90%, xác định biên dưới – biên trên của phần lớn doanh thu.
🔹 Ý nghĩa thống kê:
Giúp mô tả đặc điểm phân phối của doanh thu:
Đánh giá mức độ tập trung và biến động của doanh thu giữa các đơn hàng.
So sánh giữa trung bình và trung vị để nhận biết dữ liệu có bị lệch (skewed) không.
Độ lệch chuẩn và IQR cho biết độ ổn định của doanh thu.
Phân vị 10% và 90% cho phép xác định khoảng giá trị doanh thu phổ biến, loại bỏ ảnh hưởng của ngoại lệ. → Là bước nền tảng để hiểu dữ liệu trước khi đi vào phân tích xu hướng hoặc mô hình hóa thống kê.
## === DOANH THU TRUNG BÌNH THEO LOẠI KHÁCH HÀNG ===
customer_summary <- data %>%
group_by(Customer_Type) %>%
summarise(
Mean_Revenue = mean(Total_Price, na.rm = TRUE),
Total_Revenue = sum(Total_Price, na.rm = TRUE),
So_Don_Hang = n(),
.groups = 'drop'
) %>%
arrange(desc(Mean_Revenue))
print(customer_summary)## # A tibble: 2 × 4
## Customer_Type Mean_Revenue Total_Revenue So_Don_Hang
## <fct> <dbl> <dbl> <int>
## 1 B2B 281. 105150854. 373607
## 2 B2C 47.7 32189768. 674968
🔹 Giải thích:
group_by(Customer_Type) → gom nhóm dữ liệu theo từng
loại khách hàng (ví dụ: cá nhân, doanh nghiệp, thành
viên VIP,…).summarise() → tính các chỉ tiêu thống kê cơ bản cho
từng nhóm:
Mean_Revenue: doanh thu trung bình mỗi
khách hàng.Total_Revenue: tổng doanh thu của nhóm
khách hàng đó.So_Don_Hang: tổng số đơn hàng trong
nhóm.arrange(desc(Mean_Revenue)) → sắp xếp kết quả theo
doanh thu trung bình giảm dần để dễ so sánh nhóm có
doanh thu cao nhất.print() → in bảng kết quả ra màn hình.🔹 Ý nghĩa thống kê:
Giúp so sánh hiệu quả kinh doanh giữa các loại khách
hàng, xác định:
- Nhóm khách hàng nào mang lại doanh thu cao
nhất.
- Nhóm nào có nhiều đơn hàng nhưng giá trị thấp.
Từ đó doanh nghiệp có thể đưa ra chiến lược chăm sóc khách hàng
và định hướng marketing phù hợp hơn.
##
## === XU HƯỚNG DOANH THU THEO THÁNG ===
monthly_revenue <- data %>%
group_by(Month) %>%
summarise(Total_Revenue = sum(Total_Price, na.rm = TRUE))
ggplot(monthly_revenue, aes(x = Month, y = Total_Revenue, group = 1)) +
geom_line(color = "blue", linewidth = 1.2) +
geom_point(color = "red", size = 2) +
scale_y_continuous(labels = comma) +
labs(title = "Xu hướng doanh thu theo tháng",
x = "Tháng", y = "Tổng doanh thu") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))🔹 Giải thích:
group_by(Customer_Type) → gom nhóm dữ liệu theo loại khách hàng (ví dụ: khách mới, khách thân thiết…).
summarise() → tính các chỉ số tóm tắt cho từng nhóm khách hàng:
Mean_Revenue: doanh thu trung bình của mỗi loại khách hàng.
Total_Revenue: tổng doanh thu đóng góp bởi từng nhóm khách hàng.
So_Don_Hang: số lượng đơn hàng của nhóm đó.
arrange(desc(Mean_Revenue)) → sắp xếp kết quả giảm dần theo doanh thu trung bình để xem nhóm nào mang lại giá trị cao nhất.
🔹 Ý nghĩa thống kê:
Phân tích này giúp so sánh hiệu suất giữa các loại khách hàng, xem nhóm nào mang lại doanh thu trung bình cao nhất hoặc tổng doanh thu lớn nhất. → Hỗ trợ doanh nghiệp trong việc xác định nhóm khách hàng tiềm năng, ưu tiên chăm sóc hoặc chiến lược khuyến mãi phù hợp, từ đó tối ưu hóa doanh thu và lợi nhuận.
ggplot(data, aes(x = Total_Price)) +
geom_histogram(bins = 50, fill = "steelblue", alpha = 0.7) +
scale_x_continuous(labels = comma) +
labs(title = "Phân phối doanh thu",
subtitle = "Biểu đồ histogram thể hiện phân phối giá trị đơn hàng",
x = "Doanh thu (Total_Price)", y = "Số lượng đơn hàng") +
theme_minimal()🔹 Giải thích:
ggplot(data, aes(x = Total_Price)) → khởi tạo biểu đồ ggplot với trục hoành là biến doanh thu (Total_Price).
geom_histogram(bins = 50, fill = “steelblue”, alpha = 0.7) → vẽ biểu đồ tần suất (histogram) với 50 cột, màu xanh dương và độ trong suốt 0.7 để dễ nhìn.
scale_x_continuous(labels = comma) → định dạng trục X theo dấu phẩy ngăn cách hàng nghìn (vd: 10,000 thay vì 10000).
labs() → đặt tiêu đề, phụ đề, tên trục X (Doanh thu) và trục Y (Số lượng đơn hàng).
theme_minimal() → áp dụng giao diện tối giản, giúp biểu đồ rõ ràng và chuyên nghiệp.
🔹 Ý nghĩa thống kê:
Biểu đồ histogram giúp quan sát trực quan phân phối doanh thu giữa các đơn hàng:
Nếu cột tập trung bên trái → nhiều đơn hàng giá trị thấp (phân phối lệch phải). → Đây là bước quan trọng để hiểu cấu trúc dữ liệu doanh thu, trước khi áp dụng các phân tích thống kê hay mô hình hóa nâng cao.
ggplot(data, aes(y = Total_Price)) +
geom_boxplot(fill = "orange", alpha = 0.6) +
scale_y_continuous(labels = comma) +
labs(title = "Boxplot doanh thu", y = "Doanh thu (Total_Price)") +
theme_minimal()🔹 Giải thích:
ggplot(data, aes(y = Total_Price)) → chọn biến Total_Price làm trục tung (Y) để vẽ biểu đồ boxplot.
geom_boxplot(fill = “orange”, alpha = 0.6) → tạo biểu đồ hộp (boxplot), màu cam trong suốt 60%.
scale_y_continuous(labels = comma) → định dạng trục tung có dấu phẩy phân cách hàng nghìn (dễ đọc hơn).
labs(title = “Boxplot doanh thu”, y = “Doanh thu (Total_Price)”) → thêm tiêu đề và nhãn trục tung.
theme_minimal() → dùng giao diện tối giản, giúp biểu đồ rõ ràng và hiện đại.
🔹 Ý nghĩa thống kê:
Boxplot cho thấy phân bố, mức độ phân tán và các giá trị ngoại lai (outliers) của doanh thu.
Đường giữa hộp (median) biểu thị trung vị doanh thu – mức điển hình nhất.
Chiều dài hộp (IQR) thể hiện khoảng biến thiên của 50% dữ liệu giữa phân vị 25% và 75%.
Các chấm nằm ngoài hộp là đơn hàng có giá trị bất thường cao (outlier), thường chiếm tỷ lệ nhỏ nhưng ảnh hưởng lớn đến doanh thu tổng.
Kết hợp với histogram ở trên, có thể thấy đa số đơn hàng nhỏ, nhưng một số đơn hàng giá trị rất lớn kéo phân phối lệch phải.
if ("Discount" %in% names(data)) {
cat("\n=== TƯƠNG QUAN GIỮA DOANH THU VÀ GIẢM GIÁ ===\n")
corr <- cor(data$Total_Price, data$Discount, use = "complete.obs")
cat("Hệ số tương quan:", round(corr, 3), "\n")
ggplot(data, aes(x = Discount, y = Total_Price)) +
geom_point(alpha = 0.4, color = "darkgreen") +
geom_smooth(method = "lm", color = "red", se = FALSE) +
labs(title = "Tương quan giữa mức chiết khấu và doanh thu",
x = "Tỷ lệ chiết khấu", y = "Doanh thu (Total_Price)") +
theme_minimal()
}##
## === TƯƠNG QUAN GIỮA DOANH THU VÀ GIẢM GIÁ ===
## Hệ số tương quan: 0.248
🔹 Giải thích:
if (“Discount” %in% names(data)) → kiểm tra xem biến “Discount” có tồn tại trong bộ dữ liệu hay không.
cor(data\(Total_Price, data\)Discount, use = “complete.obs”) → tính hệ số tương quan (correlation) giữa doanh thu và tỷ lệ chiết khấu, bỏ qua giá trị bị thiếu.
geom_point() → vẽ biểu đồ tán xạ (scatter plot), mỗi điểm thể hiện một đơn hàng.
geom_smooth(method = “lm”) → thêm đường hồi quy tuyến tính, cho thấy xu hướng mối quan hệ giữa chiết khấu và doanh thu.
labs() → đặt tiêu đề và nhãn trục cho biểu đồ.
theme_minimal() → hiển thị biểu đồ rõ ràng, đơn giản.
🔹 Ý nghĩa thống kê:
Hệ số tương quan (corr) cho biết mức độ và chiều hướng quan hệ giữa chiết khấu và doanh thu:
Nếu corr > 0 → doanh thu tăng khi chiết khấu tăng (chiết khấu giúp kích cầu).
Nếu corr < 0 → doanh thu giảm khi chiết khấu tăng (mức giảm giá quá cao làm giảm lợi nhuận).
Nếu corr ≈ 0 → không có mối quan hệ rõ ràng giữa hai biến.
Biểu đồ tán xạ giúp quan sát trực quan: dữ liệu phân bố rải rác hay có xu hướng tuyến tính rõ ràng.
data <- data %>%
mutate(Revenue_Group = cut(Total_Price,
breaks = c(0, 100, 500, 1000, Inf),
labels = c("Thấp", "Trung bình", "Cao", "Rất cao")))
revenue_group_summary <- data %>%
group_by(Revenue_Group) %>%
summarise(
So_Don_Hang = n(),
Doanh_Thu_Trung_Binh = mean(Total_Price, na.rm = TRUE),
.groups = 'drop'
)
cat("\n=== PHÂN LOẠI DOANH THU THEO NHÓM ===\n")##
## === PHÂN LOẠI DOANH THU THEO NHÓM ===
## # A tibble: 4 × 3
## Revenue_Group So_Don_Hang Doanh_Thu_Trung_Binh
## <fct> <int> <dbl>
## 1 Thấp 842596 23.2
## 2 Trung bình 155134 202.
## 3 Cao 24442 699.
## 4 Rất cao 26403 2626.
🔹 Giải thích:
mutate() → thêm một biến mới vào bộ dữ liệu tên là Revenue_Group, thể hiện mức doanh thu của từng đơn hàng.
cut() → phân loại dữ liệu liên tục (Total_Price) thành các nhóm rời rạc theo khoảng giá trị:
breaks = c(0, 100, 500, 1000, Inf) → chia thành 4 khoảng doanh thu:
0–100: Thấp
100–500: Trung bình
500–1000: Cao
1000: Rất cao
labels = c(“Thấp”, “Trung bình”, “Cao”, “Rất cao”) → đặt tên cho các nhóm tương ứng.
group_by(Revenue_Group) → gom nhóm dữ liệu theo từng mức doanh thu.
summarise() → tính toán thống kê tóm tắt cho từng nhóm:
So_Don_Hang = n() → đếm số đơn hàng thuộc mỗi nhóm.
Doanh_Thu_Trung_Binh = mean(Total_Price, na.rm = TRUE) → tính doanh thu trung bình của nhóm.
arrange() không có ở đây nhưng nếu thêm, có thể sắp xếp nhóm theo doanh thu hoặc số đơn hàng.
print() → in kết quả ra màn hình.
🔹 Ý nghĩa thống kê:
Giúp phân khúc khách hàng hoặc đơn hàng theo giá trị doanh thu, dễ dàng nhận diện nhóm khách hàng giá trị cao (VIP) hoặc nhóm mua thấp.
Hỗ trợ doanh nghiệp xây dựng chiến lược marketing hoặc khuyến mãi riêng cho từng nhóm:
Nhóm thấp/trung bình → tập trung tăng tần suất mua hàng.
Nhóm cao/rất cao → duy trì, chăm sóc đặc biệt để giữ chân.
Đây là bước phân tích mô tả quan trọng, giúp hiểu rõ cấu trúc doanh thu của toàn bộ dữ liệu..
## === THỐNG KÊ CƠ BẢN THEO LOẠI KHÁCH HÀNG ===
customer_stats <- data %>%
group_by(Customer_Type) %>%
summarise(
So_Don_Hang = n(),
Tong_Doanh_Thu = sum(Total_Price, na.rm = TRUE),
Doanh_Thu_Trung_Binh = mean(Total_Price, na.rm = TRUE),
.groups = 'drop'
) %>%
mutate(Ty_Le_Don_Hang = round(So_Don_Hang / sum(So_Don_Hang) * 100, 2)) %>%
arrange(desc(Tong_Doanh_Thu))
print(customer_stats)## # A tibble: 2 × 5
## Customer_Type So_Don_Hang Tong_Doanh_Thu Doanh_Thu_Trung_Binh Ty_Le_Don_Hang
## <fct> <int> <dbl> <dbl> <dbl>
## 1 B2B 373607 105150854. 281. 35.6
## 2 B2C 674968 32189768. 47.7 64.4
🔹 Giải thích:
group_by(Customer_Type) → gom dữ liệu theo từng loại khách hàng.
summarise() → tính các chỉ số mô tả:
So_Don_Hang: tổng số đơn của mỗi loại khách.
Tong_Doanh_Thu: tổng doanh thu.
Doanh_Thu_Trung_Binh: giá trị trung bình mỗi đơn.
mutate() + Ty_Le_Don_Hang → tính tỷ lệ phần trăm số đơn hàng theo loại khách.
arrange(desc(…)) → sắp xếp giảm dần theo doanh thu.
🔹 Ý nghĩa thống kê:
Giúp doanh nghiệp xác định:
Loại khách hàng nào đóng góp doanh thu lớn nhất.
Nhóm khách hàng nào chiếm tỷ trọng nhiều nhất trong tổng số đơn.
Từ đó, có thể ưu tiên chăm sóc hoặc khuyến mãi cho nhóm sinh lợi cao.
#Biểu đồ cột – số lượng đơn hàng
ggplot(customer_stats, aes(x = reorder(Customer_Type, -So_Don_Hang), y = So_Don_Hang, fill = Customer_Type)) +
geom_col(show.legend = FALSE) +
labs(title = "Số lượng đơn hàng theo loại khách hàng", x = "Loại khách hàng", y = "Số đơn hàng") +
theme_minimal()🔹 Giải thích:
ggplot(customer_stats, aes(x = reorder(Customer_Type, -So_Don_Hang), y = So_Don_Hang, fill = Customer_Type)) → tạo biểu đồ cột, trục x là loại khách hàng, trục y là số lượng đơn hàng, sắp xếp giảm dần theo số đơn hàng, màu cột theo loại khách hàng.
geom_col(show.legend = FALSE) → vẽ cột, ẩn chú giải màu.
labs(title = “Số lượng đơn hàng theo loại khách hàng”, x = “Loại khách hàng”, y = “Số đơn hàng”) → đặt tiêu đề và nhãn trục.
theme_minimal() → giao diện biểu đồ gọn gàng, tối giản.
🔹 Ý nghĩa thống kê:
Biểu đồ thể hiện số lượng đơn hàng của từng loại khách hàng, giúp dễ dàng so sánh mức độ mua hàng giữa các nhóm.
Có thể nhanh chóng nhận ra nhóm khách hàng đóng góp nhiều đơn hàng nhất hoặc ít nhất, từ đó hỗ trợ ra quyết định marketing, khuyến mãi hay quản lý khách hàng.
#Biểu đồ tròn
ggplot(customer_stats, aes(x = "", y = Ty_Le_Don_Hang, fill = Customer_Type)) +
geom_col(width = 1) +
coord_polar(theta = "y") +
labs(title = "Tỷ lệ loại khách hàng (%)") +
theme_void()🔹 Giải thích code:
ggplot(customer_stats, aes(x = ““, y = Ty_Le_Don_Hang, fill = Customer_Type)) → tạo biểu đồ, trục y là tỷ lệ đơn hàng của từng loại khách hàng, fill màu theo loại khách hàng, trục x để trống (”“) vì vẽ tròn.
geom_col(width = 1) → vẽ cột tròn, chiều rộng cột = 1 để đủ làm tròn.
coord_polar(theta = “y”) → chuyển từ biểu đồ cột sang biểu đồ tròn (pie chart) theo trục y.
labs(title = “Tỷ lệ loại khách hàng (%)”) → đặt tiêu đề biểu đồ.
theme_void() → loại bỏ trục, lưới, nhãn để biểu đồ tròn gọn gàng.
🔹 Ý nghĩa thống kê:
Biểu đồ thể hiện tỷ trọng phần trăm đơn hàng của từng loại khách hàng trong tổng số.
Giúp nhanh chóng nhận ra nhóm khách hàng nào chiếm tỷ lệ cao nhất hoặc thấp nhất, thuận tiện cho việc phân tích chiến lược bán hàng, chăm sóc khách hàng và phân bổ nguồn lực.
####So sánh doanhn thu phân phối theo loại khách hàng
ggplot(data, aes(x = Customer_Type, y = Total_Price, fill = Customer_Type)) +
geom_boxplot(alpha = 0.6) +
scale_y_continuous(labels = scales::comma) +
labs(title = "Phân phối doanh thu theo loại khách hàng", x = "Loại khách hàng", y = "Doanh thu (Total_Price)") +
theme_minimal()🔹 Giải thích code:
ggplot(data, aes(x = Customer_Type, y = Total_Price, fill = Customer_Type)) → tạo biểu đồ, trục x là loại khách hàng, trục y là doanh thu từng đơn hàng, màu cột theo loại khách hàng.
geom_boxplot(alpha = 0.6) → vẽ biểu đồ hộp, alpha = 0.6 làm cột hơi trong suốt để dễ nhìn.
scale_y_continuous(labels = scales::comma) → hiển thị trục y với dấu phân cách hàng nghìn, dễ đọc số lớn.
labs(title = “Phân phối doanh thu theo loại khách hàng”, x = “Loại khách hàng”, y = “Doanh thu (Total_Price)”) → đặt tiêu đề và nhãn trục.
theme_minimal() → giao diện biểu đồ gọn gàng, tối giản.
🔹 Ý nghĩa thống kê:
Biểu đồ hộp thể hiện phân phối doanh thu từng đơn hàng theo loại khách hàng, bao gồm: trung vị, tứ phân vị và các giá trị ngoại lai (outlier).
Giúp nhận biết:
Nhóm khách hàng nào có doanh thu trung bình cao nhất.
Nhóm nào có sự biến thiên doanh thu lớn (có nhiều đơn hàng giá trị cao/thấp bất thường).
Đây là công cụ quan trọng để phân tích hành vi chi tiêu của khách hàng và ra quyết định marketing, khuyến mãi phù hợp.
customer_summary <- data %>%
group_by(Customer_Type) %>%
summarise(
Count = n(), # Số lượng giao dịch
Percentage = n()/nrow(data)*100, # Tỷ lệ phần trăm
Total_Revenue = sum(Total_Price), # Tổng doanh thu
Avg_Transaction_Value = mean(Total_Price) # Giá trị giao dịch trung bình
)
cat("=== PHÂN TÍCH THEO LOẠI KHÁCH HÀNG ===\n")## === PHÂN TÍCH THEO LOẠI KHÁCH HÀNG ===
## # A tibble: 2 × 5
## Customer_Type Count Percentage Total_Revenue Avg_Transaction_Value
## <fct> <int> <dbl> <dbl> <dbl>
## 1 B2B 373607 35.6 105150854. 281.
## 2 B2C 674968 64.4 32189768. 47.7
# Biểu đồ so sánh doanh thu
ggplot(customer_summary, aes(x = Customer_Type, y = Total_Revenue, fill = Customer_Type)) +
geom_bar(stat = "identity") +
scale_y_continuous(labels = comma) +
labs(title = "SO SÁNH DOANH THU THEO LOẠI KHÁCH HÀNG",
subtitle = "B2B vs B2C",
x = "Loại Khách Hàng",
y = "Tổng Doanh Thu") +
theme_minimal() +
theme(legend.position = "none")🔹 Giải thích code:
group_by(Customer_Type) → gom các dòng dữ liệu theo từng loại khách hàng (B2B, B2C, …).
summarise(…) → tạo bảng tổng hợp với các chỉ số
aes(x = Customer_Type, y = Total_Revenue, fill = Customer_Type) → trục X là loại khách hàng, trục Y là doanh thu, mỗi cột được tô màu theo loại khách hàng.
geom_bar(stat = “identity”) → vẽ cột với chiều cao chính xác bằng Total_Revenue.
scale_y_continuous(labels = comma) → hiển thị số trên trục Y với dấu phẩy ngăn cách hàng nghìn.
labs(…) → thêm tiêu đề, tiêu đề phụ, tên trục.
theme_minimal() → theme đơn giản, gọn gàng.
theme(legend.position = “none”) → ẩn chú giải màu (vì trục X đã thể hiện loại khách hàng).
🔹 Ý nghĩa thống kê:
Mặc dù số lượng giao dịch của khách hàng B2C (64.4%) nhiều hơn gần gấp đôi so với B2B (35.6%), nhưng tổng doanh thu từ B2B lại cao hơn gấp 3 lần. Điều này khẳng định khách hàng doanh nghiệp có giá trị chiến lược quan trọng hơn về mặt doanh thu.
# Phân tích hiệu suất theo khu vực địa lý
region_summary <- data %>%
group_by(Region) %>%
summarise(
Total_Orders = n_distinct(Order_ID), # Tổng số đơn hàng
Total_Revenue = sum(Total_Price), # Tổng doanh thu
Avg_Order_Value = mean(Total_Price), # Giá trị đơn hàng trung bình
.groups = 'drop'
) %>%
arrange(desc(Total_Revenue)) # Sắp xếp theo doanh thu giảm dần
cat("=== PHÂN TÍCH HIỆU SUẤT THEO KHU VỰC ===\n")## === PHÂN TÍCH HIỆU SUẤT THEO KHU VỰC ===
## # A tibble: 16 × 4
## Region Total_Orders Total_Revenue Avg_Order_Value
## <fct> <int> <dbl> <dbl>
## 1 Hamburg 23426 9619253. 137.
## 2 Hessen 21071 9181452. 145.
## 3 Mecklenburg-Vorpommern 21414 9120188. 142.
## 4 Saarland 22011 9020347. 136.
## 5 Rheinland-Pfalz 22668 9011789. 133.
## 6 Berlin 21284 8879189. 139.
## 7 Thüringen 21830 8734228. 134.
## 8 Bayern 21476 8430479. 130.
## 9 Brandenburg 20570 8402955. 136.
## 10 Niedersachsen 22428 8320694. 123.
## 11 Sachsen-Anhalt 21416 8251296. 128.
## 12 Baden-Württemberg 21317 8237277. 128.
## 13 Sachsen 22213 8213791. 123.
## 14 Schleswig-Holstein 21976 8193415. 124.
## 15 Nordrhein-Westfalen 21978 8139463. 124.
## 16 Bremen 22115 7584805. 114.
# Biểu đồ doanh thu theo khu vực
ggplot(region_summary, aes(x = reorder(Region, Total_Revenue), y = Total_Revenue)) +
geom_bar(stat = "identity", fill = "darkorange", alpha = 0.8) +
coord_flip() +
scale_y_continuous(labels = comma) +
labs(title = "DOANH THU THEO KHU VỰC",
subtitle = "Sắp xếp theo thứ tự doanh thu giảm dần",
x = "Khu Vực",
y = "Tổng Doanh Thu") +
theme_minimal()GIẢI THÍCH 5.3:
# Tổng hợp các chỉ số kinh doanh quan trọng
overall_summary <- data %>%
summarise(
Total_Orders = n_distinct(Order_ID), # Tổng số đơn hàng
Total_Customers = n_distinct(Customer_ID), # Tổng số khách hàng
Total_Products = n_distinct(Product), # Tổng số sản phẩm
Total_Revenue = sum(Total_Price), # Tổng doanh thu
Avg_Order_Value = mean(Total_Price), # Giá trị đơn hàng trung bình
Total_Discount_Given = sum(Discount_Amount) # Tổng chiết khấu đã áp dụng
)
cat("=== TỔNG QUAN HIỆU SUẤT KINH DOANH ===\n")## === TỔNG QUAN HIỆU SUẤT KINH DOANH ===
## Total_Orders Total_Customers Total_Products Total_Revenue Avg_Order_Value
## 1 349193 10000 47 137340621 130.9783
## Total_Discount_Given
## 1 11239427
GIẢI THÍCH 6.1:
# Xác định các sản phẩm có đóng góp doanh thu cao nhất
top_products <- data %>%
group_by(Product, Category) %>%
summarise(
Total_Quantity = sum(Quantity), # Tổng số lượng bán ra
Total_Revenue = sum(Total_Price), # Tổng doanh thu
.groups = 'drop'
) %>%
arrange(desc(Total_Revenue)) %>% # Sắp xếp theo doanh thu giảm dần
head(10) # Lấy 10 sản phẩm hàng đầu
cat("=== TOP 10 SẢN PHẨM THEO DOANH THU ===\n")## === TOP 10 SẢN PHẨM THEO DOANH THU ===
## # A tibble: 10 × 4
## Product Category Total_Quantity Total_Revenue
## <chr> <fct> <int> <dbl>
## 1 Veuve Clicquot Alcoholic Beverages 316620 24234519.
## 2 Moët & Chandon Alcoholic Beverages 308477 20255705.
## 3 Johnnie Walker Alcoholic Beverages 305202 11164523.
## 4 Jack Daniels Alcoholic Beverages 310730 11163887.
## 5 Tanqueray Alcoholic Beverages 304860 9924823.
## 6 Bacardi Alcoholic Beverages 307767 6824726.
## 7 Havana Club Alcoholic Beverages 309875 6753102.
## 8 Sauvignon Blanc Alcoholic Beverages 314981 2765448.
## 9 Riesling Alcoholic Beverages 342425 2711547.
## 10 Cranberry Juice Juices 862501 2693706.
# Biểu đồ top sản phẩm
ggplot(top_products, aes(x = reorder(Product, Total_Revenue), y = Total_Revenue)) +
geom_bar(stat = "identity", fill = "purple", alpha = 0.8) +
coord_flip() +
scale_y_continuous(labels = comma) +
labs(title = "TOP 10 SẢN PHẨM THEO DOANH THU",
subtitle = "Các sản phẩm có đóng góp doanh thu cao nhất",
x = "Sản Phẩm",
y = "Doanh Thu") +
theme_minimal()GIẢI THÍCH 6.2:
# Phân tích xu hướng doanh thu theo thời gian
monthly_trend <- data %>%
group_by(Month) %>%
summarise(
Total_Revenue = sum(Total_Price), # Tổng doanh thu theo tháng
Total_Orders = n_distinct(Order_ID), # Tổng số đơn hàng theo tháng
Avg_Order_Value = mean(Total_Price), # Giá trị đơn hàng trung bình
.groups = 'drop'
)
cat("=== XU HƯỚNG DOANH THU THEO THÁNG ===\n")## === XU HƯỚNG DOANH THU THEO THÁNG ===
## # A tibble: 36 × 4
## Month Total_Revenue Total_Orders Avg_Order_Value
## <chr> <dbl> <int> <dbl>
## 1 2021-01 3815437. 10025 127.
## 2 2021-02 3430573. 8840 130.
## 3 2021-03 3649256. 9774 125.
## 4 2021-04 3652787. 9556 127.
## 5 2021-05 3718815. 9902 124.
## 6 2021-06 3729842. 9595 130.
## 7 2021-07 3689650. 9745 127.
## 8 2021-08 3797610. 9930 128.
## 9 2021-09 3589288. 9597 125.
## 10 2021-10 3749630. 9770 128.
## # ℹ 26 more rows
# Biểu đồ xu hướng
ggplot(monthly_trend, aes(x = Month, y = Total_Revenue, group = 1)) +
geom_line(color = "red", size = 1.2) +
geom_point(color = "red", size = 2) +
scale_y_continuous(labels = comma) +
labs(title = "XU HƯỚNG DOANH THU THEO THỜI GIAN",
subtitle = "Biến động doanh thu qua các tháng",
x = "Tháng",
y = "Doanh Thu") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))GIẢI THÍCH 6.3: