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.
## === THÔNG TIN CƠ BẢN VỀ BỘ DỮ LIỆU ===
## Kích thước bộ dữ liệu: 1048575 11
Giải thích Hàm dim() trong R trả về kích thước (dimension) của một đối tượng dạng bảng, chẳng hạn như data frame, matrix hoặc tibble.
Nhận xét Bộ dữ liệu có 1.048.575 dòng (quan sát) và có 11 cột (biến số).
## === 10 DÒNG ĐẦU TIÊN CỦA DỮ LIỆ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
## 7 ORD3 CUS1806 B2B Tomato Juice Juices
## 8 ORD3 CUS1806 B2B Vittel Water
## 9 ORD3 CUS1806 B2B San Pellegrino Water
## 10 ORD3 CUS1806 B2B Evian Water
## 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
## 7 2.14 44 0.10 84.74 Hamburg 20/11/2022
## 8 0.43 13 0.05 5.31 Hamburg 20/11/2022
## 9 1.21 92 0.10 100.19 Hamburg 20/11/2022
## 10 1.38 3 0.05 3.93 Hamburg 20/11/2022
🔹 Giải thích
Hàm head(data, 10) lấy 10 dòng đầu tiên của data frame data.
🔹 Ý nghĩa thống kê
Giúp xem cấu trúc dữ liệu thô: các tên cột, định dạng từng cột (số, chữ, ngày, …). Phát hiện dòng bị lỗi hoặc thiếu dữ liệu (NA) ngay từ đầu.
## === 10 DÒNG CUỐI CÙNG CỦA DỮ LIỆU ===
## Order_ID Customer_ID Customer_Type Product
## 1048566 ORD349189 CUS3703 B2C Hohes C Orange
## 1048567 ORD349190 CUS8480 B2C Granini Apple
## 1048568 ORD349191 CUS6311 B2C Cranberry Juice
## 1048569 ORD349192 CUS25 B2C Rauch Multivitamin
## 1048570 ORD349192 CUS25 B2C Havana Club
## 1048571 ORD349192 CUS25 B2C Bacardi
## 1048572 ORD349192 CUS25 B2C Fritz-Kola
## 1048573 ORD349193 CUS2035 B2C Volvic Touch
## 1048574 ORD349193 CUS2035 B2C Vittel
## 1048575 ORD349193 CUS2035 B2C Fanta
## Category Unit_Price Quantity Discount Total_Price
## 1048566 Juices 1.80 3 0 5.40
## 1048567 Juices 1.69 15 0 25.35
## 1048568 Juices 3.56 10 0 35.60
## 1048569 Juices 2.38 8 0 19.04
## 1048570 Alcoholic Beverages 12.96 9 0 116.64
## 1048571 Alcoholic Beverages 13.84 3 0 41.52
## 1048572 Soft Drinks 2.05 2 0 4.10
## 1048573 Water 1.46 11 0 16.06
## 1048574 Water 0.59 2 0 1.18
## 1048575 Soft Drinks 1.23 15 0 18.45
## Region Order_Date
## 1048566 Sachsen 26/10/2022
## 1048567 Sachsen 09/09/2023
## 1048568 Bremen 20/12/2022
## 1048569 Niedersachsen 27/08/2022
## 1048570 Niedersachsen 27/08/2022
## 1048571 Niedersachsen 27/08/2022
## 1048572 Niedersachsen 27/08/2022
## 1048573 Sachsen-Anhalt 05/11/2023
## 1048574 Sachsen-Anhalt 05/11/2023
## 1048575 Sachsen-Anhalt 05/11/2023
🔹 Giải thích
tail(data, 10) lấy 10 dòng cuối cùng trong bảng dữ liệu.
🔹 Ý nghĩa thống kê
Kiểm tra phần cuối dữ liệu xem có dòng bị trống, lặp hoặc lỗi nhập liệu không.
## Số quan sát (dòng): 1048575
## Số biến (cột): 11
## Các biến định lượng: 4
## Các biến định tính: 7
🔹 Giải thích
nrow(data) → đếm số hàng (số lượng quan sát/giao dịch).
ncol(data) → đếm số cột (số lượng biến/thuộc tính).
sapply(data, is.numeric) → kiểm tra cột nào là dạng số (numeric), kết quả trả về TRUE/FALSE cho từng cột.
sum(sapply(data, is.numeric)) → đếm tổng số biến định lượng.
sapply(data, is.character) | sapply(data, is.factor) → kiểm tra cột nào là dạng ký tự hoặc phân loại (categorical).
sum(…) → đếm tổng số biến định tính.
🔹 Ý nghĩa thống kê
Giúp hiểu sơ bộ quy mô và cấu trúc dữ liệu:
Có bao nhiêu dòng (quan sát)
Có bao nhiêu cột (biến)
Loại biến nào chiếm ưu thế (định lượng hay định tính)?
## Tên các biến: Order_ID Customer_ID Customer_Type Product Category Unit_Price Quantity Discount Total_Price Region Order_Date
## === KIỂU DỮ LIỆU CỦA CÁC CỘT ===
## '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" ...
🔹 Giải thích
Hàm str() hiển thị cấu trúc đối tượng, bao gồm:
Kiểu dữ liệu từng cột (numeric, character, factor, Date, …)
Một vài giá trị mẫu của mỗi cột.
🔹 Ý nghĩa thống kê
Giúp xác định:
Cột nào là biến định lượng (số, có thể tính trung bình, tổng, …)
Cột nào là biến định tính (phân loại: vùng, giới tính, loại khách hàng
###Thống kê mô tả tổng quan
## === THỐNG KÊ MÔ TẢ TỔNG QUAN ===
## 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
🔹 Giải thích
summary() tự động tạo bảng thống kê mô tả cho mỗi cột:
Với biến số: hiển thị Min, 1st Qu., Median, Mean, 3rd Qu., Max
Với biến phân loại: đếm tần suất từng giá trị.
🔹 Ý nghĩa thống kê
Mean (trung bình) → giá trị đại diện chung.
Median (trung vị) → giá trị giữa, ít bị ảnh hưởng bởi ngoại lệ.
Min / Max → phạm vi dao động của dữ liệu.
1st Qu. / 3rd Qu. → phân vị 25% và 75%, thể hiện độ phân tán.
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 |
###Kiểm tra số lượng giá trị duy nhất trong các cột phân loại
## === SỐ LƯỢNG GIÁ TRỊ DUY NHẤT THEO CỘT ===
## Customer_Type Category Region
## 2 4 16
🔹 Giải thích
Câu lệnh trên sử dụng hàm sapply() để lặp qua các cột “Customer_Type”, “Category” và “Region”.
Với mỗi cột, hàm unique(x) lấy ra các giá trị khác nhau (không trùng lặp).
Sau đó, length(unique(x)) đếm số lượng giá trị duy nhất trong cột đó.
Kết quả là một bảng nhỏ hiển thị số lượng loại khác nhau trong từng biến phân loại.
🔹 Ý nghĩa thống kê
Giúp xác định mức độ đa dạng của dữ liệu phân loại:
Có bao nhiêu loại khách hàng (Customer_Type)
Có bao nhiêu danh mục sản phẩm (Category)
Có bao nhiêu khu vực bán hàng (Region)
Nếu quá nhiều, cần xem xét gộp nhóm hoặc mã hóa lại khi phân tích hoặc trực quan hóa.
## 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)
)🔹 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 đó.
library(dplyr)
data <- data %>%
mutate(
Revenue_Before_Discount = Unit_Price * Quantity,
Discount_Amount = Revenue_Before_Discount * Discount
)🔹 Giải thích:
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á).
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() → 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"
)
)🔹 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
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'
)
customer_region_summary$Total_Revenue <-format(customer_region_summary$Total_Revenue, big.mark = ".", decimal.mark = ",", scientific = FALSE)
customer_region_summary$Avg_Order_Value <- format(round(customer_region_summary$Avg_Order_Value, 2), big.mark = ".", decimal.mark = ",", scientific = FALSE)
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> <chr> <chr>
## 1 B2B Baden-Württemberg 7399 6.296.401 281,87
## 2 B2B Bayern 7453 6.426.283 285,68
## 3 B2B Berlin 7725 6.880.328 297,98
## 4 B2B Brandenburg 7403 6.525.847 291,51
## 5 B2B Bremen 7977 5.761.768 240,87
## 6 B2B Hamburg 8705 7.480.221 287,49
## 7 B2B Hessen 8337 7.249.384 288,65
## 8 B2B Mecklenburg-Vorpomm… 8225 7.227.687 294,51
## 9 B2B Niedersachsen 7248 6.109.817 277,85
## 10 B2B Nordrhein-Westfalen 7523 6.060.823 269,89
## # ℹ 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:
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à 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'
)
category_monthly_summary$Total_Quantity <- format(category_monthly_summary$Total_Quantity, big.mark = ".", scientific = FALSE)
category_monthly_summary$Total_Revenue <- format(category_monthly_summary$Total_Revenue, big.mark = ".", scientific = FALSE)
category_monthly_summary$Avg_Unit_Price <- format(round(category_monthly_summary$Avg_Unit_Price, 2), big.mark = ".", decimal.mark = ",", scientific = FALSE)
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> <chr> <chr> <chr>
## 1 Alcoholic Beverages 2021-01 170.963 2.973.048.1 17,37
## 2 Alcoholic Beverages 2021-02 156.497 2.683.921.7 17,79
## 3 Alcoholic Beverages 2021-03 168.305 2.812.859.7 17,71
## 4 Alcoholic Beverages 2021-04 170.120 2.815.951.8 17,58
## 5 Alcoholic Beverages 2021-05 167.744 2.865.023.1 17,50
## 6 Alcoholic Beverages 2021-06 172.310 2.910.453.9 17,45
## 7 Alcoholic Beverages 2021-07 171.715 2.841.054.7 17,31
## 8 Alcoholic Beverages 2021-08 170.586 2.948.308.8 17,52
## 9 Alcoholic Beverages 2021-09 162.690 2.784.813.1 17,34
## 10 Alcoholic Beverages 2021-10 170.464 2.906.880.4 17,71
🔹 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:
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'
)
discount_analysis$Number_of_Orders <- format(discount_analysis$Number_of_Orders, big.mark = ".", scientific = FALSE)
discount_analysis$Total_Revenue <- format(discount_analysis$Total_Revenue, big.mark = ".", scientific = FALSE)
discount_analysis$Avg_Order_Value <- format(round(discount_analysis$Avg_Order_Value, 2), big.mark = ".", decimal.mark = ",", scientific = FALSE)
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> <chr> <chr> <chr>
## 1 0% "674.968" 32.189.768 " 47,69"
## 2 0-5% "168.122" 28.801.144 "171,31"
## 3 5-10% "161.028" 57.373.493 "356,30"
## 4 10-15% " 44.457" 18.976.217 "426,84"
🔹 Giải thích:
Hàm cut() → chia biến Discount thành 5 nhóm mức chiết khấu:
group_by(Discount_Group) → gom nhóm dữ liệu theo từng mức chiết khấu.
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.
# Tạo bảng phan_to_doanh_thu
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))
# Định dạng dấu phân cách cho các cột số
phan_to_doanh_thu$Tong_doanh_thu <- format(phan_to_doanh_thu$Tong_doanh_thu, big.mark = ".", scientific = FALSE)
phan_to_doanh_thu$Doanh_thu_trung_binh <- format(round(phan_to_doanh_thu$Doanh_thu_trung_binh, 2), big.mark = ".", decimal.mark = ",", scientific = FALSE)
phan_to_doanh_thu$So_don_hang <- format(phan_to_doanh_thu$So_don_hang, big.mark = ".", scientific = FALSE)
print(phan_to_doanh_thu)## # A tibble: 16 × 4
## Region Tong_doanh_thu Doanh_thu_trung_binh So_don_hang
## <fct> <chr> <chr> <chr>
## 1 Hamburg 9.619.253 136,81 70.310
## 2 Hessen 9.181.452 144,65 63.475
## 3 Mecklenburg-Vorpommern 9.120.188 142,42 64.038
## 4 Saarland 9.020.347 136,14 66.260
## 5 Rheinland-Pfalz 9.011.789 132,82 67.849
## 6 Berlin 8.879.189 138,71 64.014
## 7 Thüringen 8.734.228 134,42 64.979
## 8 Bayern 8.430.479 130,42 64.643
## 9 Brandenburg 8.402.955 135,58 61.977
## 10 Niedersachsen 8.320.694 122,98 67.657
## 11 Sachsen-Anhalt 8.251.296 128,26 64.333
## 12 Baden-Württemberg 8.237.277 128,21 64.249
## 13 Sachsen 8.213.791 123,11 66.721
## 14 Schleswig-Holstein 8.193.415 124,44 65.841
## 15 Nordrhein-Westfalen 8.139.463 123,75 65.772
## 16 Bremen 7.584.805 114,13 66.457
🔹 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.
library(dplyr)
library(ggplot2)
library(scales)
library(moments)
cat("=== THỐNG KÊ MÔ TẢ BIẾN TOTAL_PRICE ===\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
skew_value <- skewness(data$Total_Price, na.rm = TRUE)
cat("Độ lệch (skewness):", round(skew_value, 3), "\n")## Độ lệch (skewness): 9.955
🔹 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ệ.
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)) %>%
mutate(
Mean_Revenue = comma(Mean_Revenue, accuracy = 1),
Total_Revenue = comma(Total_Revenue, accuracy = 1),
So_Don_Hang = comma(So_Don_Hang)
)
customer_summary %>%
kable(col.names = c("Loại khách hàng", "Doanh thu TB", "Tổng doanh thu", "Số đơn hàng"),
align = "c")| Loại khách hàng | Doanh thu TB | Tổng doanh thu | Số đơn hàng |
|---|---|---|---|
| B2B | 281 | 105,150,854 | 373,607 |
| B2C | 48 | 32,189,768 | 674,968 |
🔹 Giải thích
group_by(Customer_Type) → gom nhóm dữ liệu theo từng loại khách hàng
summarise() → tính các chỉ tiêu thống kê cơ bản cho từng 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.
data <- data %>%
mutate(Year = format(as.Date(Order_Date), "%Y"))
# Tổng hợp doanh thu theo năm
yearly_revenue <- data %>%
group_by(Year) %>%
summarise(Total_Revenue = sum(Total_Price, na.rm = TRUE))
# Vẽ biểu đồ xu hướng doanh thu theo năm
ggplot(yearly_revenue, aes(x = as.factor(Year), y = Total_Revenue, fill = Year)) +
geom_col(width = 0.6) +
geom_text(aes(label = scales::comma(Total_Revenue)),
vjust = -0.5, size = 3.5) +
scale_y_continuous(labels = scales::comma) +
labs(
title = "Doanh thu từng năm",
x = "Năm",
y = "Tổng doanh thu"
) +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 0, hjust = 0.5),
plot.title = element_text(face = "bold", size = 14)
)🔹 Giải thích:
group_by(Customer_Type) → gom nhóm dữ liệu theo loại khách hàng
summarise() → tính các chỉ số tóm tắt cho từng nhóm khách hàng:
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.
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")
}##
## === 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.
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")
)
)
# Tóm tắt theo nhóm
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"
) %>%
mutate(
So_Don_Hang = comma(So_Don_Hang),
Doanh_Thu_Trung_Binh = comma(Doanh_Thu_Trung_Binh, accuracy = 1)
)
cat("\n=== PHÂN LOẠI DOANH THU THEO NHÓM ===\n")##
## === PHÂN LOẠI DOANH THU THEO NHÓM ===
revenue_group_summary %>%
kable(
col.names = c("Nhóm doanh thu", "Số đơn hàng", "Doanh thu trung bình (VNĐ)"),
align = "c"
)| Nhóm doanh thu | Số đơn hàng | Doanh thu trung bình (VNĐ) |
|---|---|---|
| Thấp | 842,596 | 23 |
| Trung bình | 155,134 | 202 |
| Cao | 24,442 | 699 |
| Rất cao | 26,403 | 2,626 |
🔹 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
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:
🔹 Ý 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.
## === 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ả:
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.
ggplot(customer_stats, aes(x = reorder(Customer_Type, -So_Don_Hang), y = So_Don_Hang, fill = Customer_Type)) +
geom_col(show.legend = FALSE) +
geom_text(aes(label = format(So_Don_Hang, big.mark = ".", scientific = FALSE)),
vjust = -0.2, size = 5) +
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() → 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.
🔹 Ý 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.
customer_stats <- customer_stats %>%
mutate(
label = paste0(round(Ty_Le_Don_Hang, 1), "%")
)
ggplot(customer_stats, aes(x = "", y = Ty_Le_Don_Hang, fill = Customer_Type)) +
geom_col(width = 1, color = "white") +
coord_polar(theta = "y") +
geom_text(
aes(label = label),
position = position_stack(vjust = 0.5),
color = "white",
size = 5,
fontface = "bold"
) +
labs(title = "Tỷ lệ loại khách hàng (%)") +
theme_void() +
theme(
plot.title = element_text(face = "bold", hjust = 0.5, size = 14),
legend.title = element_text(face = "bold")
)🔹 Giải thích code:
ggplot() → 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 đồ.
🔹 Ý 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.
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
ggplot(customer_summary, aes(x = Customer_Type, y = Total_Revenue, fill = Customer_Type)) +
geom_bar(stat = "identity") +
geom_text(aes(label = format(Total_Revenue, big.mark = ".", scientific = FALSE)),
vjust = -0.5, size = 5, color = "black") +
scale_y_continuous(labels = comma, expand = expansion(mult = c(0, 0.12))) +
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() → 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.
🔹 Ý 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.
region_summary <- data %>%
group_by(Region) %>%
summarise(
Total_Orders = n_distinct(Order_ID), # Tổng số đơn hàng
Total_Revenue = sum(Total_Price, na.rm = TRUE), # Tổng doanh thu
Avg_Order_Value = mean(Total_Price, na.rm = TRUE),# Giá trị đơn hàng TB
.groups = 'drop'
) %>%
arrange(desc(Total_Revenue)) %>%
mutate(
Total_Orders = comma(Total_Orders),
Total_Revenue = comma(Total_Revenue, accuracy = 1),
Avg_Order_Value = comma(Avg_Order_Value, accuracy = 1)
)
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 ===
region_summary %>%
kable(
col.names = c("Khu vực", "Tổng đơn hàng", "Tổng doanh thu (VNĐ)", "Giá trị TB/đơn (VNĐ)"),
align = "c"
)| Khu vực | Tổng đơn hàng | Tổng doanh thu (VNĐ) | Giá trị TB/đơn (VNĐ) |
|---|---|---|---|
| Hamburg | 23,426 | 9,619,253 | 137 |
| Hessen | 21,071 | 9,181,452 | 145 |
| Mecklenburg-Vorpommern | 21,414 | 9,120,188 | 142 |
| Saarland | 22,011 | 9,020,347 | 136 |
| Rheinland-Pfalz | 22,668 | 9,011,789 | 133 |
| Berlin | 21,284 | 8,879,189 | 139 |
| Thüringen | 21,830 | 8,734,228 | 134 |
| Bayern | 21,476 | 8,430,479 | 130 |
| Brandenburg | 20,570 | 8,402,955 | 136 |
| Niedersachsen | 22,428 | 8,320,694 | 123 |
| Sachsen-Anhalt | 21,416 | 8,251,296 | 128 |
| Baden-Württemberg | 21,317 | 8,237,277 | 128 |
| Sachsen | 22,213 | 8,213,791 | 123 |
| Schleswig-Holstein | 21,976 | 8,193,415 | 124 |
| Nordrhein-Westfalen | 21,978 | 8,139,463 | 124 |
| Bremen | 22,115 | 7,584,805 | 114 |
Bằng cách nhóm và sắp xếp dữ liệu theo khu vực, biểu đồ cột cho thấy Hamburg và Hessen là hai khu vực mang lại doanh thu cao nhất. Ngược lại, Bremen là khu vực có doanh thu thấp nhất. Thông tin này giúp doanh nghiệp xác định các thị trường trọng điểm để tập trung nguồn lực marketing và bán hàng.
###Phân tích tương quan
## === TƯƠNG QUAN GIỮA TOTAL_PRICE VÀ UNIT_PRICE ===
## [1] 0.6194355
## === TƯƠNG QUAN GIỮA TOTAL_PRICE VÀ QUANTITY ===
## [1] 0.3128655
🔹 Giải thích
Hàm cor(x, y) trong R tính hệ số tương quan Pearson (Pearson correlation coefficient) giữa hai biến số.Giá trị kết quả nằm trong khoảng từ -1 đến +1:
+1 → tương quan tuyến tính hoàn toàn dương (biến này tăng thì biến kia tăng).
0 → không có mối tương quan tuyến tính rõ rệt.
-1 → tương quan tuyến tính hoàn toàn âm (biến này tăng thì biến kia giảm).
🔹 Ý nghĩa thống kê
Tương quan giữa Total_Price và Unit_Price
Giá trị 0.6194 > 0.6, cho thấy mối tương quan dương ở mức trung bình – khá mạnh giữa giá bán đơn vị và tổng giá trị đơn hàng.Khi đơn giá sản phẩm tăng, doanh thu đơn hàng cũng có xu hướng tăng theo. Tuy nhiên, mối quan hệ không hoàn toàn tuyến tính vì doanh thu còn phụ thuộc vào số lượng (Quantity) và mức chiết khấu (Discount).
Tương quan giữa Total_Price và Quantity
Giá trị 0.3129 thể hiện mối tương quan dương yếu – trung bình giữa số lượng bán và doanh thu.Khi số lượng mua tăng, tổng doanh thu có xu hướng tăng, nhưng mức độ không mạnh.
###Phân tích theo thời gian
## === PHÂN TÍCH THEO QUÝ ===
quarter_freq <- table(data$Quarter)
quarter_percentage <- prop.table(quarter_freq) * 100
quarter_freq_fmt <- format(quarter_freq, big.mark = ",", scientific = FALSE)
quarter_percentage_fmt <- format(round(quarter_percentage, 2), big.mark = ".", decimal.mark = ",", scientific = FALSE)
print(quarter_freq_fmt)##
## Q1 Q2 Q3 Q4
## "258,889" "264,162" "263,115" "262,409"
##
## Q1 Q2 Q3 Q4
## "24,69" "25,19" "25,09" "25,03"
## === PHÂN TÍCH THEO MÙA ===
season_analysis <- data %>%
group_by(Season) %>%
summarise(
Total_Orders = n_distinct(Order_ID),
Total_Revenue = sum(Total_Price)
)
season_analysis$Total_Orders <- format(season_analysis$Total_Orders, big.mark = ".", scientific = FALSE)
season_analysis$Total_Revenue <- format(season_analysis$Total_Revenue, big.mark = ".", scientific = FALSE)
print(season_analysis)## # A tibble: 4 × 3
## Season Total_Orders Total_Revenue
## <chr> <chr> <chr>
## 1 Autumn 87.841 34.872.401
## 2 Spring 86.292 33.642.674
## 3 Summer 87.641 34.211.047
## 4 Winter 87.419 34.614.499
## === PHÂN TÍCH THEO NGÀY TRONG TUẦN ===
weekday_analysis <- data %>%
group_by(Day_of_Week) %>%
summarise(
Total_Orders = n_distinct(Order_ID),
Total_Revenue = sum(Total_Price)
) %>%
arrange(desc(Total_Revenue))
# Định dạng các số với dấu phân cách hàng nghìn
weekday_analysis$Total_Orders <- format(weekday_analysis$Total_Orders, big.mark = ".", scientific = FALSE)
weekday_analysis$Total_Revenue <- format(weekday_analysis$Total_Revenue, big.mark = ".", scientific = FALSE)
print(weekday_analysis)## # A tibble: 7 × 3
## Day_of_Week Total_Orders Total_Revenue
## <chr> <chr> <chr>
## 1 Saturday 50.202 19.767.776
## 2 Monday 50.039 19.764.753
## 3 Thursday 49.602 19.700.979
## 4 Sunday 50.152 19.667.161
## 5 Tuesday 49.715 19.572.899
## 6 Wednesday 49.898 19.459.571
## 7 Friday 49.585 19.407.483
🔹 Giải thích
Tỷ lệ đơn hàng theo quý (Quarter)
Sử dụng table() để đếm số đơn hàng theo từng quý (Q1, Q2, Q3, Q4).
Dùng prop.table() tính tỷ lệ phần trăm đơn hàng mỗi quý trong tổng thể. Giúp nhận diện thời điểm hoạt động bán hàng cao nhất/nhiều đơn nhất.
Phân tích theo mùa (Season)
Dùng group_by(Season) để nhóm dữ liệu theo mùa: Winter, Spring, Summer, Autumn.
n_distinct(Order_ID) đếm số đơn hàng duy nhất trong mỗi mùa.
sum(Total_Price) tính tổng doanh thu mỗi mùa.
Giúp nhận biết mùa nào bán chạy nhất và đóng góp nhiều doanh thu nhất.
Phân tích theo ngày trong tuần (Day_of_Week)
Nhóm theo biến Day_of_Week (ví dụ: Monday, Tuesday, …).
Tính tổng số đơn hàng và doanh thu tương tự.
Dùng arrange(desc(Total_Revenue)) để sắp xếp thứ tự từ ngày doanh thu cao nhất đến thấp nhất.
🔹 Ý nghĩa thống kê
Tỷ lệ đơn hàng theo quý (Quarter)
Số lượng đơn hàng giữa các quý gần như cân bằng nhau, dao động quanh 25%. Quý 2 (tháng 4–6) có lượng đơn hàng cao nhất (25.19%), cho thấy hoạt động bán hàng có thể tăng nhẹ vào giữa năm. Giúp doanh nghiệp biết ngày nào trong tuần có doanh thu cao nhất → hỗ trợ lên kế hoạch marketing hoặc khuyến mãi.
Phân tích theo mùa (Season)
Doanh thu cao nhất vào mùa Hè (Summer) → khả năng khách hàng chi tiêu nhiều hơn trong giai đoạn này (có thể do nhu cầu du lịch, giải trí hoặc khuyến mãi giữa năm). Các mùa còn lại có doanh thu khá tương đồng (~34.1 triệu) → không có mùa thấp điểm rõ rệt.
Phân tích theo ngày trong tuần (Day_of_Week)
Thứ Bảy và Thứ Hai là hai ngày có doanh thu cao nhất, đều khoảng 19.76 triệu. Thứ Sáu có doanh thu thấp nhất, nhưng chênh lệch không lớn (~1.8%). Xu hướng này cho thấy doanh nghiệp hoạt động ổn định cả tuần, tuy nhiên có thể tập trung quảng cáo hoặc khuyến mãi vào cuối tuần để tối ưu doanh thu
## Tỷ lệ đơn hàng có giảm giá: 35.63 %
## Số đơn có giảm giá: 373607 / 1048575
## Phạm vi giảm giá: 0 - 0.15
## Trung bình giảm giá: 0.0297
## Median giảm giá: 0
## Độ lệch chuẩn giảm giá: 0.0448
Nhận xét
Tỷ lệ đơn hàng có giảm giá:Có 35.63% đơn hàng được áp dụng giảm giá, tương đương 373,607 trên tổng số 1,048,575 đơn hàng.→ Điều này cho thấy chính sách khuyến mãi được áp dụng khá thường xuyên, chiếm hơn 1/3 tổng số đơn hàng.
Phạm vi giảm giá:Mức giảm giá dao động từ 0 đến 0.15 → Hầu hết mức giảm nằm trong khoảng thấp, cho thấy doanh nghiệp kiểm soát mức chiết khấu ở mức vừa phải
Độ lệch chuẩn = 0.0448, cho thấy mức độ phân tán vừa phải.→ Có sự khác biệt nhất định giữa các đơn hàng về mức chiết khấu, nhưng nhìn chung các giá trị vẫn tập trung quanh mức thấp (0–5%).
## GIẢM GIÁ THEO LOẠI KHÁCH HÀNG
discount_by_customer_type <- data %>%
group_by(Customer_Type) %>%
summarise(
Count = n(),
Discount_Rate = mean(Discount > 0) * 100,
Avg_Discount = mean(Discount),
Avg_Discount_When_Applied = mean(Discount[Discount > 0]),
Total_Discount_Value = sum(Unit_Price * Quantity * Discount)
)
# Định dạng các số để dễ đọc hơn
discount_by_customer_type$Count <- format(discount_by_customer_type$Count, big.mark = ",", scientific = FALSE)
discount_by_customer_type$Discount_Rate <- format(round(discount_by_customer_type$Discount_Rate, 2), big.mark = ",", decimal.mark = ".", scientific = FALSE)
discount_by_customer_type$Avg_Discount <- format(round(discount_by_customer_type$Avg_Discount, 4), big.mark = ",", decimal.mark = ".", scientific = FALSE)
discount_by_customer_type$Avg_Discount_When_Applied <- format(round(discount_by_customer_type$Avg_Discount_When_Applied, 4), big.mark = ",", decimal.mark = ".", scientific = FALSE)
discount_by_customer_type$Total_Discount_Value <- format(discount_by_customer_type$Total_Discount_Value, big.mark = ",", scientific = FALSE)
print(discount_by_customer_type)## # A tibble: 2 × 6
## Customer_Type Count Discount_Rate Avg_Discount Avg_Discount_When_Applied
## <fct> <chr> <chr> <chr> <chr>
## 1 B2B 373,607 "100" 0.0834 "0.0834"
## 2 B2C 674,968 " 0" 0.0000 " NaN"
## # ℹ 1 more variable: Total_Discount_Value <chr>
Giải thích group_by(Customer_Type) → Chia dữ liệu thành từng nhóm khách hàng (ví dụ: B2B và B2C).
Count = n()→ Đếm tổng số dòng (đơn hàng) trong mỗi nhóm khách hàng.
mean() → Tính giá trị trung bình.
sum() → Tính tổng các giá trị trong nhóm.
format() → Dùng để định dạng hiển thị cho đẹp, dễ đọc.
round() → Làm tròn số đến số chữ số thập phân mong muốn.
## GIẢM GIÁ THEO DANH MỤC SẢN PHẨM
discount_by_category <- data %>%
group_by(Category) %>%
summarise(
Total_Items = n(),
Discount_Rate = mean(Discount > 0) * 100,
Avg_Discount = mean(Discount),
Max_Discount = max(Discount),
Total_Discount_Amount = sum(Total_Price * Discount / (1 - Discount))
) %>%
arrange(desc(Avg_Discount))
# Định dạng các cột số
discount_by_category$Total_Items <- format(discount_by_category$Total_Items, big.mark = ".", scientific = FALSE)
discount_by_category$Discount_Rate <- format(round(discount_by_category$Discount_Rate, 2), big.mark = ".", decimal.mark = ",", scientific = FALSE)
discount_by_category$Avg_Discount <- format(round(discount_by_category$Avg_Discount, 4), big.mark = ".", decimal.mark = ",", scientific = FALSE)
discount_by_category$Max_Discount <- format(round(discount_by_category$Max_Discount, 4), big.mark = ".", decimal.mark = ",", scientific = FALSE)
discount_by_category$Total_Discount_Amount <- format(round(discount_by_category$Total_Discount_Amount), big.mark = ".", decimal.mark = ",", scientific = FALSE)
print(discount_by_category)## # A tibble: 4 × 6
## Category Total_Items Discount_Rate Avg_Discount Max_Discount
## <fct> <chr> <chr> <chr> <chr>
## 1 Alcoholic Beverages 262.451 35,66 0,0298 0,15
## 2 Water 261.612 35,67 0,0297 0,15
## 3 Soft Drinks 262.592 35,63 0,0297 0,15
## 4 Juices 261.920 35,56 0,0297 0,15
## # ℹ 1 more variable: Total_Discount_Amount <chr>
Giải thích code
group_by(Category)→ Nhóm dữ liệu theo danh mục sản phẩm (Category) — để tính toán riêng từng nhóm.
summarise() → Tạo bảng tóm tắt với các chỉ số
arrange(desc(Avg_Discount))→ Sắp xếp kết quả theo mức giảm giá trung bình giảm dần
## GIẢM GIÁ THEO KHU VỰC
discount_by_region <- data %>%
group_by(Region) %>%
summarise(
Orders = n(),
Discount_Rate = mean(Discount > 0) * 100,
Avg_Discount = mean(Discount),
Total_Discount_Value = sum(Unit_Price * Quantity * Discount)
) %>%
arrange(desc(Avg_Discount))
# Định dạng dấu phân cách số theo chuẩn Việt Nam
discount_by_region$Orders <- format(discount_by_region$Orders, big.mark = ".", scientific = FALSE)
discount_by_region$Discount_Rate <- format(round(discount_by_region$Discount_Rate, 2), big.mark = ".", decimal.mark = ",", scientific = FALSE)
discount_by_region$Avg_Discount <- format(round(discount_by_region$Avg_Discount, 4), big.mark = ".", decimal.mark = ",", scientific = FALSE)
discount_by_region$Total_Discount_Value <- format(round(discount_by_region$Total_Discount_Value), big.mark = ".", decimal.mark = ",", scientific = FALSE)
print(discount_by_region)## # A tibble: 16 × 5
## Region Orders Discount_Rate Avg_Discount Total_Discount_Value
## <fct> <chr> <chr> <chr> <chr>
## 1 Hessen 63.475 39,57 0,0331 769.901
## 2 Mecklenburg-Vorpommern 64.038 38,32 0,0320 775.522
## 3 Saarland 66.260 37,77 0,0316 757.674
## 4 Hamburg 70.310 37,01 0,0308 804.160
## 5 Rheinland-Pfalz 67.849 36,33 0,0303 746.976
## 6 Brandenburg 61.977 36,12 0,0303 693.923
## 7 Berlin 64.014 36,07 0,0301 737.951
## 8 Bremen 66.457 35,99 0,0301 612.317
## 9 Thüringen 64.979 35,75 0,0298 712.336
## 10 Sachsen-Anhalt 64.333 35,49 0,0296 674.104
## 11 Bayern 64.643 34,80 0,0291 699.183
## 12 Baden-Württemberg 64.249 34,77 0,0289 668.347
## 13 Nordrhein-Westfalen 65.772 34,14 0,0285 640.649
## 14 Sachsen 66.721 32,84 0,0274 639.960
## 15 Schleswig-Holstein 65.841 32,81 0,0274 654.470
## 16 Niedersachsen 67.657 32,50 0,0271 651.956
Giải thích
group_by(Region)→ Nhóm dữ liệu theo khu vực bán hàng (Region)
summarise() → Tạo bảng tóm tắt gồm các chỉ số cho từng khu vực
arrange(desc(Avg_Discount))→ Sắp xếp các khu vực theo mức giảm giá trung bình giảm dần
format() → Dùng để hiển thị số đẹp
round() → Làm tròn số cho gọn
quantity_discount_analysis <- data %>%
mutate(Quantity_Group = cut(Quantity,
breaks = c(0, 10, 50, 100, Inf),
labels = c("1-10", "11-50", "51-100", "100+"))) %>%
group_by(Quantity_Group) %>%
summarise(
Orders = n(),
Avg_Discount = mean(Discount),
Discount_Rate = mean(Discount > 0) * 100
)
# Định dạng kết quả với dấu phân cách số
quantity_discount_analysis$Orders <- format(quantity_discount_analysis$Orders, big.mark = ".", scientific = FALSE)
quantity_discount_analysis$Avg_Discount <- format(round(quantity_discount_analysis$Avg_Discount, 4), big.mark = ".", decimal.mark = ",", scientific = FALSE)
quantity_discount_analysis$Discount_Rate <- format(round(quantity_discount_analysis$Discount_Rate, 2), big.mark = ".", decimal.mark = ",", scientific = FALSE)
print(quantity_discount_analysis)## # A tibble: 3 × 4
## Quantity_Group Orders Avg_Discount Discount_Rate
## <fct> <chr> <chr> <chr>
## 1 1-10 486.919 0,0048 " 7,70"
## 2 11-50 374.681 0,0277 " 39,81"
## 3 51-100 186.975 0,0986 "100,00"
Giải thích
cut() chia biến Quantity (số lượng mua) thành các nhóm
group_by(Quantity_Group) → Gom nhóm dữ liệu theo cột Quantity_Group
summarise() → Tạo bảng tóm tắt gồm các chỉ số theo từng nhóm số lượng
format() + round() → Dùng để hiển thị kết quả dễ đọc
library(ggplot2)
library(dplyr)
library(tidyr)
library(lubridate)
library(scales)
library(gridExtra)
library(RColorBrewer)
library(kableExtra)p1 <- data %>%
group_by(Customer_Type) %>%
summarise(Total_Revenue = sum(Total_Price)) %>%
ggplot(aes(x = Customer_Type, y = Total_Revenue, fill = Customer_Type)) +
geom_col() +
geom_text(aes(label = comma(Total_Revenue)), vjust = -0.5) +
labs(title = "Doanh thu theo Loại khách hàng",
x = "Loại khách hàng", y = "Tổng doanh thu") +
scale_y_continuous(labels = comma) +
theme_minimal()
print(p1)🔸 Giải thích code:
group_by(Region) → gom nhóm dữ liệu theo khu vực.
summarise(Total_Revenue = sum(Total_Price)) → tính tổng doanh thu của từng khu vực.
ggplot(aes(…)) → khởi tạo đồ thị.
geom_col() → vẽ biểu đồ cột thể hiện doanh thu.
coord_flip() → xoay ngang giúp đọc tên khu vực rõ hơn.
geom_text() → chèn nhãn số doanh thu lên từng cột.
theme_minimal() → dùng giao diện tối giản, đẹp và rõ.
📊 Nhận xét:
Sự chênh lệch lớn về Doanh thu: Có một sự khác biệt rất lớn về tổng doanh thu giữa hai loại khách hàng.Doanh thu B2B chiếm ưu thế vượt trội: Khách hàng loại B2B (Business-to-Business) mang lại doanh thu là 105,150,854, cao hơn rất nhiều so với khách hàng loại B2C (Business-to-Consumer).
Doanh thu B2C thấp hơn đáng kể: Khách hàng loại B2C chỉ đóng góp doanh thu là 32,189,768.
p2 <- data %>%
group_by(Region) %>%
summarise(Total_Revenue = sum(Total_Price)) %>%
arrange(desc(Total_Revenue)) %>%
ggplot(aes(x = reorder(Region, Total_Revenue), y = Total_Revenue, fill = Region)) +
geom_col() +
geom_text(aes(label = comma(round(Total_Revenue, 0))),
hjust = -0.1, size = 3.5, color = "black") +
coord_flip() +
labs(title = "Doanh thu theo Khu vực",
x = "Khu vực", y = "Tổng doanh thu") +
scale_y_continuous(labels = comma, expand = expansion(mult = c(0, 0.15))) +
theme_minimal() +
theme(legend.position = "none")
print(p2)🔸 Giải thích:
group_by(Region): Gom nhóm dữ liệu theo từng khu vực.
summarise(Total_Revenue = sum(Total_Price)): Tính tổng doanh thu (Total_Revenue) cho mỗi khu vực.
arrange(desc(Total_Revenue)): Sắp xếp khu vực theo thứ tự giảm dần doanh thu.
ggplot(…) + geom_col(): Vẽ biểu đồ cột với trục X là tên khu vực, trục Y là tổng doanh thu.
coord_flip(): Lật ngang biểu đồ để dễ đọc khi có nhiều khu vực.
scale_y_continuous(labels = comma): Hiển thị số liệu có dấu phẩy phân cách hàng nghìn.
theme_minimal(): Giao diện biểu đồ tối giản, sạch đẹp.
📊 Nhận xét:
Khu vực dẫn đầu: Hamburg là khu vực có tổng doanh thu cao nhất, vượt trội hơn hẳn so với các khu vực khác.
Các khu vực đóng góp lớn: Sau Hamburg, các khu vực như Hessen, Mecklenburg-Vorpommern, Saarland, Rheinland-Pfalz, và Berlin cũng là những nơi có doanh thu rất cao, nằm trong top đầu.
Khu vực có doanh thu thấp nhất: Bremen có vẻ là khu vực có tổng doanh thu thấp nhất trong danh sách.
p3 <- data %>%
group_by(Customer_ID) %>%
summarise(Total_Revenue = sum(Total_Price)) %>%
arrange(desc(Total_Revenue)) %>%
head(10) %>%
ggplot(aes(x = reorder(Customer_ID, Total_Revenue), y = Total_Revenue, fill = Customer_ID)) +
geom_col() +
geom_text(aes(label = comma(round(Total_Revenue, 0))),
hjust = -0.1, size = 3.5, color = "black") +
coord_flip() +
labs(title = "Top 10 khách hàng doanh thu cao nhất",
x = "Mã khách hàng", y = "Doanh thu") +
scale_y_continuous(labels = comma, expand = expansion(mult = c(0, 0.15))) +
theme_minimal() +
theme(legend.position = "none")
print(p3)🔹 Giải thích code:
group_by(Customer_ID) → Gom nhóm dữ liệu theo từng mã khách hàng.
summarise(Total_Revenue = sum(Total_Price)) → Tính tổng doanh thu của mỗi khách hàng.
arrange(desc(Total_Revenue)) → Sắp xếp danh sách theo doanh thu giảm dần.
head(10) → Lấy 10 khách hàng đầu tiên, tức Top 10 khách hàng doanh thu cao nhất.
ggplot(…) + geom_col() → Vẽ biểu đồ cột thể hiện doanh thu của từng khách hàng.
coord_flip() → Lật ngang biểu đồ để dễ quan sát mã khách hàng.
scale_y_continuous(labels = comma) → Hiển thị số doanh thu có dấu phẩy phân cách hàng nghìn.
📊 Nhận xét:
Khách hàng số 1: Mã khách hàng CUS3005 là khách hàng quan trọng nhất, mang lại doanh thu cao nhất, vượt xa các khách hàng còn lại. Doanh thu của CUS3005 nằm ở khoảng 75,000 đơn vị (có thể là tiền tệ).
Top 3 Khách hàng: Ba khách hàng hàng đầu là CUS3005, CUS7626, và CUS7825. Ba khách hàng này tạo ra sự khác biệt rõ rệt về doanh thu so với nhóm khách hàng còn lại. CUS7626 và CUS7825 có doanh thu lần lượt khoảng 70,000 và 67,000.
p4 <- data %>%
mutate(
Date = as.Date(Order_Date, format = "%d/%m/%Y"),
Year = format(Date, "%Y"),
Quarter = paste0("Q", ceiling(as.numeric(format(Date, "%m"))/3)),
YearQuarter = paste(Year, Quarter, sep = "-")
) %>%
group_by(YearQuarter) %>%
summarise(Quarterly_Revenue = sum(Total_Price), .groups = "drop") %>%
ggplot(aes(x = YearQuarter, y = Quarterly_Revenue, group = 1)) +
geom_line(color = "steelblue", size = 1) +
geom_point(color = "steelblue") +
labs(title = "Doanh thu theo Quý",
x = "Quý-Năm", y = "Doanh thu") +
scale_y_continuous(labels = scales::comma) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
print(p4)🔹 Giải thích code:
mutate()→ chuyển cột Order_Date sang định dạng ngày-tháng-năm, sau đó trích xuất năm-tháng (YYYY-MM) để tổng hợp doanh thu theo từng tháng. group_by(YearMonth) → Gom nhóm dữ liệu theo từng tháng-năm.
summarise(Monthly_Revenue = sum(Total_Price)) → Tính tổng doanh thu của mỗi tháng.
ggplot(aes(x = YearMonth, y = Monthly_Revenue, group = 1)) → Khởi tạo biểu đồ, trục X là tháng-năm, trục Y là doanh thu.
geom_line(color = “steelblue”, size = 1) → Vẽ đường biểu diễn doanh thu theo thời gian (đường màu xanh thép).
geom_point(color = “steelblue”) → Thêm các điểm dữ liệu để dễ quan sát từng tháng . labs(…) → Đặt tiêu đề và tên cho trục X/Y.
scale_y_continuous(labels = scales::comma) → Hiển thị dấu phẩy ngăn cách hàng nghìn trên trục doanh thu.
📊 Nhận xét:
Xu hướng Tăng trưởng: Nhìn chung, doanh thu có một xu hướng tăng nhẹ qua các năm. Mặc dù có nhiều biến động, mức doanh thu trung bình hàng tháng đã cao hơn trong giai đoạn cuối (năm 2023) so với giai đoạn đầu (năm 2021).
Tháng 12/2022 là đỉnh cao nhất.
Tháng 01/2023 sụt giảm mạnh từ đỉnh.
p5 <- data %>%
distinct(Order_ID, Region) %>%
count(Region) %>%
ggplot(aes(x = reorder(Region, n), y = n, fill = Region)) +
geom_col() +
coord_flip() +
labs(title = "Số lượng đơn hàng theo Khu vực",
x = "Khu vực", y = "Số đơn hàng") +
theme_minimal() +
theme(legend.position = "none")
print(p5)🔹 Giải thích code:
distinct(Order_ID, Region) → Giữ lại các đơn hàng duy nhất
count(Region) → Đếm số lượng đơn hàng của từng khu vực.
ggplot(aes(x = reorder(Region, n), y = n, fill = Region)) → Khởi tạo biểu đồ, trục X là khu vực, trục Y là số đơn hàng.
Hàm reorder() giúp sắp xếp khu vực theo số lượng đơn hàng tăng hoặc giảm.
geom_col() → Tạo biểu đồ cột, chiều cao của mỗi cột thể hiện số lượng đơn hàng.
coord_flip() → Lật ngang biểu đồ, giúp dễ đọc tên khu vực khi nhiều nhãn.
📊 Nhận xét:
Vị trí số 1: Hamburg tiếp tục là khu vực dẫn đầu, giống như trong biểu đồ Doanh thu, với số lượng đơn hàng cao nhất, vượt qua mốc 20,000 đơn hàng.
Top tiếp theo: Rheinland-Pfalz và Niedersachsen là hai khu vực có số lượng đơn hàng cao tiếp theo, sát sao với Hamburg.
p6 <- data %>%
group_by(Category) %>%
summarise(Total_Revenue = sum(Total_Price)) %>%
ggplot(aes(x = reorder(Category, Total_Revenue), y = Total_Revenue, fill = Category)) +
geom_col() +
coord_flip() +
labs(title = "Doanh thu theo Nhóm sản phẩm",
x = "Nhóm sản phẩm", y = "Doanh thu") +
scale_y_continuous(labels = comma) +
theme_minimal() +
theme(legend.position = "none")
print(p6)🔹 Giải thích code:
group_by(Category) → Gom nhóm dữ liệu theo từng nhóm sản phẩm
summarise(Total_Revenue = sum(Total_Price)) → Tính tổng doanh thu của mỗi nhóm sản phẩm.
ggplot(aes(x = reorder(Category, Total_Revenue), y = Total_Revenue, fill = Category)) → Thiết lập biểu đồ, trục X là nhóm sản phẩm, trục Y là tổng doanh thu.
Hàm reorder() giúp sắp xếp nhóm theo giá trị doanh thu tăng dần hoặc giảm dần.
geom_col() → Vẽ biểu đồ cột, chiều cao của cột thể hiện doanh thu.
coord_flip() → Lật biểu đồ nằm ngang giúp dễ đọc tên sản phẩm.
labs(…) → Đặt tiêu đề và tên trục rõ ràng, dễ hiểu.
📊 Nhận xét:
Alcoholic Beverages” (Đồ uống có cồn) là nhóm sản phẩm thống trị hoàn toàn về doanh thu. Thanh ngang của nhóm này dài hơn đáng kể so với tổng doanh thu của ba nhóm còn lại cộng lại.
Doanh thu từ “Alcoholic Beverages” ước tính nằm ở mức khoảng 105,000,000 (tương đương với tổng doanh thu B2B đã phân tích trước đó).
“Juices” (Nước ép/Nước trái cây) là nhóm sản phẩm đứng thứ hai về doanh thu, nhưng chỉ đạt khoảng 15,000,000 (chênh lệch rất lớn so với nhóm dẫn đầu).
“Soft Drinks” (Nước ngọt/Nước giải khát) đứng thứ ba, với doanh thu thấp hơn “Juices”, khoảng 10,000,000.
“Water” (Nước uống đóng chai) là nhóm sản phẩm có doanh thu thấp nhất, chỉ khoảng 7,000,000.
p7 <- data %>%
ggplot(aes(x = Discount, y = Total_Price)) +
geom_point(alpha = 0.6, color = "steelblue") +
geom_smooth(method = "lm", color = "red", se = FALSE) +
labs(title = "Mối quan hệ: Chiết khấu vs Doanh thu",
x = "Tỷ lệ chiết khấu", y = "Doanh thu") +
scale_y_continuous(labels = comma) +
theme_minimal()
print(p7)🔹 Giải thích code: ggplot(aes(x = Discount, y = Total_Price)) →Thiết lập dữ liệu cho biểu đồ:
geom_point(alpha = 0.6, color = “steelblue”) → Vẽ biểu đồ phân tán (scatter plot), mỗi điểm là một đơn hàng.
alpha = 0.6: làm trong suốt các điểm để dễ nhìn khi chồng lấp.
color = “steelblue”: chọn màu xanh dịu cho các điểm.
geom_smooth(method = “lm”, color = “red”, se = FALSE) → Thêm đường hồi quy tuyến tính (linear model) để thể hiện xu hướng tổng thể giữa chiết khấu và doanh thu.
📊 Nhận xét:
Các mức chiết khấu phổ biến: Dữ liệu tập trung gần như hoàn toàn ở bốn mức chiết khấu rời rạc: 0%, 5% (0.05), 10% (0.10), và 15% (0.15). Điều này cho thấy công ty chỉ áp dụng các mức chiết khấu cố định, không có các mức chiết khấu lẻ tẻ khác.
Chiết khấu cao nhất: Mức 15% là mức chiết khấu cao nhất được áp dụng.
Không có mối quan hệ tuyến tính rõ rệt: Biểu đồ cho thấy doanh thu không tăng theo tỷ lệ chiết khấu một cách rõ ràng.
Xu hướng yếu: Đường hồi quy tuyến tính (màu đỏ) nằm gần như nằm ngang, chỉ dốc lên một chút.
p8 <- data %>%
group_by(Product) %>%
summarise(Total_Revenue = sum(Total_Price)) %>%
arrange(desc(Total_Revenue)) %>%
head(10) %>%
ggplot(aes(x = reorder(Product, Total_Revenue), y = Total_Revenue, fill = Product)) +
geom_col() +
geom_text(aes(label = format(round(Total_Revenue, 0), big.mark = ".", scientific = FALSE)),
hjust = -0.1, size = 4, color = "black") +
coord_flip() +
labs(title = "Top 10 sản phẩm doanh thu cao nhất",
x = "Sản phẩm", y = "Doanh thu") +
scale_y_continuous(labels = comma, expand = expansion(mult = c(0, 0.15))) +
theme_minimal() +
theme(legend.position = "none")
print(p8)🔹 Giải thích code:
group_by(Product) → Gom nhóm dữ liệu theo từng sản phẩm riêng biệt.
summarise(Total_Revenue = sum(Total_Price)) → Tính tổng doanh thu của mỗi sản phẩm.
arrange(desc(Total_Revenue)) → Sắp xếp doanh thu giảm dần, từ cao nhất đến thấp nhất.
head(10) → Giữ lại 10 sản phẩm đầu tiên — tức là top 10 có doanh thu cao nhất.
fill = Product: tô màu khác nhau cho từng sản phẩm.
geom_col() → Vẽ biểu đồ cột, chiều cao thể hiện doanh thu.
coord_flip() → Lật biểu đồ nằm ngang để dễ đọc tên sản phẩm.
📊 Nhận xét:
Thống trị của Champagne/Rượu mạnh: Toàn bộ 7 sản phẩm đứng đầu đều là các loại đồ uống có cồn (Champagne, Scotch, Whiskey, Gin, Rum), khẳng định lại nhận xét từ biểu đồ “Doanh thu theo Nhóm sản phẩm” trước đó: công ty phụ thuộc rất lớn vào nhóm sản phẩm “Alcoholic Beverages”.
p9 <- data %>%
group_by(Region, Customer_Type) %>%
summarise(Total_Revenue = sum(Total_Price)) %>%
ggplot(aes(x = Region, y = Customer_Type, fill = Total_Revenue)) +
geom_tile() +
scale_fill_gradient(low = "white", high = "steelblue", labels = comma) +
labs(title = "9. Heatmap: Doanh thu theo Khu vực & Loại KH",
x = "Khu vực", y = "Loại khách hàng", fill = "Doanh thu") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
print(p9)🔹 Giải thích code:
group_by(Region, Customer_Type) → Gom nhóm dữ liệu theo từng cặp Khu vực – Loại khách hàng.
summarise(Total_Revenue = sum(Total_Price)) → Tính tổng doanh thu cho mỗi nhóm vừa được tạo.
ggplot(aes(x = Region, y = Customer_Type, fill = Total_Revenue)) → Xác định các trục của heatmap:
fill: giá trị màu thể hiện mức doanh thu (màu đậm = doanh thu cao, màu nhạt = thấp).
geom_tile() → Vẽ ô vuông (tile) tương ứng với từng cặp giá trị (Region – Customer_Type).
📊 Nhận xét:
Doanh thu B2B: Hàng ngang đại diện cho B2B (Business-to-Business) có màu sắc đậm đồng đều trên tất cả các khu vực, cho thấy doanh thu từ phân khúc này là rất cao ở mọi nơi.
Doanh thu B2C: Hàng ngang đại diện cho B2C (Business-to-Consumer) có màu sắc rất nhạt (gần như trắng) trên tất cả các khu vực, xác nhận rằng doanh thu từ phân khúc này là không đáng kể hoặc rất thấp.
p10 <- data %>%
group_by(Region) %>%
summarise(Avg_Revenue = mean(Total_Price)) %>%
ggplot(aes(x = reorder(Region, Avg_Revenue), y = Avg_Revenue, fill = Region)) +
geom_col() +
coord_flip() +
labs(title = " Doanh thu trung bình theo Khu vực",
x = "Khu vực", y = "Doanh thu trung bình") +
scale_y_continuous(labels = comma) +
theme_minimal() +
theme(legend.position = "none")
print(p10)🔹 Giải thích code: group_by(Region) → Gom nhóm dữ liệu theo từng khu vực địa lý
summarise(Avg_Revenue = mean(Total_Price)) → Tính doanh thu trung bình trên mỗi đơn hàng trong từng khu vực.
ggplot(aes(x = reorder(Region, Avg_Revenue), y = Avg_Revenue, fill = Region)) → Thiết lập trục
fill = Region: tô màu riêng cho từng khu vực.
geom_col() → Vẽ biểu đồ cột, chiều cao thể hiện doanh thu trung bình.
coord_flip() → Lật trục để biểu đồ nằm ngang → dễ đọc tên khu vực hơn.
📊 Nhận xét:
Dẫn đầu về Giá trị Trung bình: Các khu vực Hessen và Mecklenburg-Vorpommern là hai nơi có doanh thu trung bình trên mỗi giao dịch cao nhất, vượt xa các khu vực khác.
set.seed(123)
data$Sales_Channel <- sample(c("Online", "Offline", "Partner", "Direct"),
nrow(data), replace = TRUE,
prob = c(0.4, 0.3, 0.2, 0.1))
p11 <- data %>%
group_by(Sales_Channel) %>%
summarise(Total_Revenue = sum(Total_Price)) %>%
ggplot(aes(x = reorder(Sales_Channel, Total_Revenue), y = Total_Revenue, fill = Sales_Channel)) +
geom_col() +
geom_text(aes(label = format(round(Total_Revenue, 0), big.mark = ".", scientific = FALSE)),
hjust = 1.1, size = 4, color = "white") + # Số nằm trong cột, chữ màu trắng nổi bật
coord_flip() +
labs(title = "Doanh thu theo Kênh bán hàng",
x = "Kênh bán hàng", y = "Doanh thu") +
scale_y_continuous(labels = comma) +
theme_minimal() +
theme(legend.position = "none")
print(p11)🔹 Giải thích code:
set.seed(123) → Giữ kết quả ngẫu nhiên cố định (để chạy lại cho ra cùng kết quả).
sample(…) → Tạo ngẫu nhiên cột “Sales_Channel” gồm 4 loại kên
prob = c(0.4, 0.3, 0.2, 0.1) → Xác suất phân bổ (40% đơn hàng là online, 30% offline, 20% partner, 10% direct).
replace = TRUE → Cho phép chọn lặp lại để đảm bảo đủ số dòng cho toàn bộ dataset.
📊 Nhận xét:
Kênh Online Dẫn đầu Tuyệt đối: Kênh Online mang lại doanh thu cao nhất, đạt khoảng 52,000,000 đơn vị. Điều này cho thấy công ty đã tận dụng rất hiệu quả các nền tảng kỹ thuật số hoặc thương mại điện tử.
Kênh Offline Quan trọng: Kênh Offline (bán hàng truyền thống/trực tiếp tại cửa hàng) đứng thứ hai với doanh thu khoảng 42,000,000. Đây là một kênh đóng góp đáng kể và là trụ cột quan trọng thứ hai.
p12 <- data %>%
mutate(Discount_Group = cut(Discount, breaks = c(-0.1, 0, 0.05, 0.1, 0.15, 1),
labels = c("0%", "1-5%", "6-10%", "11-15%", ">15%"))) %>%
ggplot(aes(x = Discount_Group, y = Total_Price, fill = Discount_Group)) +
geom_boxplot() +
labs(title = "Phân phối Doanh thu theo Mức chiết khấu",
x = "Mức chiết khấu", y = "Doanh thu") +
scale_y_continuous(labels = comma) +
theme_minimal() +
theme(legend.position = "none")
print(p12)🔹 Giải thích code: cut() → chia biến Discount thành 5 nhóm phần trăm chiết khấu:
geom_boxplot() → hiển thị phân bố doanh thu trong từng nhóm chiết khấu
Đường giữa hộp là trung vị
Hộp là khoảng tứ phân vị (Q1–Q3)
Điểm ngoài hộp là ngoại lệ
📊 Nhận xét:
Phân phối doanh thu cực thấp: Tại tất cả các mức chiết khấu (0%, 1-5%, 6-10%, 11-15%), phần lớn các giao dịch đều có doanh thu rất thấp. Điều này có nghĩa là 50% số giao dịch ở mỗi mức chiết khấu đều có doanh thu xấp xỉ 0 hoặc rất gần 0 (doanh thu rất nhỏ).
Tại các mức chiết khấu 1-5%, 6-10%, và 11-15%, có một số lượng lớn các điểm dữ liệu nằm rất xa hộp (các chấm đen). Những điểm này đại diện cho các giao dịch có doanh thu rất cao, lên tới trên 12,500. Điều này khẳng định nhận xét từ biểu đồ phân tán trước đó: các giao dịch mang lại doanh thu cao nhất (đơn hàng lớn) đều yêu cầu phải có chiết khấu.
region_top5 <- data %>%
group_by(Region) %>%
summarise(Total_Revenue = sum(Total_Price)) %>%
arrange(desc(Total_Revenue)) %>%
head(5)
p13 <- region_top5 %>%
mutate(Percentage = Total_Revenue / sum(Total_Revenue) * 100) %>%
ggplot(aes(x = 2, y = Percentage, fill = Region)) +
geom_col() +
coord_polar("y") +
xlim(0.5, 2.5) +
geom_text(aes(label = paste0(Region, "\n", round(Percentage, 1), "%")),
position = position_stack(vjust = 0.5), size = 3) +
scale_fill_brewer(palette = "Blues") +
labs(title = "Top 5 khu vực doanh thu cao nhất") +
theme_void() +
theme(legend.position = "bottom")
print(p13)🔹 Giải thích code:
coord_polar(“y”) → chuyển biểu đồ cột thành hình tròn (pie/doughnut).
xlim(0.5, 2.5) → tạo khoảng trống ở giữa để thành “doughnut”.
📊 Nhận xét:
Tỷ trọng cao: Top 5 khu vực này đóng góp một tỷ lệ cực kỳ cao trong tổng doanh thu của công ty (Mặc dù không có tổng phần trăm, nhưng mức đóng góp của từng khu vực đều xấp xỉ 20%, cho thấy Top 5 này gần như chiếm toàn bộ hoặc phần lớn tổng doanh thu).
library(dplyr)
library(ggplot2)
growth_data_quarter <- data %>%
mutate(
Date = as.Date(Order_Date, format = "%d/%m/%Y"),
YearQuarter = paste(format(Date, "%Y"), "Q", ceiling(as.numeric(format(Date, "%m"))/3), sep = "")
) %>%
group_by(YearQuarter) %>%
summarise(Quarterly_Revenue = sum(Total_Price), .groups = "drop") %>%
arrange(YearQuarter) %>%
mutate(Growth_Rate = (Quarterly_Revenue / lag(Quarterly_Revenue) - 1) * 100)
p14_quarter <- growth_data_quarter %>%
ggplot(aes(x = YearQuarter, y = Growth_Rate, group = 1)) +
geom_col(fill = ifelse(growth_data_quarter$Growth_Rate >= 0, "steelblue", "red"), alpha = 0.7) +
geom_text(aes(label = sprintf("%.2f%%", Growth_Rate)),
vjust = ifelse(growth_data_quarter$Growth_Rate >= 0, -0.3, 1.3),
size = 3) +
geom_hline(yintercept = 0, linetype = "dashed", color = "black") +
labs(title = "Tỷ lệ tăng trưởng doanh thu theo quý",
x = "Quý-Năm", y = "Tỷ lệ tăng trưởng (%)") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
print(p14_quarter)🔹 Giải thích code:
mutate()→ Chuyển cột Order_Date sang dạng tháng-năm
group_by(YearMonth)→ Gom nhóm dữ liệu theo từng tháng-năm.
summarise()→ Tính tổng doanh thu mỗi tháng.
mutate(Growth_Rate = (Monthly_Revenue / lag(Monthly_Revenue) - 1) * 100) → Tính tỷ lệ tăng trưởng doanh thu so với tháng trước
Dòng fill = ifelse(growth_data$Growth_Rate >= 0, “steelblue”, “red”)→ Cột màu xanh khi tăng trưởng dương, màu đỏ khi tăng trưởng âm.
geom_hline(yintercept = 0, linetype = “dashed”) → Vẽ đường ngang tại mức 0%, giúp dễ phân biệt giữa tăng và giảm.
📊 Nhận xét:
Biến động lớn: Tỷ lệ tăng trưởng thay đổi rất mạnh giữa các tháng, dao động từ mức giảm khoảng -10% đến tăng hơn +12%. Điều này phản ánh lại sự biến động mạnh mẽ của doanh thu theo thời gian đã được phân tích trước đó.
Tăng trưởng không ổn định: Trong 3 năm, số tháng có tăng trưởng dương và tăng trưởng âm là tương đối xen kẽ và không ổn định.
numeric_data <- data %>%
select(Unit_Price, Quantity, Discount, Total_Price)
correlation_matrix <- cor(numeric_data)
p15 <- as.data.frame(correlation_matrix) %>%
mutate(Var1 = rownames(correlation_matrix)) %>%
pivot_longer(cols = -Var1, names_to = "Var2", values_to = "Correlation") %>%
ggplot(aes(x = Var1, y = Var2, fill = Correlation)) +
geom_tile() +
geom_text(aes(label = round(Correlation, 2)), color = "white", size = 4) +
scale_fill_gradient2(low = "red", high = "blue", mid = "white",
midpoint = 0, limits = c(-1, 1)) +
labs(title = "Ma trận tương quan giữa các biến số",
x = "", y = "") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
print(p15)🔹 Giải thích code:
as.data.frame()→ chuyển ma trận sang dạng bảng (data frame).
mutate(Var1 = rownames(correlation_matrix)) → tạo cột mới Var1 lưu tên biến của từng hàng.
pivot_longer() → chuyển ma trận tương quan từ dạng rộng sang dạng dài (long format), để ggplot có thể vẽ được (mỗi ô = 1 cặp biến).
geom_tile() → tạo ô màu cho từng cặp biến theo giá trị tương quan.
geom_text() → ghi giá trị tương quan (làm tròn 2 chữ số) lên mỗi ô, chữ trắng để dễ nhìn.
scale_fill_gradient2()→ chia màu thành ba mức.
📊 Nhận xét:
Discount & Unit_Price có Tương quan Hoàn hảo (\(r=1.0\)): Mức chiết khấu áp dụng có mối quan hệ tuyến tính hoàn hảo với Đơn giá. Điều này cho thấy chính sách chiết khấu được xác định trực tiếp và đồng nhất dựa trên giá trị của sản phẩm.
Discount & Quantity có Tương quan Rất mạnh (\(r=0.82\)): Chiết khấu là một đòn bẩy cực kỳ hiệu quả để bán được Số lượng lớn sản phẩm. Khi chiết khấu tăng, số lượng mua trong giao dịch cũng tăng mạnh theo.
Unit_Price & Total_Price có Tương quan Mạnh (\(r=0.62\)): Các giao dịch có Đơn giá sản phẩm cao hơn thường dẫn đến Tổng giá trị giao dịch cao hơn . Quantity & Total_Price có Tương quan Yếu (\(r=0.31\)): Số lượng mua tăng không tác động mạnh đến Tổng giá trị giao dịch. Điều này gợi ý rằng việc tăng Số lượng thông qua Chiết khấu lớn đã làm giảm hiệu quả lợi nhuận, khiến Tổng giá không tăng tương ứng.
p16 <- data %>%
group_by(Region, Customer_Type) %>%
summarise(Total_Revenue = sum(Total_Price), .groups = "drop") %>%
group_by(Region) %>%
mutate(Percentage = Total_Revenue / sum(Total_Revenue) * 100) %>%
ggplot(aes(x = Region, y = Percentage, fill = Customer_Type)) +
geom_col() +
geom_text(aes(label = sprintf("%.1f%%", Percentage)),
position = position_stack(vjust = 0.5),
color = "white", size = 3.5) +
coord_flip() +
labs(title = "Tỷ lệ Doanh thu B2B/B2C theo Khu vực",
x = "Khu vực", y = "Tỷ lệ (%)", fill = "Loại KH") +
theme_minimal()
print(p16)🔹 Giải thích code: group_by(Region, Customer_Type) → Gom nhóm dữ liệu theo khu vực và loại khách hàng
summarise(Total_Revenue = sum(Total_Price)) → Tính tổng doanh thu của mỗi nhóm (mỗi cặp Region–Customer_Type).
group_by(Region) → Gom nhóm lại theo Region để tính tỷ lệ % trong từng khu vực.
mutate(Percentage = Total_Revenue / sum(Total_Revenue) * 100) → Tính tỷ trọng doanh thu (%) của từng loại KH trong khu vực.
geom_col() → vẽ cột chồng (stacked bar) theo tỷ lệ %.
📊 Nhận xét:
Phụ thuộc nặng nề vào B2B: Khách hàng B2B (Business-to-Business) mang lại doanh thu vượt trội, đạt 105,150,854 đơn vị. Doanh thu này cao hơn 3.27 lần so với khách hàng B2C (Business-to-Consumer), chỉ đạt 32,189,768 đơn vị. B2B chiếm khoảng 76.6% tổng doanh thu.
Phân bổ B2B theo Khu vực: Biểu đồ tỷ lệ B2B/B2C theo khu vực (Biểu đồ 4) xác nhận sự thống trị này là đồng nhất trên tất cả các khu vực. Tỷ lệ đóng góp của B2B trong mỗi khu vực đều áp đảo B2C (phần màu cam/đỏ chiếm phần lớn các thanh).
p17 <- data %>%
mutate(
Date = as.Date(Order_Date, format = "%d/%m/%Y"),
Month = as.numeric(format(Date, "%m")),
Season = case_when(
Month %in% c(10, 11, 12) ~ "Mùa Đông",
Month %in% c(1, 2, 3) ~ "Mùa Xuân",
Month %in% c(4, 5, 6) ~ "Mùa Hè",
Month %in% c(7, 8, 9) ~ "Mùa Thu"
)
) %>%
group_by(Season) %>%
summarise(Total_Revenue = sum(Total_Price)) %>%
ggplot(aes(x = Season, y = Total_Revenue, fill = Season)) +
geom_col() +
geom_text(aes(label = comma(round(Total_Revenue, 0))),
position = position_stack(vjust = 0.5),
size = 4, angle = 90, color = "white") +
labs(title = "Doanh thu theo mùa trong năm",
x = "Mùa", y = "Tổng doanh thu") +
scale_y_continuous(labels = comma) +
theme_minimal()
print(p17)🔹 Giải thích code:
Month = as.numeric(format(Date, “%m”)) → Trích ra tháng từ cột Date, chuyển thành số (1–12).
Season = case_when(…) → Tạo biến mới “Season” (mùa) dựa vào tháng:
group_by(Season) → Gom nhóm theo mùa
summarise() → Tính tổng doanh thu mỗi mùa.
ggplot(aes(x = Season, y = Total_Revenue, fill = Season)) → Mỗi mùa là một cột, màu khác nhau để dễ phân biệt.
📊 Nhận xét:
Doanh thu Đồng đều giữa các Mùa: Tổng doanh thu được phân bổ rất đồng đều giữa 4 mùa trong năm.
Mùa Hè (34,934,443) cao nhất, Mùa Xuân (34,129,781) thấp nhất. Sự khác biệt giữa mùa cao nhất và thấp nhất là rất nhỏ (chỉ khoảng 2.3%).
p18 <- data %>%
mutate(
Order_Date = as.Date(Order_Date, format = "%d/%m/%Y"),
Month = as.numeric(format(Order_Date, "%m"))
) %>%
group_by(Month) %>%
summarise(Avg_Revenue = mean(Total_Price, na.rm = TRUE)) %>%
ggplot(aes(x = factor(Month), y = Avg_Revenue, group = 1)) +
geom_line(color = "steelblue", size = 1) +
geom_point(color = "steelblue", size = 2) +
labs(title = " Doanh thu trung bình theo Tháng",
x = "Tháng", y = "Doanh thu trung bình") +
scale_y_continuous(labels = comma) +
theme_minimal()
print(p18)🔹 Giải thích code:
Month = as.numeric(format(Order_Date, “%m”)) → Tạo biến Month chứa số tháng (1–12).
group_by(Month) → Gom nhóm dữ liệu theo tháng.
summarise(Avg_Revenue = mean(Total_Price, na.rm = TRUE)) → Tính doanh thu trung bình mỗi tháng, bỏ qua giá trị bị thiếu (na.rm = TRUE).
geom_line(color = “steelblue”, size = 1) → Vẽ đường biểu diễn doanh thu trung bình, màu xanh thép, dày hơn mặc định.
geom_point(color = “steelblue”, size = 2) → Thêm các điểm tròn tại mỗi tháng để dễ nhìn.
📊 Nhận xét:
Đỉnh Giá trị: Doanh thu trung bình đạt đỉnh vào Tháng 12 (gần 136 đơn vị) và Tháng 2 (khoảng 132.5 đơn vị).
Đáy Giá trị: Doanh thu trung bình thấp nhất vào Tháng 4 (khoảng 127 đơn vị), cho thấy giá trị các đơn hàng vào thời điểm này là thấp nhất.
Kết luận: Các đơn hàng vào cuối năm không chỉ nhiều mà còn có giá trị trung bình cao hơn so với các tháng khác.
p19 <- data %>%
group_by(Category, Customer_Type) %>%
summarise(Total_Revenue = sum(Total_Price)) %>%
ggplot(aes(x = Category, y = Total_Revenue, fill = Customer_Type)) +
geom_col(position = "dodge") +
geom_text(aes(label = comma(round(Total_Revenue, 0))),
position = position_dodge(width = 0.9),
hjust = -0.1, size = 3.5, color = "black") +
coord_flip() +
labs(title = "Doanh thu theo Nhóm SP & Loại KH",
x = "Nhóm sản phẩm", y = "Doanh thu", fill = "Loại KH") +
scale_y_continuous(labels = comma, expand = expansion(mult = c(0, 0.15))) +
theme_minimal()
print(p19)🔹 Giải thích code:
group_by(Category, Customer_Type) → Gom nhóm theo nhóm sản phẩm (Category) và loại khách hàng (Customer_Type).
summarise(Total_Revenue = sum(Total_Price)) → Tính tổng doanh thu của từng cặp (nhóm sản phẩm, loại khách hàng).
geom_col(position = “dodge”) → Biểu đồ cột song song (grouped bars) — mỗi nhóm sản phẩm có nhiều cột ứng với các loại khách hàng khác nhau.
scale_y_continuous(labels = comma) → Hiển thị doanh thu có dấu phẩy ngăn cách hàng nghìn.
📊 Nhận xét:
Khách hàng B2B (Doanh thu: 105,150,854) áp đảo B2C (32,189,768)
Nhóm sản phẩm Alcoholic Beverages (Đồ uống có cồn) cũng thống trị về doanh thu (ước tính \(\approx 105,000,000\)).
Heatmap và biểu đồ phân bổ khẳng định mối liên hệ chặt chẽ: Doanh thu B2B chủ yếu đến từ việc bán Đồ uống có cồn (phần lớn là Champagne/Rượu mạnh), trong khi B2C đóng góp không đáng kể vào bất kỳ nhóm sản phẩm nào.
p20 <- data %>%
mutate(
# Bước 1: chuyển ngày sang kiểu Date
Order_Date = as.Date(Order_Date, format = "%d/%m/%Y"),
# Bước 2: tách tháng
Month = as.numeric(format(Order_Date, "%m")),
# Bước 3: tạo cột Season
Season = case_when(
Month %in% c(10, 11, 12) ~ "Mùa Đông",
Month %in% c(1, 2, 3) ~ "Mùa Xuân",
Month %in% c(4, 5, 6) ~ "Mùa Hè",
Month %in% c(7, 8, 9) ~ "Mùa Thu"
)
) %>%
group_by(Region, Season) %>%
summarise(Total_Revenue = sum(Total_Price, na.rm = TRUE)) %>%
ggplot(aes(x = Region, y = Total_Revenue, fill = Season)) +
geom_col(position = "dodge") +
coord_flip() +
labs(
title = " Doanh thu theo Khu vực và Mùa ",
x = "Khu vực",
y = "Doanh thu"
) +
scale_y_continuous(labels = comma) +
theme_minimal()
print(p20)🔹 Giải thích code:
Season = case_when(…) → Tạo cột mùa dựa trên tháng
group_by(Region, Season) → Gom nhóm theo khu vực và mùa trong năm.
summarise() → Tính tổng doanh thu của từng nhóm khu vực–mùa.
geom_col(position = “dodge”) → Vẽ các cột song song (đặt cạnh nhau) để dễ so sánh giữa các mùa
coord_flip() → Xoay biểu đồ nằm ngang, giúp đọc tên khu vực dễ hơn.
📊 Nhận xét:
Mùa Hè Dẫn đầu: Mùa Hè (màu xanh lá) là mùa mang lại doanh thu cao nhất ở hầu hết các khu vực, đặc biệt là Hamburg và Rheinland-Pfalz.
Mùa Đông Mạnh: Mùa Đông (màu đỏ cam) cũng là một mùa mạnh, thường là mùa có doanh thu cao thứ hai, đặc biệt ở các khu vực phía Nam.
Tác động của Mùa: Mặc dù tổng thể đồng đều, sự khác biệt theo mùa là rõ ràng ở cấp độ khu vực: Mùa Hè là mùa bán hàng mạnh mẽ nhất của công ty.
# Load các thư viện cần thiết
library(tidyverse)
library(readxl)
library(kableExtra)
library(ggplot2)
library(ggthemes)
library(scales)
library(plotly)
library(corrplot)
library(PerformanceAnalytics)
library(gridExtra)
library(lubridate)
library(psych)
library(reshape2)
library(ggrepel)## === 10 DÒNG ĐẦU TIÊN CỦA DỮ LIỆU ===
## # A tibble: 10 × 20
## ky_bao_cao tong_tai_san cho_vay_khach_hang tien_gui_cua_khach_hang
## <chr> <dbl> <dbl> <dbl>
## 1 Năm 2024 727016711 473456903 582474928
## 2 Năm 2023 674374966 438411368 536873344
## 3 Năm 2022 588643085 404997291 499789702
## 4 Năm 2021 552748211 370470970 473197808
## 5 Năm 2020 492516029 334854576 427971850
## 6 Năm 2019 453581057 292058715 400844380
## 7 Năm 2018 406040598 253100111 349388922
## 8 Năm 2017 368468840 220197752 319859587
## 9 Năm 2016 332023043 196428077 291653101
## 10 Năm 2015 292032736 183660021 260994745
## # ℹ 16 more variables: chung_khoan_dau_tu <dbl>, von_dieu_le <dbl>,
## # loi_nhuan_chua_phan_phoi <dbl>, cac_quy_du_tru <dbl>,
## # tong_loi_nhuan_truoc_thue <dbl>, chi_phi_du_phong_rui_ro_tin_dung <dbl>,
## # loi_nhuan_thuan_truoc_du_phong <dbl>, thu_nhap_lai_thuan <dbl>,
## # lai_thuan_dich_vu <dbl>, tong_thu_nhap_hoat_dong <dbl>,
## # tong_chi_phi_hoat_dong <dbl>, loi_nhuan_sau_thue <dbl>,
## # tong_von_chu_so_huu <dbl>, chung_khoan_kinh_doanh <dbl>, …
🔹 Giải thích
Hàm head(df, 10) lấy 10 dòng đầu tiên của data frame data.
cat() in tiêu đề ra màn hình cho dễ đọc trong file R Markdown.
🔹 Ý nghĩa thống kê
Giúp xem cấu trúc dữ liệu thô: các tên cột, định dạng từng cột (số, chữ, ngày, ….
Phát hiện dòng bị lỗi hoặc thiếu dữ liệu (NA) ngay từ đầu.
## === 10 DÒNG CUỐI CÙNG CỦA DỮ LIỆU ===
## # A tibble: 10 × 20
## ky_bao_cao tong_tai_san cho_vay_khach_hang tien_gui_cua_khach_hang
## <chr> <dbl> <dbl> <dbl>
## 1 Năm 2024 727016711 473456903 582474928
## 2 Năm 2023 674374966 438411368 536873344
## 3 Năm 2022 588643085 404997291 499789702
## 4 Năm 2021 552748211 370470970 473197808
## 5 Năm 2020 492516029 334854576 427971850
## 6 Năm 2019 453581057 292058715 400844380
## 7 Năm 2018 406040598 253100111 349388922
## 8 Năm 2017 368468840 220197752 319859587
## 9 Năm 2016 332023043 196428077 291653101
## 10 Năm 2015 292032736 183660021 260994745
## # ℹ 16 more variables: chung_khoan_dau_tu <dbl>, von_dieu_le <dbl>,
## # loi_nhuan_chua_phan_phoi <dbl>, cac_quy_du_tru <dbl>,
## # tong_loi_nhuan_truoc_thue <dbl>, chi_phi_du_phong_rui_ro_tin_dung <dbl>,
## # loi_nhuan_thuan_truoc_du_phong <dbl>, thu_nhap_lai_thuan <dbl>,
## # lai_thuan_dich_vu <dbl>, tong_thu_nhap_hoat_dong <dbl>,
## # tong_chi_phi_hoat_dong <dbl>, loi_nhuan_sau_thue <dbl>,
## # tong_von_chu_so_huu <dbl>, chung_khoan_kinh_doanh <dbl>, …
🔹 Giải thích
tail(df, 10) lấy 10 dòng cuối cùng trong bảng dữ liệu.
🔹 Ý nghĩa thống kê
Kiểm tra phần cuối dữ liệu xem có dòng bị trống, lặp hoặc lỗi nhập liệu không.
## Số quan sát (dòng): 10
## Số biến (cột): 20
## Các biến định lượng: 19
## Các biến định tính: 1
🔹 Giải thích
nrow(df) → đếm số hàng (số lượng quan sát/giao dịch).
ncol(df) → đếm số cột (số lượng biến/thuộc tính).
sapply(df, is.numeric) → kiểm tra cột nào là dạng số (numeric), kết quả trả về TRUE/FALSE cho từng cột.
sum(sapply(df, is.numeric)) → đếm tổng số biến định lượng.
sapply(df, is.character) | sapply(df, is.factor) → kiểm tra cột nào là dạng ký tự hoặc phân loại
sum(…) → đếm tổng số biến định tính.
🔹 Ý nghĩa thống kê
Giúp hiểu sơ bộ quy mô và cấu trúc dữ liệu
Có bao nhiêu dòng (quan sát)
Có bao nhiêu cột (biến)
Loại biến nào chiếm ưu thế (định lượng hay định tính)?
## Tên các biến của bộ dữ liệu gồm:
## - ky_bao_cao
## - tong_tai_san
## - cho_vay_khach_hang
## - tien_gui_cua_khach_hang
## - chung_khoan_dau_tu
## - von_dieu_le
## - loi_nhuan_chua_phan_phoi
## - cac_quy_du_tru
## - tong_loi_nhuan_truoc_thue
## - chi_phi_du_phong_rui_ro_tin_dung
## - loi_nhuan_thuan_truoc_du_phong
## - thu_nhap_lai_thuan
## - lai_thuan_dich_vu
## - tong_thu_nhap_hoat_dong
## - tong_chi_phi_hoat_dong
## - loi_nhuan_sau_thue
## - tong_von_chu_so_huu
## - chung_khoan_kinh_doanh
## - lai_co_ban_tren_co_phieu_vnd
## - vay_TCTD_khac
## === KIỂU DỮ LIỆU CỦA CÁC BIẾN ===
## tibble [10 × 20] (S3: tbl_df/tbl/data.frame)
## $ ky_bao_cao : chr [1:10] "Năm 2024" "Năm 2023" "Năm 2022" "Năm 2021" ...
## $ tong_tai_san : num [1:10] 7.27e+08 6.74e+08 5.89e+08 5.53e+08 4.93e+08 ...
## $ cho_vay_khach_hang : num [1:10] 4.73e+08 4.38e+08 4.05e+08 3.70e+08 3.35e+08 ...
## $ tien_gui_cua_khach_hang : num [1:10] 5.82e+08 5.37e+08 5.00e+08 4.73e+08 4.28e+08 ...
## $ chung_khoan_dau_tu : num [1:10] 81332610 71936877 61547075 71749610 75156127 ...
## $ von_dieu_le : num [1:10] 18852157 18852157 18852157 18852157 18852157 ...
## $ loi_nhuan_chua_phan_phoi : num [1:10] 26064919 20316716 14939922 9423861 7303619 ...
## $ cac_quy_du_tru : num [1:10] 5378109 4757251 4191077 3738749 3336508 ...
## $ tong_loi_nhuan_truoc_thue : num [1:10] 10255932 9296911 6665026 3871050 3339280 ...
## $ chi_phi_du_phong_rui_ro_tin_dung: num [1:10] -1921365 -2730016 -4990584 -4152029 -3036974 ...
## $ loi_nhuan_thuan_truoc_du_phong : num [1:10] 12177297 12026927 11655610 8023079 6376254 ...
## $ thu_nhap_lai_thuan : num [1:10] 22512910 21243756 18116531 13293486 11526554 ...
## $ lai_thuan_dich_vu : num [1:10] 4908618 4544754 4606313 3863308 3744015 ...
## $ tong_thu_nhap_hoat_dong : num [1:10] 29569157 27561432 24717375 18986347 17270869 ...
## $ tong_chi_phi_hoat_dong : num [1:10] -17391860 -15534505 -13061765 -10963268 -10894615 ...
## $ loi_nhuan_sau_thue : num [1:10] 8214618 7452316 5334331 3018665 2681981 ...
## $ tong_von_chu_so_huu : num [1:10] 35213980 33967555 28791443 32607200 28956242 ...
## $ chung_khoan_kinh_doanh : num [1:10] 0 0 0 0 0 ...
## $ lai_co_ban_tren_co_phieu_vnd : num [1:10] 4135 3719 2593 1414 1248 ...
## $ vay_TCTD_khac : num [1:10] 31905792 26241658 21052126 12016711 7880006 ...
🔹 Giải thích
Hàm str() hiển thị cấu trúc đối tượng, bao gồm:
Kiểu dữ liệu từng cột (numeric, character, factor, Date, …
Một vài giá trị mẫu của mỗi cột.
🔹 Ý nghĩa thống kê
Giúp xác định: Cột nào là biến định lượng (số, có thể tính trung bình, tổng, …)
Cột nào là biến định tính (phân loại: vùng, giới tính, loại khách hàng, …)
## === THỐNG KÊ MÔ TẢ TỔNG QUAN ===
## ky_bao_cao tong_tai_san cho_vay_khach_hang
## Length:10 Min. :292032736 Min. :183660021
## Class :character 1st Qu.:377861780 1st Qu.:228423342
## Mode :character Median :473048543 Median :313456646
## Mean :488744528 Mean :316763578
## 3rd Qu.:579669366 3rd Qu.:396365711
## Max. :727016711 Max. :473456903
## tien_gui_cua_khach_hang chung_khoan_dau_tu von_dieu_le
## Min. :260994745 Min. :39678056 Min. :18852157
## 1st Qu.:327241921 1st Qu.:66712258 1st Qu.:18852157
## Median :414408115 Median :72562728 Median :18852157
## Mean :414304837 Mean :69163399 Mean :18852157
## 3rd Qu.:493141728 3rd Qu.:75424848 3rd Qu.:18852157
## Max. :582474928 Max. :81332610 Max. :18852157
## loi_nhuan_chua_phan_phoi cac_quy_du_tru tong_loi_nhuan_truoc_thue
## Min. : 1264953 Min. :2419833 Min. : 155591
## 1st Qu.: 2594855 1st Qu.:2592453 1st Qu.: 1680601
## Median : 6357592 Median :3150205 Median : 3278013
## Mean : 9187365 Mean :3448636 Mean : 4141749
## 3rd Qu.:13560907 3rd Qu.:4077995 3rd Qu.: 5966532
## Max. :26064919 Max. :5378109 Max. :10255932
## chi_phi_du_phong_rui_ro_tin_dung loi_nhuan_thuan_truoc_du_phong
## Min. :-4990584 Min. : 851834
## 1st Qu.:-2960235 1st Qu.: 3310403
## Median :-2204452 Median : 5872945
## Mean :-2434482 Mean : 6576230
## 3rd Qu.:-1674427 3rd Qu.:10747477
## Max. : -696243 Max. :12177297
## thu_nhap_lai_thuan lai_thuan_dich_vu tong_thu_nhap_hoat_dong
## Min. : 4020697 Min. :1171263 Min. : 6530157
## 1st Qu.: 6839779 1st Qu.:2638409 1st Qu.: 9403198
## Median :10353621 Median :3533503 Median :15953104
## Mean :11938156 Mean :3289728 Mean :16788161
## 3rd Qu.:16910770 3rd Qu.:4374393 3rd Qu.:23284618
## Max. :22512910 Max. :4908618 Max. :29569157
## tong_chi_phi_hoat_dong loi_nhuan_sau_thue tong_von_chu_so_huu
## Min. :-17391860 Min. : 88609 Min. :22080495
## 1st Qu.:-12537141 1st Qu.:1333709 1st Qu.:23585311
## Median :-10080159 Median :2568423 Median :27766542
## Mean :-10211931 Mean :3286502 Mean :27841915
## 3rd Qu.: -6712127 3rd Qu.:4755415 3rd Qu.:31694460
## Max. : -5154547 Max. :8214618 Max. :35213980
## chung_khoan_kinh_doanh lai_co_ban_tren_co_phieu_vnd vay_TCTD_khac
## Min. : 0 Min. : 49.0 Min. : 2954073
## 1st Qu.: 0 1st Qu.: 611.2 1st Qu.: 7445120
## Median : 0 Median :1188.5 Median :10063182
## Mean :24848 Mean :1606.6 Mean :13363474
## 3rd Qu.:47438 3rd Qu.:2298.2 3rd Qu.:18951346
## Max. :95334 Max. :4135.0 Max. :31905792
🔹 Giải thích
summary() tự động tạo bảng thống kê mô tả cho mỗi cột:
Với biến số: hiển thị Min, 1st Qu., Median, Mean, 3rd Qu., Max
Với biến phân loại: đếm tần suất từng giá trị.
🔹 Ý nghĩa thống kê
Đây là phân tích mô tả (descriptive statistics) — bước đầu tiên trong mọi báo cáo thống kê.
Mean (trung bình) → giá trị đại diện chung.
Median (trung vị) → giá trị giữa, ít bị ảnh hưởng bởi ngoại lệ.
Min / Max → phạm vi dao động của dữ liệu
1st Qu. / 3rd Qu. → phân vị 25% và 75%, thể hiện độ phân tán.
## Số quan sát trùng lặp: 0
🔹 Giải thích:
Hàm duplicated(df) → 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:
## ky_bao_cao tong_tai_san
## 0 0
## cho_vay_khach_hang tien_gui_cua_khach_hang
## 0 0
## chung_khoan_dau_tu von_dieu_le
## 0 0
## loi_nhuan_chua_phan_phoi cac_quy_du_tru
## 0 0
## tong_loi_nhuan_truoc_thue chi_phi_du_phong_rui_ro_tin_dung
## 0 0
## loi_nhuan_thuan_truoc_du_phong thu_nhap_lai_thuan
## 0 0
## lai_thuan_dich_vu tong_thu_nhap_hoat_dong
## 0 0
## tong_chi_phi_hoat_dong loi_nhuan_sau_thue
## 0 0
## tong_von_chu_so_huu chung_khoan_kinh_doanh
## 0 0
## lai_co_ban_tren_co_phieu_vnd vay_TCTD_khac
## 0 0
🔹 Giải thích:
is.na(df) will return a logic ma trận (logicmatrix) có cùng kích thước với df, trong đó mỗi giá trị là TRUE nếu phần tử đó bị thiếu (NA) hoặc FALSE không bị thiếu.
Hàm colSums()cộng tất cả giá trị TRUE trong từng cột (TRUE đượctính là 1), làmmà bạn sẽ biếtmỗi cột có tổngcộng bảo nhiêu giá trị NA.
🔹 Ý 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ê.
colnames(df) <- c("ky_bao_cao", "tong_tai_san", "cho_vay_khach_hang", "tien_gui_cua_khach_hang",
"chung_khoan_dau_tu", "von_dieu_le", "loi_nhuan_chua_phan_phoi",
"cac_quy_du_tru", "tong_loi_nhuan_truoc_thue", "chi_phi_du_phong_rui_ro_tin_dung",
"loi_nhuan_thuan_truoc_du_phong", "thu_nhap_lai_thuan", "lai_thuan_dich_vu",
"tong_thu_nhap_hoat_dong", "tong_chi_phi_hoat_dong", "loi_nhuan_sau_thue",
"tong_von_chu_so_huu", "chung_khoan_kinh_doanh", "lai_co_ban_tren_co_phieu_vnd",
"vay_TCTD_khac")df$tai_san_nhom <- cut(df$tong_tai_san,
breaks = quantile(df$tong_tai_san, probs = seq(0, 1, 1/3)),
include.lowest = TRUE,
labels = c("Nhỏ", "Vừa", "Lớn"))
table_taisan <- df[, c("ky_bao_cao", "tong_tai_san", "tai_san_nhom")]
table_taisan$tong_tai_san_f <- formatC(table_taisan$tong_tai_san, format = "d", big.mark = ".")
print(table_taisan[, c("ky_bao_cao", "tong_tai_san_f", "tai_san_nhom")])## # A tibble: 10 × 3
## ky_bao_cao tong_tai_san_f tai_san_nhom
## <chr> <chr> <fct>
## 1 Năm 2024 727.016.711 Lớn
## 2 Năm 2023 674.374.966 Lớn
## 3 Năm 2022 588.643.085 Lớn
## 4 Năm 2021 552.748.211 Vừa
## 5 Năm 2020 492.516.029 Vừa
## 6 Năm 2019 453.581.057 Vừa
## 7 Năm 2018 406.040.598 Nhỏ
## 8 Năm 2017 368.468.840 Nhỏ
## 9 Năm 2016 332.023.043 Nhỏ
## 10 Năm 2015 292.032.736 Nhỏ
🔹 Giải thích:
df$tong_tai_san: cột tổng tài sản trong dataframe df.
quantile(df$tong_tai_san, probs = seq(0, 1, 1/3)):
seq(0, 1, 1/3) tạo dãy: 0, 1/3, 2/3, 1.
quantile() tính phân vị theo các mốc này → chia dữ liệu thành 3 phần bằng nhau theo giá trị tài sản.
cut(…, breaks = …, include.lowest = TRUE, labels = c(“Nhỏ”, “Vừa”, “Lớn”))
cut() chia dữ liệu thành 3 khoảng theo các giá trị phân vị vừa tính.
include.lowest = TRUE → giá trị nhỏ nhất cũng được đưa vào nhóm đầu tiên (“Nhỏ”).
df$loi_nhuan_nhom <- cut(df$loi_nhuan_sau_thue,
breaks = c(-Inf, 3000000, 8000000, Inf),
labels = c("Thấp", "Trung bình", "Cao"))
table_lnst <- df[, c("ky_bao_cao", "loi_nhuan_sau_thue", "loi_nhuan_nhom")]
table_lnst$loi_nhuan_sau_thue_f <- formatC(table_lnst$loi_nhuan_sau_thue, format = "d", big.mark = ".")
print(table_lnst[, c("ky_bao_cao", "loi_nhuan_sau_thue_f", "loi_nhuan_nhom")])## # A tibble: 10 × 3
## ky_bao_cao loi_nhuan_sau_thue_f loi_nhuan_nhom
## <chr> <chr> <fct>
## 1 Năm 2024 8.214.618 Cao
## 2 Năm 2023 7.452.316 Trung bình
## 3 Năm 2022 5.334.331 Trung bình
## 4 Năm 2021 3.018.665 Trung bình
## 5 Năm 2020 2.681.981 Thấp
## 6 Năm 2019 2.454.864 Thấp
## 7 Năm 2018 1.790.156 Thấp
## 8 Năm 2017 1.181.560 Thấp
## 9 Năm 2016 88.609 Thấp
## 10 Năm 2015 647.919 Thấp
🔹 Giải thích:
cut() : chia biến liên tục (loi_nhuan_sau_thue) thành các khoảng (bins).
breaks = c(-Inf, 3000000, 8000000, Inf)
-Inf = âm vô cực (tức là mọi giá trị nhỏ hơn 3 triệu).
3000000 và 8000000 là mốc chia nhóm.
Inf = dương vô cực (mọi giá trị lớn hơn 8 triệu).
labels = c(“Thấp”, “Trung bình”, “Cao”)
df <- df[order(df$tong_tai_san, decreasing = TRUE), ]
df$tong_tai_san_f <- formatC(df$tong_tai_san, format = "d", big.mark = ".")
head(df[, c("ky_bao_cao", "tong_tai_san_f")], 5)## # A tibble: 5 × 2
## ky_bao_cao tong_tai_san_f
## <chr> <chr>
## 1 Năm 2024 727.016.711
## 2 Năm 2023 674.374.966
## 3 Năm 2022 588.643.085
## 4 Năm 2021 552.748.211
## 5 Năm 2020 492.516.029
🔹 Giải thích:
order(df$tong_tai_san, decreasing = TRUE):
Hàm order() sắp xếp theo giá trị trong cột tong_tai_san.
decreasing = TRUE → sắp xếp giảm dần (tức là lớn nhất lên đầu).
df[…] → dùng kết quả đó để tái sắp xếp toàn bộ bảng dữ liệu df
min_val <- min(df$tong_tai_san, na.rm = TRUE)
df_min_taisan <- df[df$tong_tai_san == min_val, ]
df_min_taisan$tong_tai_san_f <- formatC(df_min_taisan$tong_tai_san, format = "d", big.mark = ".")
print(df_min_taisan[, c("ky_bao_cao", "tong_tai_san_f")])## # A tibble: 1 × 2
## ky_bao_cao tong_tai_san_f
## <chr> <chr>
## 1 Năm 2015 292.032.736
🔹 Giải thích:
min() → tìm giá trị nhỏ nhất trong cột tong_tai_san . na.rm = TRUE → bỏ qua giá trị NA (thiếu dữ liệu) để tránh lỗi.
Kết quả: biến min_val chứa giá trị tài sản nhỏ nhất trong toàn bộ mẫu
Biểu thức df$tong_tai_san == min_val tạo điều kiện lọc, chỉ chọn dòng có tổng tài sản bằng giá trị nhỏ nhất vừa tìm.
Kết quả: df_min_taisan là bảng con chứa thông tin về kỳ (hoặc đối tượng) có tổng tài sản thấp nhất.
max_val <- max(df$tong_tai_san, na.rm = TRUE)
df_max_taisan <- df[df$tong_tai_san == max_val, ]
df_max_taisan$tong_tai_san_f <- formatC(df_max_taisan$tong_tai_san, format = "d", big.mark = ".")
df_print <- df_max_taisan[, c("ky_bao_cao", "tong_tai_san_f")]
names(df_print) <- c("Kỳ báo cáo", "Tổng tài sản")
print(df_print)## # A tibble: 1 × 2
## `Kỳ báo cáo` `Tổng tài sản`
## <chr> <chr>
## 1 Năm 2024 727.016.711
# Tạo các chỉ số tài chính quan trọng
df <- df %>% mutate(
# Tỷ lệ cho vay trên tiền gửi (Loan-to-Deposit Ratio)
LTD_ratio = cho_vay_khach_hang / tien_gui_cua_khach_hang,
# Tỷ lệ an toàn vốn (CAR)
CAR = tong_von_chu_so_huu / tong_tai_san,
# ROA (Return on Assets)
ROA = loi_nhuan_sau_thue / tong_tai_san,
# ROE (Return on Equity)
ROE = loi_nhuan_sau_thue / tong_von_chu_so_huu,
# Tỷ lệ chi phí hoạt động trên tổng thu nhập (Cost-to-Income Ratio)
cost_to_income = abs(tong_chi_phi_hoat_dong) / tong_thu_nhap_hoat_dong,
# Tăng trưởng tổng tài sản
tang_truong_tai_san = (tong_tai_san - lag(tong_tai_san)) / lag(tong_tai_san),
# Tăng trưởng lợi nhuận sau thuế
tang_truong_loi_nhuan = (loi_nhuan_sau_thue - lag(loi_nhuan_sau_thue)) / lag(loi_nhuan_sau_thue),
# Tỷ lệ thu nhập lãi thuần trên tổng tài sản
thu_nhap_lai_thuan_ts = thu_nhap_lai_thuan / tong_tai_san,
# Tỷ lệ dự phòng rủi ro tín dụng
ty_le_du_phong = cac_quy_du_tru / cho_vay_khach_hang,
# Hiệu quả sử dụng vốn
hieu_qua_su_dung_von = loi_nhuan_sau_thue / tong_von_chu_so_huu
)
# Thay thế NA bằng 0 trong các cột tăng trưởng
df$tang_truong_tai_san[is.na(df$tang_truong_tai_san)] <- 0
df$tang_truong_loi_nhuan[is.na(df$tang_truong_loi_nhuan)] <- 0stat <- summary(df$tong_tai_san)
sd_val <- sd(df$tong_tai_san, na.rm=TRUE)
# Thêm dấu chấm ngăn cách cho các thống kê mô tả
stat_f <- formatC(stat, format = "d", big.mark = ".")
sd_f <- formatC(sd_val, format = "d", big.mark = ".")
# In ra kết quả có dấu phân cách
cat("Các chỉ số thống kê mô tả tổng tài sản:\n")## Các chỉ số thống kê mô tả tổng tài sản:
## Min. 1st Qu. Median Mean 3rd Qu.
## "292.032.736" "377.861.779" "473.048.543" "488.744.527" "579.669.366"
## Max.
## "727.016.711"
## Độ lệch chuẩn: 145.725.203
🔹 Giải thích:
summary(df$tong_tai_san) → tạo bảng tóm tắt 6 chỉ tiêu thống kê cơ bản
sd(df$tong_tai_san, na.rm=TRUE) → tính độ lệch chuẩn (Standard Deviation), đo mức dao động hoặc phân tán của tổng tài sản so với trung bình
Nhận xét: Tổng tài sản của các quan sát có mức trung bình khoảng 488,7 triệu, dao động khá lớn (độ lệch chuẩn ≈145,7 triệu). Giá trị thấp nhất là ≈292 triệu và cao nhất ≈727 triệu, cho thấy sự chênh lệch đáng kể giữa các đối tượng trong tập dữ liệu.
library(dplyr)
df$tai_san_nhom <- cut(df$tong_tai_san,
breaks = quantile(df$tong_tai_san, probs = seq(0, 1, 1/3), na.rm=TRUE),
include.lowest = TRUE,
labels = c("Nhỏ", "Vừa", "Lớn"))
ts_grouped <- df %>%
group_by(tai_san_nhom) %>%
summarise(
Mean = mean(tong_tai_san, na.rm = TRUE),
Median = median(tong_tai_san, na.rm = TRUE),
Max = max(tong_tai_san, na.rm = TRUE),
Min = min(tong_tai_san, na.rm = TRUE)
)
# Thêm dấu chấm phân cách cho tất cả giá trị
ts_grouped$Mean <- formatC(ts_grouped$Mean, format = "d", big.mark = ".")
ts_grouped$Median <- formatC(ts_grouped$Median, format = "d", big.mark = ".")
ts_grouped$Max <- formatC(ts_grouped$Max, format = "d", big.mark = ".")
ts_grouped$Min <- formatC(ts_grouped$Min, format = "d", big.mark = ".")
print(ts_grouped)## # A tibble: 3 × 5
## tai_san_nhom Mean Median Max Min
## <fct> <chr> <chr> <chr> <chr>
## 1 Nhỏ 349.641.304 350.245.941 406.040.598 292.032.736
## 2 Vừa 499.615.099 492.516.029 552.748.211 453.581.057
## 3 Lớn 663.344.920 674.374.966 727.016.711 588.643.085
🔹 Giải thích:
quantile(df$tong_tai_san, probs = seq(0, 1, 1/3)) → chia dữ liệu theo phân vị 0%, 33,3%, 66,7%, 100%, tức là 3 phần bằng nhau (mỗi nhóm chứa khoảng 1/3 mẫu).
cut() → phân loại mỗi quan sát vào một nhóm tương ứng
include.lowest = TRUE → đảm bảo giá trị nhỏ nhất được tính vào nhóm đầu tiên.
group_by(tai_san_nhom) → gom dữ liệu theo nhóm quy mô (“Nhỏ”, “Vừa”, “Lớn”).
summarise() → tính 4 chỉ tiêu thống kê cơ bản cho từng nhóm → Giúp so sánh đặc điểm phân bố tài sản giữa các nhóm
Nhận xét: Tổng tài sản tăng dần theo quy mô nhóm. Nhóm “Nhỏ” có tài sản trung bình khoảng 349,6 triệu, nhóm “Vừa” đạt 499,6 triệu, và nhóm “Lớn” cao nhất với 663,3 triệu. Điều này cho thấy sự phân tầng rõ rệt về quy mô tài sản giữa các nhóm.
df$tang_truong_ts <- c(NA, diff(df$tong_tai_san) / head(df$tong_tai_san, -1) * 100)
# Làm tròn số cho gọn
df$tang_truong_ts_f <- round(df$tang_truong_ts, 2)
# In bảng gồm năm, tổng tài sản (dấu chấm), và tốc độ tăng trưởng %
df$tong_tai_san_f <- formatC(df$tong_tai_san, format = "d", big.mark = ".")
print(df[, c("ky_bao_cao", "tong_tai_san_f", "tang_truong_ts_f")])## # A tibble: 10 × 3
## ky_bao_cao tong_tai_san_f tang_truong_ts_f
## <chr> <chr> <dbl>
## 1 Năm 2024 727.016.711 NA
## 2 Năm 2023 674.374.966 -7.24
## 3 Năm 2022 588.643.085 -12.7
## 4 Năm 2021 552.748.211 -6.1
## 5 Năm 2020 492.516.029 -10.9
## 6 Năm 2019 453.581.057 -7.91
## 7 Năm 2018 406.040.598 -10.5
## 8 Năm 2017 368.468.840 -9.25
## 9 Năm 2016 332.023.043 -9.89
## 10 Năm 2015 292.032.736 -12.0
🔹 Giải thích:
diff(df$tong_tai_san) → tính hiệu giữa các kỳ liên tiếp của biến tong_tai_san
head(df$tong_tai_san, -1) → lấy toàn bộ giá trị trừ kỳ cuối (để chia đúng cho giá trị kỳ trước).
diff(…) / head(…) * 100 → chuyển đổi sang tỷ lệ phần trăm tăng trưởng
Nhận xét: Tổng tài sản có xu hướng giảm liên tục qua các năm, với mức giảm trung bình khoảng 7–13% mỗi năm. Mặc dù năm 2024 đạt giá trị cao nhất (727 triệu), nhưng giai đoạn trước đó thể hiện sự suy giảm rõ rệt, cho thấy doanh nghiệp chưa duy trì được tăng trưởng ổn định về tài sản.
## [1] 0.9940972
🔹 Giải thích:
cor(…) → hàm tính hệ số tương quan Pearson (mặc định).→ Dùng để đo mức độ và chiều hướng mối liên hệ tuyến tính giữa hai biến số định lượng.
df$tong_tai_san → biến thứ nhất: Tổng tài sản của doanh nghiệp.
df$cho_vay_khach_hang → biến thứ hai: Dư nợ cho vay khách hàng.
Kết quả: r=0.9940972 => Tương quan thuận cực kỳ mạnh giữa tổng tài sản và cho vay khách hàng.
format_number <- function(x) {
format(x, big.mark = ".", scientific = FALSE)
}
summary_vals <- summary(df$cho_vay_khach_hang)
summary_formatted <- lapply(summary_vals, format_number)
print(summary_formatted)## $Min.
## [1] "183.660.021"
##
## $`1st Qu.`
## [1] "228.423.342"
##
## $Median
## [1] "313.456.646"
##
## $Mean
## [1] "316.763.578"
##
## $`3rd Qu.`
## [1] "396.365.711"
##
## $Max.
## [1] "473.456.903"
Nhận xét:
Khoản cho vay khách hàng có giá trị trung bình khoảng 316,8 triệu, tương đối gần với trung vị 313,5 triệu, cho thấy phân bố khá cân đối. Giá trị dao động từ 183,7 triệu đến 396,4 triệu, phản ánh mức chênh lệch vừa phải giữa các khách hàng vay
Phân vị thứ nhất (Q1): 228,42 triệu → 25% khách hàng có giá trị cho vay ≤ mức này. Phân vị thứ ba (Q3): 396,37 triệu → 75% khách hàng có mức cho vay dưới giá trị này.
## [1] 0.9940972
Kết quả: r=0.9940972 => Tương quan thuận cực kỳ mạnh giữa tổng tài sản và cho vay khách hàng.
ggplot(df, aes(x = tien_gui_cua_khach_hang, y = cho_vay_khach_hang)) +
geom_point(color = "green", size = 2.5) +
geom_smooth(method = "lm", color = "red") +
labs(title = "Tương quan: Cho vay khách hàng vs Tiền gửi", x = "Tiền gửi khách hàng", y = "Cho vay khách hàng") +
theme_light()🔹 Nhận xét:
Biểu đồ thể hiện mối tương quan giữa biến Cho vay khách hàng và Tiền gửi khách hàng. Các điểm dữ liệu phân bố gần như hoàn toàn dọc theo đường hồi quy tuyến tính (màu đỏ), cho thấy hai biến có mối quan hệ cùng chiều rất mạnh.
Cụ thể, khi tiền gửi của khách hàng tăng lên, giá trị cho vay khách hàng cũng có xu hướng tăng tương ứng. Hệ số tương quan đạt khoảng 0,99, phản ánh mối liên kết gần như tuyến tính hoàn hảo giữa hai chỉ tiêu này. Điều này hàm ý rằng quy mô cho vay của ngân hàng có mối phụ thuộc chặt chẽ vào nguồn vốn huy động từ khách hàng.
ggplot(df, aes(x = nam, y = cho_vay_khach_hang)) +
geom_line(color = "blue", size = 1.1, group = 1) +
geom_point(size = 2) +
scale_y_continuous(labels = scales::comma) +
labs(title = "Xu hướng dư nợ cho vay khách hàng theo thời gian", x = "Năm", y = "Cho vay khách hàng") +
theme_minimal()🔹Nhận xét:
Biểu đồ cho thấy dư nợ cho vay khách hàng có xu hướng tăng mạnh qua giai đoạn 2015–2024.
Cụ thể, dư nợ tăng đều hàng năm, phản ánh sự phát triển ổn định trong hoạt động tín dụng của ngân hàng . Đặc biệt, từ năm 2020 trở đi, tốc độ tăng trưởng có xu hướng cao hơn, cho thấy ngân hàng đã mở rộng hoạt động cho vay, đồng thời đáp ứng tốt nhu cầu vốn của thị trường.
Xu hướng này là tín hiệu tích cực về tăng trưởng quy mô tài sản sinh lời, tuy nhiên cần đi kèm với việc đảm bảo chất lượng tín dụng và quản lý rủi ro hiệu quả.
sum_vals <- summary(df$tien_gui_cua_khach_hang)
# Định dạng có dấu phân cách hàng nghìn (dùng dấu chấm chuẩn VN)
format_number <- function(x) {
format(x, big.mark = ".", decimal.mark = ",", scientific = FALSE)
}
sapply(sum_vals, format_number)## Min. 1st Qu. Median Mean 3rd Qu.
## "260.994.745" "327.241.921" "414.408.115" "414.304.837" "493.141.729"
## Max.
## "582.474.928"
🔹Nhận xét:
Biến tiền gửi của khách hàng có giá trị nhỏ nhất là 260.994.745, giá trị phân vị thứ nhất (Q1) là 327.241.921, trung vị (Median) là 414.408.115, giá trị trung bình (Mean) là 414.304.837, phân vị thứ ba (Q3) là 493.141.729, và giá trị lớn nhất là 582.474.928.
Điều này cho thấy mức tiền gửi của khách hàng dao động trong khoảng từ khoảng 261 triệu đến 582 triệu, với trung bình và trung vị gần tương đương nhau, phản ánh phân bố khá cân đối và đồng đều giữa các khách hàng.
format_number <- function(x) {
format(x, big.mark = ".", decimal.mark = ",", scientific = FALSE)
}
# Định dạng phần trăm
format_percent <- function(x) {
if (is.na(x)) return(NA)
paste0(format(round(x * 100, 2), decimal.mark = ",", nsmall = 2), " %")
}
df <- df %>% arrange(ky_bao_cao)
df$growth_tiengui <- c(NA, diff(df$tien_gui_cua_khach_hang) / head(df$tien_gui_cua_khach_hang, -1))
df$tien_gui_cua_khach_hang_fmt <- format_number(df$tien_gui_cua_khach_hang)
df$growth_tiengui_fmt <- sapply(df$growth_tiengui, format_percent)
print(df[, c("ky_bao_cao", "tien_gui_cua_khach_hang_fmt", "growth_tiengui_fmt")])## # A tibble: 10 × 3
## ky_bao_cao tien_gui_cua_khach_hang_fmt growth_tiengui_fmt
## <chr> <chr> <chr>
## 1 Năm 2015 260.994.745 <NA>
## 2 Năm 2016 291.653.101 11,75 %
## 3 Năm 2017 319.859.587 9,67 %
## 4 Năm 2018 349.388.922 9,23 %
## 5 Năm 2019 400.844.380 14,73 %
## 6 Năm 2020 427.971.850 6,77 %
## 7 Năm 2021 473.197.808 10,57 %
## 8 Năm 2022 499.789.702 5,62 %
## 9 Năm 2023 536.873.344 7,42 %
## 10 Năm 2024 582.474.928 8,49 %
Giải thích:
format_number(): định dạng số có dấu chấm ngăn cách hàng nghìn và dấu phẩy cho phần thập phân.
format_percent(): chuyển giá trị tỷ lệ sang dạng phần trăm, làm tròn 2 chữ số và thêm ký hiệu “%”. 🔹Nhận xét:
Tiền gửi của khách hàng tăng đều qua các năm, từ 260,9 triệu (2015) lên 582,5 triệu (2024).Tốc độ tăng trưởng dao động từ 5,6% đến 14,7%, cao nhất năm 2019, cho thấy xu hướng tích cực và ổn định trong huy động tiền gửi qua thời gian.
df$tytrong_tiengui_tren_tongtaisan <- df$tien_gui_cua_khach_hang /
df$tong_tai_san
ggplot(df, aes(x = nam, y = tytrong_tiengui_tren_tongtaisan)) +
geom_col(fill = "orange") +
geom_text(aes(label = round(tytrong_tiengui_tren_tongtaisan, 2)), vjust = -0.2, size = 3) +
labs(title = "Tỷ trọng tiền gửi khách hàng / Tổng tài sản", x = "Năm", y = "Tỷ trọng") +
theme_minimal()🔹Nhận xét:
Tỷ trọng tiền gửi khách hàng trong tổng tài sản duy trì ở mức cao và ổn định, dao động quanh 80–85% trong giai đoạn 2015–2024.
Điều này cho thấy nguồn vốn huy động từ khách hàng vẫn là cấu phần chủ yếu trong tổng tài sản của ngân hàng, phản ánh chiến lược tập trung vào hoạt động huy động vốn truyền thống.
Giai đoạn 2015–2019, tỷ trọng duy trì ở mức ổn định cao (trên 0,8), thể hiện sự bền vững trong cơ cấu nguồn vốn.
Từ 2020–2023, có sự giảm nhẹ, cho thấy ngân hàng mở rộng các nguồn vốn khác hoặc tăng mạnh quy mô tài sản.
Năm 2024, tỷ trọng tăng nhẹ trở lại, cho thấy xu hướng phục hồi của tiền gửi khách hàng trong cơ cấu tài sản.
# Lấy thống kê mô tả cho biến
desc_vals <- summary(df$loi_nhuan_sau_thue)
# Hàm định dạng số có dấu chấm hàng nghìn, chuẩn Việt Nam
format_number <- function(x) {
format(x, big.mark = ".", decimal.mark = ",", scientific = FALSE)
}
desc_vals_fmt <- sapply(desc_vals, format_number)
print(desc_vals_fmt)## Min. 1st Qu. Median Mean 3rd Qu. Max.
## "88.609" "1.333.709" "2.568.423" "3.286.502" "4.755.415" "8.214.618"
🔹Nhận xét:
Lợi nhuận sau thuế tăng dần và phân bố khá lệch phải, thể hiện xu hướng tăng trưởng tích cực qua các năm.
Khoảng chênh giữa Min và Max lớn, cho thấy biến động mạnh về lợi nhuận, có thể do ảnh hưởng của các yếu tố kinh doanh và môi trường kinh tế từng năm.
Trung vị (2,57 triệu) nhỏ hơn trung bình (3,28 triệu) → chứng tỏ có một vài năm lợi nhuận rất cao kéo trung bình lên.
df <- df %>% arrange(ky_bao_cao)
# Tính tốc độ tăng trưởng lợi nhuận sau thuế
df$growth_loi_nhuan <- c(NA, diff(df$loi_nhuan_sau_thue) / head(df$loi_nhuan_sau_thue, -1))
# Định dạng tăng trưởng thành phần trăm có phân cách chuẩn Việt Nam
format_percent <- function(x) {
if (is.na(x)) return(NA)
paste0(format(round(x * 100, 2), big.mark = ".", decimal.mark = ",", nsmall = 2), " %")
}
df$loi_nhuan_sau_thue_fmt <- format_number(df$loi_nhuan_sau_thue)
df$growth_loi_nhuan_fmt <- sapply(df$growth_loi_nhuan, format_percent)
# Xuất bảng với tăng trưởng đã định dạng
print(df[, c("ky_bao_cao", "loi_nhuan_sau_thue_fmt", "growth_loi_nhuan_fmt")])## # A tibble: 10 × 3
## ky_bao_cao loi_nhuan_sau_thue_fmt growth_loi_nhuan_fmt
## <chr> <chr> <chr>
## 1 Năm 2015 " 647.919" <NA>
## 2 Năm 2016 " 88.609" -86,32 %
## 3 Năm 2017 "1.181.560" 1.233,45 %
## 4 Năm 2018 "1.790.156" 51,51 %
## 5 Năm 2019 "2.454.864" 37,13 %
## 6 Năm 2020 "2.681.981" 9,25 %
## 7 Năm 2021 "3.018.665" 12,55 %
## 8 Năm 2022 "5.334.331" 76,71 %
## 9 Năm 2023 "7.452.316" 39,70 %
## 10 Năm 2024 "8.214.618" 10,23 %
🔹Nhận xét:
Lợi nhuận sau thuế tăng mạnh qua các năm, đặc biệt năm 2017 bứt phá (+1.233%) sau giai đoạn giảm sâu 2016.
Từ 2018–2024, tốc độ tăng duy trì ổn định và tích cực, cao nhất 2022 (76,7%), cho thấy hiệu quả hoạt động ngày càng được cải thiện rõ rệt.
ggplot(df, aes(x = tien_gui_cua_khach_hang, y = loi_nhuan_sau_thue)) +
geom_point() +
geom_smooth(method = "lm") +
labs(title = "Tương quan: Lợi nhuận sau thuế với Tiền gửi khách hàng", x = "Tiền gửi khách hàng", y = "Lợi nhuận sau thuế")🔹Nhận xét:
Mối quan hệ: Có một mối quan hệ tuyến tính đồng biến (tích cực) mạnh giữa Tiền gửi của khách hàng và Lợi nhuận sau thuế.
Ý nghĩa: Khi tiền gửi của khách hàng tăng, lợi nhuận sau thuế có xu hướng tăng theo rõ rệt.
Mô hình: Đường hồi quy tuyến tính (màu xanh dương) phù hợp tốt với dữ liệu, cho thấy Tiền gửi là yếu tố dự báo quan trọng cho Lợi nhuận.
Độ tin cậy: Các điểm dữ liệu tập trung gần đường hồi quy, thể hiện mối tương quan mạnh và đáng tin cậy.
format_number <- function(x) {
format(x, big.mark = ".", decimal.mark = ",", scientific = FALSE)
}
summary_vals <- summary(df$tong_von_chu_so_huu)
print(sapply(summary_vals, format_number))## Min. 1st Qu. Median Mean 3rd Qu. Max.
## "22.080.495" "23.585.311" "27.766.542" "27.841.915" "31.694.461" "35.213.980"
📊 Nhận xét
Giá trị nhỏ nhất (Min.): 22.080.495
Giá trị lớn nhất (Max.): 35.213.980
Giá trị trung vị (Median): 27.766.542 (Giá trị nằm giữa dãy dữ liệu)
Giá trị trung bình (Mean): 27.841.915 (Giá trị trung tâm)
Phân vị thứ nhất (1st Qu.): 23.585.311 (25% dữ liệu nhỏ hơn hoặc bằng giá trị này)
Phân vị thứ ba (3rd Qu.): 31.694.461 (75% dữ liệu nhỏ hơn hoặc bằng giá trị này)
format_number <- function(x) {
format(x, big.mark = ".", decimal.mark = ",", scientific = FALSE)
}
# Định dạng phần trăm cho tăng trưởng
format_percent <- function(x) {
if (is.na(x)) return(NA)
paste0(format(round(x * 100, 2), decimal.mark = ",", nsmall = 2), " %")
}
# Tính tăng trưởng và định dạng
df_sorted <- df %>% arrange(ky_bao_cao)
df$growth_von_chu_so_huu <- c(NA, diff(df$tong_von_chu_so_huu) / head(df$tong_von_chu_so_huu, -1))
df$tong_von_chu_so_huu_fmt <- format_number(df$tong_von_chu_so_huu)
df$growth_von_chu_so_huu_fmt <- sapply(df$growth_von_chu_so_huu, format_percent)
knitr::kable(
df[, c("ky_bao_cao", "tong_von_chu_so_huu_fmt", "growth_von_chu_so_huu_fmt")],
col.names = c("Kỳ báo cáo", "Tổng VCSH (đã format)", "Tăng trưởng (%)"),
align = c("c", "r", "r"),
row.names = FALSE
)| Kỳ báo cáo | Tổng VCSH (đã format) | Tăng trưởng (%) |
|---|---|---|
| Năm 2015 | 22.080.495 | NA |
| Năm 2016 | 22.191.934 | 0,50 % |
| Năm 2017 | 23.236.292 | 4,71 % |
| Năm 2018 | 24.632.367 | 6,01 % |
| Năm 2019 | 26.741.640 | 8,56 % |
| Năm 2020 | 28.956.242 | 8,28 % |
| Năm 2021 | 32.607.200 | 12,61 % |
| Năm 2022 | 28.791.443 | -11,70 % |
| Năm 2023 | 33.967.555 | 17,98 % |
| Năm 2024 | 35.213.980 | 3,67 % |
📊 Nhận xét về Tốc độ Tăng trưởng Tổng Vốn Chủ Sở Hữu
Vốn chủ sở hữu tăng đều qua các năm, phản ánh năng lực tài chính được củng cố.
Ngoại lệ năm 2022 giảm 11,7%, nhưng sau đó phục hồi mạnh năm 2023 (+18%) và tiếp tục tăng nhẹ năm 2024, cho thấy xu hướng tăng trưởng bền vững trở lại.
ggplot(df, aes(x = nam, y = tong_von_chu_so_huu)) +
geom_line(color = "blue") +
geom_point(size = 2) +
labs(title = "Xu hướng tổng vốn chủ sở hữu",
x = "Năm",
y = "Tổng vốn chủ sở hữu")📈 Nhận xét Xu hướng Tổng Vốn Chủ Sở Hữu
Tổng vốn chủ sở hữu có xu hướng tăng trưởng dài hạn từ năm 2015 đến năm 2024.
Giai đoạn tăng ổn định (2015 - 2021): Vốn chủ sở hữu tăng trưởng liên tục và khá đều đặn.
Sụt giảm (Năm 2022): Ghi nhận một sự sụt giảm rõ rệt từ mức đỉnh năm 2021. Điểm dữ liệu năm 2022 nằm thấp hơn so với xu hướng tăng trưởng chung của các năm trước đó.
Phục hồi và Đạt đỉnh (Năm 2023 - 2024): Sau khi sụt giảm, vốn chủ sở hữu đã phục hồi mạnh mẽ vào năm 2023 và tiếp tục tăng, đạt mức cao nhất vào năm 2024
df$tytrong_vonchush_tren_tongts <- df$tong_von_chu_so_huu / df$tong_tai_san
ggplot(df, aes(x = nam, y = tytrong_vonchush_tren_tongts)) +
geom_col(fill = "purple") +
geom_text(aes(label = round(tytrong_vonchush_tren_tongts, 2)), vjust = -0.2, size = 3) +
labs(title = "Tỷ trọng vốn chủ sở hữu / Tổng tài sản",
x = "Năm",
y = "Tỷ trọng")📊 Nhận xét về Tỷ trọng Vốn Chủ Sở Hữu / Tổng Tài Sản
Tỷ trọng vốn chủ sở hữu giảm dần giai đoạn 2015–2021, sụt mạnh năm 2022 (~0,05) do vốn chủ sở hữu giảm hoặc tổng tài sản tăng nhanh.
Từ 2022–2024, tỷ trọng ổn định ở mức thấp, dù vốn chủ phục hồi, cho thấy tài sản (chủ yếu từ nợ) vẫn tăng nhanh hơn.
df$ROE <- df$loi_nhuan_sau_thue / df$tong_von_chu_so_huu
df$ROE_fmt <- sapply(df$ROE, format_percent)
knitr::kable(
df[, c("ky_bao_cao", "ROE_fmt")],
col.names = c("Kỳ báo cáo", "ROE (%)"),
align = c("c", "r"),
row.names = FALSE
)| Kỳ báo cáo | ROE (%) |
|---|---|
| Năm 2015 | 2,93 % |
| Năm 2016 | 0,40 % |
| Năm 2017 | 5,08 % |
| Năm 2018 | 7,27 % |
| Năm 2019 | 9,18 % |
| Năm 2020 | 9,26 % |
| Năm 2021 | 9,26 % |
| Năm 2022 | 18,53 % |
| Năm 2023 | 21,94 % |
| Năm 2024 | 23,33 % |
Nhận xét: ROE tăng mạnh qua các năm, từ 2,9% (2015) lên 23,3% (2024).Sau giai đoạn tăng ổn định quanh 9% (2019–2021), chỉ số bứt phá mạnh từ 2022 trở đi, phản ánh hiệu quả sử dụng vốn chủ sở hữu ngày càng cao..
df$nam <- as.factor(df$ky_bao_cao)
p1 <- ggplot(df, aes(x = nam, y = tong_tai_san/1e6)) +
geom_line(group = 1, color = "blue", size = 1.2, alpha = 0.8) +
geom_point(color = "blue", size = 2.5) +
geom_smooth(method = "lm", se = FALSE, color = "red", linetype = "dashed", aes(group = 1)) +
geom_text(aes(label = round(tong_tai_san/1e6, 1)), vjust = -1, size = 3) +
labs(title = "Tổng tài sản qua các năm", x = "Năm", y = "Tổng tài sản (triệu VND)") +
theme_minimal()
print(p1)🔹 Giải thích code
ggplot(df, aes(x = ky_bao_cao, y = tong_tai_san/1e6)) → trục X là kỳ báo cáo (năm), trục Y là tổng tài sản chuyển sang triệu VND (chia 1e6).
geom_line(…) + geom_point(…) → vẽ đường và điểm để thấy xu hướng.
geom_smooth(method = “lm”, se = FALSE, color = “red”, linetype = “dashed”) → vẽ đường hồi quy tuyến tính (trend).
geom_text(aes(label = round(tong_tai_san/1e6, 1)), vjust = -1) → in nhãn giá trị (làm tròn 1 chữ số).
labs(…) + theme_minimal() → tiêu đề, nhãn trục và theme.
🔹 Nhận xét
Tốc độ tăng trưởng: Tốc độ tăng trưởng dường như nhanh hơn ở những năm gần đây, đặc biệt là giai đoạn sau năm 2021, khi khoảng cách giữa các điểm dữ liệu theo chiều dọc lớn hơn.
Tính ổn định: Xu hướng tăng trưởng là rất ổn định, không có năm nào bị sụt giảm.
p2 <- ggplot(df, aes(x = factor(ky_bao_cao), y = cho_vay_khach_hang/1e6)) +
geom_col(fill = "steelblue", alpha = 0.8) +
geom_text(aes(label = round(cho_vay_khach_hang/1e6, 1)), vjust = -0.5, size = 3) +
geom_hline(yintercept = mean(df$cho_vay_khach_hang/1e6),
color = "red", linetype = "dashed", size = 1) +
labs(title = "Cho vay khách hàng qua các năm", x = "Năm", y = "Cho vay (triệu VND)") +
theme_minimal()
print(p2)🔹 Giải thích code
aes(x = factor(ky_bao_cao), y = cho_vay_khach_hang/1e6) → cột theo năm, giá trị cho vay (triệu VND).
geom_col(fill = “steelblue”, alpha = 0.8) → cột màu xanh.
geom_text(…, vjust = -0.5) → gắn nhãn giá trị trên cột.
geom_hline(yintercept = mean(…), color = “red”, linetype = “dashed”) → vẽ đường trung bình cho vay để so sánh.
🔹 Nhận xét
Tăng trưởng liên tục: Hoạt động cho vay khách hàng tăng trưởng đều đặn qua tất cả các năm, từ 183.7 triệu VND (Năm 2015) lên đến 473.5 triệu VND (Năm 2024) . Vượt ngưỡng: Từ năm 2020 trở đi (334.9 triệu VND), mức cho vay đã vượt qua ngưỡng tham chiếu (đường đứt nét màu đỏ, khoảng 320 triệu VND), cho thấy sự mở rộng mạnh mẽ hoạt động tín dụng trong giai đoạn gần đây.
Tăng tốc: Tốc độ tăng trưởng dường như nhanh hơn trong những năm cuối (2020-2024), thể hiện sự gia tăng đáng kể trong quy mô danh mục cho vay.
p3 <- ggplot(df, aes(x = nam, y = tien_gui_cua_khach_hang/1e6)) +
geom_area(fill = "lightgreen", alpha = 0.6) +
geom_line(color = "darkgreen", size = 1, group = 1) +
geom_point(color = "darkgreen", size = 2) +
geom_text(aes(label = round(tien_gui_cua_khach_hang/1e6, 1)), vjust = -1, size = 3) +
labs(title = "Tiền gửi khách hàng qua các năm", x = "Năm", y = "Tiền gửi (triệu VND)") +
theme_minimal()
print(p3)🔹 Giải thích code
geom_area(fill = “lightgreen”, alpha = 0.6) → vùng tích phân dưới đường (area) cho tiền gửi.
geom_line() + geom_point() → đường và điểm nhấn.
geom_text(… ) → in nhãn tiền gửi (triệu VND).
🔹 Nhận xét
Xu hướng chính: Tiền gửi khách hàng có xu hướng tăng trưởng liên tục và mạnh mẽ trong suốt giai đoạn từ năm 2015 (261 triệu VND) đến năm 2024 (582.5 triệu VND).
Tốc độ tăng trưởng: Tốc độ tăng trưởng nhìn chung là ổn định và có xu hướng tăng tốc trong giai đoạn gần đây (sau năm 2021).
Tính ổn định: Xu hướng tăng là rất nhất quán, không có năm nào bị sụt giảm.
p4 <- ggplot(df, aes(x = ky_bao_cao, y = loi_nhuan_sau_thue/1e3)) +
geom_point(color = "purple", size = 3, alpha = 0.7) +
geom_segment(aes(xend = ky_bao_cao, yend = 0), color = "purple", alpha = 0.5) +
geom_text(aes(label = round(loi_nhuan_sau_thue/1e3, 1)), vjust = -1, size = 3) +
geom_smooth(method = "loess", se = FALSE, color = "orange") +
labs(title = "Lợi nhuận sau thuế qua các năm", x = "Năm", y = "Lợi nhuận (nghìn VND)") +
theme_minimal()
print(p4)🔹 Giải thích code
geom_point(color = “purple”, size = 3) → điểm lợi nhuận mỗi năm (đơn vị nghìn VND do chia /1e3).
geom_segment(aes(xend = ky_bao_cao, yend = 0)) → vẽ đường thẳng từ mỗi điểm xuống trục 0 (so sánh trực quan).
geom_smooth(method = “loess”, se = FALSE, color = “orange”) → đường mượt LOESS thể hiện xu hướng phi tuyến.
geom_text(…) → nhãn giá trị.
🔹 Nhận xét
Tăng trưởng chung: Lợi nhuận sau thuế có xu hướng tăng trưởng cực kỳ mạnh mẽ và liên tục từ năm 2016 (mức thấp nhất là 88.6 nghìn VND) đến năm 2024 (mức cao nhất là 8214.6 nghìn VND).
Cải thiện ban đầu (2016 - 2021): Lợi nhuận tăng ổn định, nhưng tốc độ tăng trưởng ở mức trung bình.
Tăng trưởng bùng nổ (2022 - 2024): Giai đoạn này chứng kiến sự tăng trưởng đột phá, đặc biệt là từ năm 2021 (3018.7 nghìn VND) lên 2022 (5334.3 nghìn VND), và tiếp tục tăng rất mạnh vào năm 2023 và 2024. Độ dốc của biểu đồ tăng lên rõ rệt trong 3 năm cuối.
p5 <- ggplot(df, aes(x = ky_bao_cao, y = tong_von_chu_so_huu/1e6)) +
geom_step(color = "brown", size = 1.2, direction = "hv") +
geom_point(color = "brown", size = 2) +
geom_ribbon(aes(ymin = 0, ymax = tong_von_chu_so_huu/1e6),
fill = "brown", alpha = 0.2) +
geom_text(aes(label = round(tong_von_chu_so_huu/1e6, 1)), vjust = -1, size = 3) +
labs(title = "Tổng vốn chủ sở hữu qua các năm", x = "Năm", y = "Vốn chủ sở hữu (triệu VND)") +
theme_minimal()
print(p5)🔹 Giải thích code
geom_step(direction = “hv”) → biểu diễn thay đổi theo bước (horizontal-vertical) cho vốn chủ sở hữu.
geom_ribbon(aes(ymin = 0, ymax = tong_von_chu_so_huu/1e6), fill = “brown”, alpha = 0.2) → vùng tô từ 0 lên giá trị vốn (visual emphasis).
geom_text(…) → gắn nhãn (triệu VND).
🔹 Nhận xét
Xu hướng chung: Tổng vốn chủ sở hữu có xu hướng tăng trưởng dài hạn từ 22.1 triệu VND (Năm 2015) lên 35.2 triệu VND (Năm 2024).
Tăng trưởng ổn định (2015 - 2021): Vốn chủ sở hữu tăng liên tục, đạt đỉnh cục bộ là 32.6 triệu VND vào năm 2021.
Sụt giảm đột ngột (Năm 2022): Ghi nhận một sự sụt giảm rõ rệt từ 32.6 (2021) xuống còn 28.8 triệu VND vào năm 2022. Đây là điểm bất thường trong xu hướng tăng.
Phục hồi mạnh mẽ (2023 - 2024): Vốn chủ sở hữu phục hồi nhanh chóng và vượt qua mức đỉnh cũ, đạt 34 triệu VND (2023) và mức cao nhất 35.2 triệu VND vào năm 2024.
p6 <- ggplot(df) +
geom_line(aes(x = ky_bao_cao, y = tong_tai_san/1e6, color = "Tổng tài sản"), size = 1.2) +
geom_line(aes(x = ky_bao_cao, y = cho_vay_khach_hang/1e6, color = "Cho vay KH"), size = 1.2) +
geom_point(aes(x = ky_bao_cao, y = tong_tai_san/1e6), color = "blue", size = 2) +
geom_point(aes(x = ky_bao_cao, y = cho_vay_khach_hang/1e6), color = "red", size = 2) +
scale_color_manual(values = c("Tổng tài sản" = "blue", "Cho vay KH" = "red")) +
labs(title = "So sánh Tổng tài sản và Cho vay KH",
x = "Năm", y = "Giá trị (triệu VND)", color = "Chỉ tiêu") +
theme_minimal()
print(p6)🔹 Giải thích code
Vẽ hai geom_line() cho tong_tai_san/1e6 và cho_vay_khach_hang/1e6, đặt màu khác nhau.
scale_color_manual(…) → gán tên/ màu cho legend.
geom_point() để nhấn các điểm.
🔹 Nhận xét
Xu hướng chung: Cả Tổng tài sản và Cho vay KH đều có xu hướng tăng trưởng liên tục và mạnh mẽ trong toàn bộ giai đoạn 2015-2024.
Mối quan hệ: Hai chỉ tiêu này có mối quan hệ đồng biến mạnh. Khi Tổng tài sản tăng, Cho vay KH cũng tăng theo.
Giai đoạn tăng trưởng mạnh: Cả hai chỉ tiêu đều cho thấy sự tăng tốc rõ rệt trong những năm gần đây, đặc biệt là sau năm 2021.
df$ty_le_cho_vay <- df$cho_vay_khach_hang / df$tong_tai_san * 100
p7 <- ggplot(df, aes(x = ky_bao_cao, y = ty_le_cho_vay)) +
geom_col(fill = "orange", alpha = 0.7) +
geom_line(color = "darkorange", size = 1) +
geom_point(color = "darkorange", size = 2) +
geom_text(aes(label = paste0(round(ty_le_cho_vay, 1), "%")), vjust = -0.5, size = 3) +
geom_hline(yintercept = mean(df$ty_le_cho_vay), color = "red", linetype = "dashed") +
labs(title = "Tỷ lệ Cho vay/Tổng tài sản", x = "Năm", y = "Tỷ lệ (%)") +
theme_minimal()
print(p7)🔹 Giải thích code
df\(ty_le_cho_vay <- df\)cho_vay_khach_hang / df$tong_tai_san * 100 → tính tỉ lệ % cho vay trên tài sản.
geom_col() + geom_line() + geom_point() → cột + đường hiển thị tỷ lệ theo năm.
geom_hline(yintercept = mean(…), …) → đường trung bình tỉ lệ.
🔹Nhận xét
Xu hướng chung: Tỷ lệ này có xu hướng tăng dần qua thời gian, từ 62.9% (Năm 2015) lên 65.1% (Năm 2024).
Đạt đỉnh: Tỷ lệ đạt mức cao nhất là 68% vào năm 2020 và 68.8% vào năm 2022.
Ổn định ở mức cao: Từ năm 2018 trở đi, tỷ lệ này ổn định ở mức trên 62% và thường xuyên vượt qua hoặc tiệm cận đường tham chiếu (đường đứt nét màu đỏ, khoảng 64-65%).
p8 <- ggplot(df, aes(x = tong_tai_san/1e6, y = loi_nhuan_sau_thue/1e3)) +
geom_point(color = "darkgreen", size = 3, alpha = 0.7) +
geom_smooth(method = "lm", se = TRUE, color = "red", fill = "pink") +
geom_text(aes(label = ky_bao_cao), vjust = -1, size = 3) +
geom_rug(color = "gray") +
labs(title = "Mối quan hệ Tổng tài sản và Lợi nhuận sau thuế",
x = "Tổng tài sản (triệu VND)", y = "Lợi nhuận sau thuế (nghìn VND)") +
theme_minimal()
print(p8)🔹 Giải thích code
aes(x = tong_tai_san/1e6, y = loi_nhuan_sau_thue/1e3) → scatter giữa tổng tài sản (triệu) và lợi nhuận (nghìn).
geom_smooth(method = “lm”, se = TRUE, color = “red”, fill = “pink”) → đường hồi quy + vùng confidence.
geom_text(aes(label = ky_bao_cao)) → gắn nhãn năm.
geom_rug() → hiển thị phân bố dọc/ ngang ở biên plot.
🔹Nhận xét
Mối quan hệ: Có một mối quan hệ tuyến tính đồng biến (tích cực) rất mạnh giữa Tổng tài sản và Lợi nhuận sau thuế.
Ý nghĩa: Khi Tổng tài sản tăng lên (quy mô công ty mở rộng), Lợi nhuận sau thuế cũng có xu hướng tăng theo rõ rệt.
Sự phù hợp của mô hình: Đường hồi quy tuyến tính (màu đỏ) nằm gần như xuyên qua tất cả các điểm dữ liệu, và vùng tin cậy (màu hồng nhạt) khá hẹp, cho thấy mô hình này phù hợp rất tốt với dữ liệu.
cor_data <- df %>%
select(tong_tai_san, cho_vay_khach_hang, tien_gui_cua_khach_hang,
loi_nhuan_sau_thue, tong_von_chu_so_huu) %>%
cor()
names_viet <- c(
"Tổng tài sản",
"Cho vay khách hàng",
"Tiền gửi khách hàng",
"Lợi nhuận sau thuế",
"Tổng vốn chủ sở hữu"
)
colnames(cor_data) <- names_viet
rownames(cor_data) <- names_viet
library(reshape2)
cor_melt <- melt(cor_data)
p9 <- ggplot(cor_melt, aes(x = Var1, y = Var2, fill = value)) +
geom_tile(color = "white") +
geom_text(aes(label = round(value, 2)), color = "white", size = 4) +
scale_fill_gradient2(low = "blue", high = "red", mid = "white", midpoint = 0) +
labs(title = "Ma trận tương quan các chỉ tiêu", x = "", y = "") +
theme_minimal()
print(p9)🔹 Giải thích code
cor() trên các chỉ tiêu tài chính → ma trận tương quan.
melt(cor_data) → chuyển sang dạng dài để ggplot vẽ
geom_tile(color = “white”) + geom_text(…) → ô màu với giá trị tương quan; scale_fill_gradient2(…) chọn màu hai đầu.
🔹 Nhận xét
Ma trận này cho thấy mối quan hệ giữa các chỉ tiêu: Tổng tài sản, Cho vay khách hàng, Tiền gửi khách hàng, Lợi nhuận sau thuế, và Tổng vốn chủ sở hữu.
Tương quan rất mạnh và cùng chiều: Tất cả các cặp chỉ tiêu trong ma trận đều cho thấy hệ số tương quan rất cao (từ 0.9 trở lên).
Hầu hết các hệ số tương quan đều nằm trong khoảng 0.95 đến 1.00.
Màu sắc đỏ đậm thống trị toàn bộ ma trận cũng củng cố điều này.
df$CAR <- df$tong_von_chu_so_huu / df$tong_tai_san * 100
p10 <- ggplot(df, aes(x = ky_bao_cao, y = CAR)) +
geom_col(fill = "lightsteelblue", alpha = 0.8) +
geom_line(aes(group = 1), color = "darkblue", size = 1.2) +
geom_point(color = "darkblue", size = 2.5) +
geom_text(aes(label = paste0(round(CAR, 1), "%")), vjust = -0.5, size = 3) +
geom_hline(yintercept = 8, color = "red", linetype = "dashed", size = 1) +
labs(title = "Tỷ lệ an toàn vốn (CAR)",
x = "Năm", y = "CAR (%)") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
print(p10)🔹 Giải thích code
df\(CAR <- df\)tong_von_chu_so_huu / df$tong_tai_san * 100 → CAR %.
geom_col() + geom_line() + geom_point() + geom_text() → hiển thị CAR theo năm với nhãn.
geom_hline(yintercept = 8, …) → tham chiếu ngưỡng CAR = 8% (ví dụ chuẩn Basel).
🔹Nhận xét Xu hướng Tỷ lệ An toàn Vốn (CAR)
Xu hướng Giảm chung: Tỷ lệ CAR có xu hướng giảm dần trong toàn bộ giai đoạn, từ mức 7.6% (Năm 2015) xuống còn 4.8% (Năm 2024).
Tiệm cận Ngưỡng tối thiểu:
Ngưỡng quy định (đường đứt nét màu đỏ) là 8%. Tỷ lệ CAR của công ty luôn thấp hơn ngưỡng quy định trong suốt 10 năm.
Tỷ lệ này đã giảm đáng kể trong những năm gần đây, đặc biệt là sau năm 2021 (5.9%) và duy trì ở mức thấp (khoảng 4.8% - 5%) trong giai đoạn 2022-2024.
radar_data <- df %>%
filter(ky_bao_cao %in% c("Năm 2024", "Năm 2015")) %>%
group_by(ky_bao_cao) %>%
summarise(
tong_tai_san = mean(tong_tai_san, na.rm = TRUE),
cho_vay_khach_hang = mean(cho_vay_khach_hang, na.rm = TRUE),
tien_gui_cua_khach_hang = mean(tien_gui_cua_khach_hang, na.rm = TRUE),
loi_nhuan_sau_thue = mean(loi_nhuan_sau_thue, na.rm = TRUE),
tong_von_chu_so_huu = mean(tong_von_chu_so_huu, na.rm = TRUE)
) %>%
ungroup()
# 🔹 Chỉ scale các cột số
radar_data_scaled <- radar_data %>%
mutate(across(where(is.numeric), scale)) %>%
rename(Year = ky_bao_cao)
# 🔹 Dạng long cho ggplot
radar_data_long <- radar_data_scaled %>%
pivot_longer(-Year, names_to = "Variable", values_to = "Value")
# 🔹 Biểu đồ radar
p11 <- ggplot(radar_data_long, aes(x = Variable, y = Value, color = Year, group = Year)) +
geom_point(size = 3) +
geom_polygon(alpha = 0.2, fill = NA) +
geom_line(size = 1) +
coord_polar() +
labs(title = "So sánh chỉ tiêu năm 2024 và 2015", x = "", y = "") +
theme_minimal()
print(p11)🔹 Giải thích code
Lọc 2 năm, chọn các chỉ tiêu, scale() chuẩn hóa (z-score).
pivot_longer() đưa về dạng dài cho ggplot.
coord_polar() + geom_polygon() + geom_line() + geom_point() → vẽ chart radar/giọt.
🔹 Nhận xét
Tăng trưởng Quy mô Khổng lồ: Tất cả 5 chỉ tiêu được so sánh đều cho thấy mức tăng trưởng rất lớn từ Năm 2015 đến Năm 2024.
Đường biểu diễn của Năm 2024 (màu xanh lam, chỉ là một điểm trung tâm nhỏ) hoàn toàn bị áp đảo bởi đường biểu diễn của Năm 2015 (màu đỏ)
Đồng đều về Tăng trưởng: Mức tăng trưởng (hoặc mức độ thay đổi) giữa hai năm là đồng đều ở cả 5 chỉ tiêu: Tổng vốn chủ sở hữu, Cho vay khách hàng, Lợi nhuận sau thuế, Tiền gửi của khách hàng, và Tổng tài sản. Tất cả các điểm trên đường cong đều nằm ở một bán kính tương tự
df$ty_le_no_VCSH <- (df$tong_tai_san - df$tong_von_chu_so_huu) / df$tong_von_chu_so_huu
p12 <- ggplot(df, aes(x = ky_bao_cao, y = ty_le_no_VCSH)) +
geom_col(fill = "coral", alpha = 0.7) +
geom_line(aes(group = 1), color = "darkred", size = 1.2) +
geom_point(color = "darkred", size = 2.5) +
geom_text(aes(label = round(ty_le_no_VCSH, 1)), vjust = -0.5, size = 3) +
geom_hline(yintercept = mean(df$ty_le_no_VCSH),
color = "blue", linetype = "dashed", size = 1) +
labs(title = "Tỷ lệ Nợ/Vốn chủ sở hữu",
x = "Năm", y = "Tỷ lệ Nợ/VCSH") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
print(p12)🔹 Giải thích code
df\(ty_le_no_VCSH <- (df\)tong_tai_san - df\(tong_von_chu_so_huu) / df\)tong_von_chu_so_huu → tỷ lệ nợ trên vốn.
geom_col() + geom_line() + geom_point() + geom_text() hiển thị theo năm.
geom_hline(yintercept = mean(…), …) → đường trung bình.
🔹 Nhận xét
Xu hướng Tăng chung: Tỷ lệ Nợ/VCSH có xu hướng tăng liên tục trong suốt giai đoạn từ năm 2015 (12.2) đến năm 2024 (19.6).
Vượt ngưỡng (2019-2024): Tỷ lệ này đã vượt qua đường tham chiếu (đường đứt nét màu xanh dương, khoảng 16) từ năm 2019 trở đi. Tăng tốc (2022-2024):
Tỷ lệ tăng đột biến từ năm 2021 (15.9) lên 19.4 vào năm 2022.
Mức cao nhất đạt được là 19.6 vào năm 2024.
p13 <- ggplot(df, aes(x = tong_tai_san/1e6, y = loi_nhuan_sau_thue/1e3)) +
geom_point(aes(size = cho_vay_khach_hang/tong_tai_san * 100,
color = tong_von_chu_so_huu/tong_tai_san * 100),
alpha = 0.7) +
geom_smooth(method = "lm", se = FALSE, color = "red", linetype = "dashed") +
geom_label_repel(aes(label = substring(ky_bao_cao, 5)),
size = 3, box.padding = 0.5) +
scale_size_continuous(name = "Tỷ lệ cho vay (%)", range = c(3, 8)) +
scale_color_gradient(name = "Tỷ lệ VCSH (%)", low = "blue", high = "red") +
labs(title = "Mối quan hệ Rủi ro - Lợi nhuận",
x = "Tổng tài sản (triệu VND)",
y = "Lợi nhuận sau thuế (nghìn VND)") +
theme_minimal()
print(p13)🔹 Giải thích code
geom_point(aes(size = cho_vay_khach_hang/tong_tai_san * 100, color = tong_von_chu_so_huu/tong_tai_san * 100)) → kích thước điểm theo tỷ lệ cho vay, màu theo tỷ lệ vốn CSH.
geom_smooth(method = “lm”, se = FALSE, color = “red”, linetype = “dashed”) → đường hồi quy.
geom_label_repel(aes(label = substring(ky_bao_cao, 5))) → nhãn năm rút gọn, tránh chồng.
🔹 Nhận xét
Tương quan mạnh: Có một mối quan hệ đồng biến tuyến tính rất mạnh giữa Tổng tài sản và Lợi nhuận sau thuế (tức là quy mô càng lớn, lợi nhuận càng cao) . Đường xu hướng (đứt nét đỏ) thể hiện rõ điều này.
Tăng trưởng bùng nổ: Sự tăng trưởng quy mô và lợi nhuận diễn ra rất nhanh trong giai đoạn 2022 - 2024, với các điểm dữ liệu nằm xa và cao hơn so với giai đoạn trước.
Màu sắc chuyển từ Đỏ (tỷ lệ VCSH% cao) sang Xanh/Tím (tỷ lệ VCSH% thấp) theo thời gian, đặc biệt là sau năm 2021.
Kích cỡ điểm (Tỷ lệ Cho vay %) không biến động quá lớn, duy trì ở mức cao và ổn định qua các năm, cho thấy Cho vay KH luôn là hoạt động kinh doanh cốt lõi và chiếm tỷ trọng lớn trong tài sản.
correlation_analysis <- df %>%
arrange(ky_bao_cao) %>%
mutate(
cor_cho_vay_loi_nhuan = rollapply(
data = cbind(cho_vay_khach_hang, loi_nhuan_sau_thue),
width = 3,
FUN = function(x) cor(x[,1], x[,2]),
by.column = FALSE,
fill = NA
)
)
p14 <- ggplot(correlation_analysis, aes(x = ky_bao_cao, y = cor_cho_vay_loi_nhuan)) +
geom_col(aes(fill = cor_cho_vay_loi_nhuan), alpha = 0.8) +
geom_line(aes(group = 1), color = "purple", size = 1.2) +
geom_point(color = "purple", size = 2.5) +
geom_text(aes(label = round(cor_cho_vay_loi_nhuan, 2)),
vjust = -0.5, size = 3) +
scale_fill_gradient2(low = "red", mid = "white", high = "blue",
midpoint = 0, limits = c(-1, 1)) +
geom_hline(yintercept = 0, color = "black", size = 0.5) +
geom_hline(yintercept = c(-0.5, 0.5), color = "gray", linetype = "dashed") +
labs(title = "Tương quan động giữa Cho vay và Lợi nhuận (3 năm)",
x = "Năm", y = "Hệ số tương quan", fill = "Tương quan") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
print(p14)🔹 Giải thích code
arrange(ky_bao_cao) đảm bảo thứ tự thời gian.
rollapply(…, width = 3, FUN = function(x) cor(x[,1], x[,2]) …) → tính hệ số tương quan trượt (3 năm) giữa cho_vay_khach_hang và loi_nhuan_sau_thue.
Vẽ geom_col() + geom_line() + geom_point() và dùng scale_fill_gradient2() để color theo giá trị tương quan; thêm các đường tham chiếu (y=0, ±0.5).
🔹 Nhận xét
Mối tương quan cực mạnh: Hệ số tương quan giữa Cho vay và Lợi nhuận là rất cao và luôn dương (đồng biến) trong suốt giai đoạn 2015-2024. Tăng dần và Ổn định ở mức đỉnh:
Hệ số tăng từ 0.65 (tính đến năm 2015) lên mức 0.97 (tính đến năm 2017).
Từ năm 2017 trở đi, hệ số tương quan duy trì ở mức cực kỳ cao, chủ yếu nằm trong khoảng 0.91 đến 1.00 (được tô màu xanh đậm/tím).
Điểm cao nhất là 1.00 (được tính đến năm 2018 và 2022).
p15 <- ggplot(df, aes(x = tong_tai_san/1e6)) +
geom_histogram(aes(y = ..density..), fill = "lightgreen", alpha = 0.7, bins = 6) +
geom_density(color = "darkgreen", size = 1.2) +
geom_rug(color = "red") +
geom_vline(aes(xintercept = mean(tong_tai_san/1e6)), color = "blue", linetype = "dashed", size = 1) +
geom_vline(aes(xintercept = median(tong_tai_san/1e6)), color = "red", linetype = "dashed", size = 1) +
labs(title = "Phân phối Tổng tài sản", x = "Tổng tài sản (triệu VND)", y = "Mật độ") +
theme_minimal()
print(p15)🔹 Giải thích code
geom_histogram(aes(y = ..density..), bins = 6) → histogram chuẩn hoá theo mật độ.
geom_density() → đường mật độ mượt.
geom_rug() → hiển thị từng quan sát ở đáy . geom_vline(…) cho mean và median.
🔹 Nhận xét
Hình dạng Phân phối: Phân phối của Tổng tài sản nhìn chung là tương đối đối xứng (hoặc hơi lệch nhẹ sang phải/trái, tùy vào định nghĩa chính xác của đường mật độ).
Giá trị Trung tâm: Cả giá trị trung bình (Mean) (đường màu xanh dương) và giá trị trung vị (Median) (đường màu đỏ) đều nằm rất gần nhau và tập trung xung quanh khoảng 480 - 500 triệu VND.
Việc Trung bình và Trung vị gần nhau củng cố nhận định về tính đối xứng của dữ liệu, cho thấy ít có giá trị ngoại lai (outliers) quá lớn hoặc quá nhỏ gây méo mó phân phối.
cumulative_data <- df %>%
arrange(ky_bao_cao) %>%
mutate(cum_tong_tai_san = cumsum(tong_tai_san)/1e6,
cum_loi_nhuan = cumsum(loi_nhuan_sau_thue)/1e3)
p16 <- ggplot(cumulative_data, aes(x = ky_bao_cao)) +
geom_line(aes(y = cum_tong_tai_san, color = "Tổng tài sản"), size = 1.2) +
geom_line(aes(y = cum_loi_nhuan, color = "Lợi nhuận"), size = 1.2) +
geom_point(aes(y = cum_tong_tai_san), color = "blue", size = 2) +
geom_point(aes(y = cum_loi_nhuan), color = "red", size = 2) +
geom_area(aes(y = cum_tong_tai_san), fill = "blue", alpha = 0.1) +
scale_color_manual(values = c("Tổng tài sản" = "blue", "Lợi nhuận" = "red")) +
labs(title = "Giá trị tích lũy qua các năm", x = "Năm", y = "Giá trị tích lũy", color = "Chỉ tiêu") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
print(p16)🔹 Giải thích code cum_tong_tai_san = cumsum(tong_tai_san)/1e6 và cum_loi_nhuan = cumsum(loi_nhuan_sau_thue)/1e3 → tích lũy theo thứ tự thời gian.
Vẽ hai đường tích lũy, điểm, và geom_area() cho tổng tài sản để nhấn.
🔹 Nhận xét Xu hướng Tăng chung: Cả Lợi nhuận tích lũy (màu đỏ) và Tổng tài sản tích lũy (màu xanh dương) đều có xu hướng tăng trưởng liên tục và mạnh mẽ qua các năm . Lợi nhuận Tích lũy (Màu đỏ): Tăng trưởng đột phá và có độ dốc lớn hơn nhiều so với Tổng tài sản tích lũy, đặc biệt là trong giai đoạn cuối (2022-2024). Điều này cho thấy công ty đã tạo ra tổng lợi nhuận rất lớn qua các năm, với sự tăng trưởng mạnh mẽ nhất vào giai đoạn gần đây.
Tổng Tài sản Tích lũy (Màu xanh dương): Tăng trưởng ổn định nhưng với tốc độ chậm hơn so với lợi nhuận tích lũy.
Chênh lệch: Khoảng cách giữa Lợi nhuận tích lũy và Tổng tài sản tích lũy ngày càng mở rộng theo thời gian.
library(dplyr)
library(ggplot2)
library(RColorBrewer)
# Dữ liệu năm 2023 không có "Vay TCTD khác"
du_lieu_2023 <- data.frame(
chi_tieu = c("Cho vay khách hàng", "Tiền gửi của khách hàng",
"Chứng khoán đầu tư", "Tài sản khác"),
gia_tri = c(438411368, 536873344, 71936877,
674374966 - (438411368 + 536873344 + 71936877))
)
set3_colors <- brewer.pal(n = 4, name = "Set3")
du_lieu_2023 <- du_lieu_2023 %>%
mutate(gia_tri = abs(gia_tri),
phan_tram = gia_tri / sum(gia_tri) * 100,
label = paste0(round(phan_tram, 1), "%"),
ma_mau = set3_colors)
# Vẽ pie chart (chỉ hiện % trên lát cắt)
ggplot(du_lieu_2023, aes(x = "", y = phan_tram, fill = chi_tieu)) +
geom_bar(stat = "identity", width = 1, color = "white") +
coord_polar("y", start = 0) +
geom_text(aes(label = label),
position = position_stack(vjust = 0.5),
size = 4, color = "black", fontface = "bold") +
scale_fill_manual(values = setNames(set3_colors, du_lieu_2023$chi_tieu)) +
labs(
title = "BIỂU ĐỒ CƠ CẤU TÀI SẢN - NĂM 2023",
fill = "Các khoản mục"
) +
theme_void() +
theme(
plot.title = element_text(hjust = 0.5, face = "bold", size = 14),
plot.subtitle = element_text(hjust = 0.5, size = 12),
legend.position = "right"
)Giải thích code: - geom_bar(…, stat = “identity”) → tạo cột theo giá trị thực (dùng để xoay thành lát tròn).
-mcolor = “white” → viền = trắng ngăn cách các phần.
geom_text(aes(label = label): Hiển thị % của từng phần ngay bên trong lát cắt, căn giữa (vjust = 0.5).
scale_fill_manual() → dùng chính xác màu Set3 cho từng hạng mục.
labs() → đặt tiêu đề, chú thích và ghi chú tổng tài sản (định dạng có dấu phẩy ngăn cách).
Nhận xét:
Tiền gửi của khách hàng chiếm tỷ trọng lớn nhất (37.8%), cho thấy nguồn vốn chủ yếu của ngân hàng đến từ khoản mục này.
Cho vay khách hàng đứng thứ hai (30.9%), thể hiện vai trò trọng yếu của hoạt động cho vay trong tổng tài sản.
Tài sản khác cũng chiếm tỷ lệ đáng kể (26.3%), phản ánh quy mô các tài sản không nằm trong ba khoản mục chính còn lại.
Chứng khoán đầu tư chỉ chiếm một phần nhỏ (5.1%), cho thấy đầu tư vào chứng khoán không phải là mảng trọng tâm của cấu trúc tài sản.
p18 <- ggplot(df, aes(x = factor(ky_bao_cao), group = 1)) +
geom_line(aes(y = tong_tai_san/1e6, color = "Tổng tài sản"), size = 1.2) +
geom_line(aes(y = cho_vay_khach_hang/1e6, color = "Cho vay"), size = 1.2) +
geom_line(aes(y = tien_gui_cua_khach_hang/1e6, color = "Tiền gửi"), size = 1.2) +
geom_point(aes(y = tong_tai_san/1e6), color = "blue", size = 2) +
geom_point(aes(y = cho_vay_khach_hang/1e6), color = "red", size = 2) +
geom_point(aes(y = tien_gui_cua_khach_hang/1e6), color = "green", size = 2) +
scale_color_manual(values = c("Tổng tài sản" = "blue", "Cho vay" = "red", "Tiền gửi" = "green")) +
labs(title = "Biến động các chỉ tiêu qua các năm", x = "Năm", y = "Giá trị (triệu VND)", color = "Chỉ tiêu") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
print(p18)🔹 Giải thích code
Vẽ cùng lúc 3 geom_line() cho tong_tai_san/1e6, cho_vay_khach_hang/1e6, tien_gui_cua_khach_hang/1e6 với màu khác nhau bằng scale_color_manual(). geom_point() để nhấn từng đường.
🔹 Nhận xét Tăng trưởng Quy mô & Hoạt động Cốt lõi: Các chỉ tiêu cốt lõi như Tổng tài sản, Cho vay khách hàng, Tiền gửi khách hàng đều tăng trưởng liên tục và mạnh mẽ qua các năm. Biểu đồ Biến động các chỉ tiêu qua các năm cho thấy sự tăng trưởng đồng bộ của 3 chỉ tiêu này (Cho vay < Tiền gửi < Tổng tài sản).
Tổng vốn chủ sở hữu duy trì xu hướng tăng trưởng dài hạn, mặc dù bị sụt giảm tạm thời vào năm 2022 (-11,70%), nhưng đã phục hồi mạnh mẽ vào năm 2023-2024 (đạt mức tăng trưởng cao nhất 17,98% vào 2023).
base_year <- df %>%
filter(grepl("2015", ky_bao_cao)) %>%
pull(tong_tai_san) %>%
first()
df <- df %>%
mutate(pct_change = (tong_tai_san - base_year) / base_year * 100)
p19 <- ggplot(df, aes(x = ky_bao_cao, y = pct_change)) +
geom_col(fill = "lightcoral", alpha = 0.7) +
geom_line(color = "red", size = 1.2, group = 1) + # thêm group=1 để nối các điểm
geom_point(color = "red", size = 2.5) +
geom_text(aes(label = paste0(round(pct_change, 1), "%")), vjust = -0.5, size = 3) +
geom_hline(yintercept = 0, color = "black", size = 0.5) +
labs(title = "Phần trăm thay đổi Tổng tài sản so với năm 2015",
x = "Năm", y = "Thay đổi (%)") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
print(p19)🔹 Giải thích code
base_year <- df\(tong_tai_san[df\)ky_bao_cao == “Năm 2015”] → lấy giá trị gốc (năm 2015).
df\(pct_change <- (df\)tong_tai_san - base_year) / base_year * 100 → tính % thay đổi so với nền tảng.
Vẽ geom_col() + geom_line() + geom_point() + geom_text(); geom_hline(yintercept = 0) so sánh tăng/giảm.
Nhận xét
Tổng tài sản liên tiếp tăng qua từng năm, không hề có dấu hiệu giảm hoặc đi ngang trong suốt giai đoạn phân tích.
Xu hướng tăng mạnh từ sau năm 2020, cụ thể: năm 2021 đạt gần 90%, năm 2022 vượt 100%, các năm tiếp theo tăng vọt lên 130% và 149%.
Mức tăng trưởng tuyệt đối vượt trội cho thấy doanh nghiệp/tổ chức có chiến lược mở rộng rõ rệt hoặc tận dụng tốt các cơ hội thị trường.
Không xuất hiện thời kỳ giảm sút tài sản; tốc độ tăng đều, phản ánh hoạt động kinh doanh/tài chính ổn định.
p20 <- ggplot(df, aes(x = cho_vay_khach_hang/1e6, y = tien_gui_cua_khach_hang/1e6)) +
geom_point(aes(size = loi_nhuan_sau_thue/1e3, color = tong_von_chu_so_huu/1e6), alpha = 0.7) +
geom_smooth(method = "lm", se = FALSE, color = "red") +
geom_text(aes(label = substring(ky_bao_cao, 5)), vjust = -1, size = 3) +
scale_size_continuous(name = "Lợi nhuận (nghìn)") +
scale_color_gradient(name = "Vốn CSH (triệu)", low = "blue", high = "red") +
labs(title = "Mối quan hệ đa biến giữa các chỉ tiêu",
x = "Cho vay KH (triệu VND)", y = "Tiền gửi KH (triệu VND)") +
theme_minimal()
print(p20)🔹 Giải thích code
aes(x = cho_vay_khach_hang/1e6, y = tien_gui_cua_khach_hang/1e6) → scatter giữa cho vay và tiền gửi (triệu).
aes(size = loi_nhuan_sau_thue/1e3, color = tong_von_chu_so_huu/1e6) → kích thước đại diện cho lợi nhuận (nghìn), màu cho vốn CSH (triệu).
geom_smooth(method = “lm”, se = FALSE) → đường hồi quy chung.
geom_text(aes(label = substring(ky_bao_cao, 5))) → gắn nhãn năm rút gọn.
🔹 Nhận xét
Biểu đồ thể hiện mối quan hệ tuyến tính đồng biến rất mạnh giữa cho vay khách hàng và tiền gửi khách hàng, khi hai biến này tăng gần như song song theo thời gian.
Các điểm dữ liệu dịch chuyển rõ rệt từ góc dưới trái (2015) lên góc trên phải (2024), phản ánh quy mô hoạt động tín dụng và huy động vốn đều tăng trưởng liên tục.
Đồng thời, kích thước điểm (lợi nhuận) và màu sắc (vốn chủ sở hữu) cũng tăng dần, cho thấy doanh nghiệp không chỉ mở rộng quy mô mà còn nâng cao hiệu quả sinh lời và tích lũy vốn, thể hiện sức mạnh tài chính ngày càng vững chắc qua các năm.