library(readxl)
library(tidyverse)
library(lubridate)
library(scales)
library(ggplot2)
library(dplyr)
library(stringr)
library(skimr)
library(kableExtra)
library(patchwork)
library(reshape2)
library(knitr)
library(janitor)
library(Hmisc)
library(psych)
library(forecast)
library(tseries)
library(GGally)
library(corrplot)
library(ggpubr)
library(moments)
options(scipen = 999)
library(showtext)
font_add_google("Roboto", "Roboto")
showtext_auto()# Hàm định dạng số với dấu phân cách hàng nghìn
format_number <- function(x, digits = 0) {
if(is.numeric(x)) {
return(format(round(x, digits), big.mark = ",", scientific = FALSE, trim = TRUE))
}
return(x)
}
# Hàm định dạng tiền tệ (tỷ VND)
format_currency <- function(x, suffix = " tỷ VND", digits = 1) {
if(is.numeric(x)) {
value <- round(x/1e9, digits)
return(paste0(format(value, big.mark = ",", scientific = FALSE), suffix))
}
return(x)
}
# Hàm áp dụng định dạng cho data frame
format_dataframe <- function(df, currency_cols = NULL, digit_list = NULL) {
result <- df
for(col in names(df)) {
if(is.numeric(df[[col]])) {
if(col %in% currency_cols) {
result[[col]] <- format_currency(df[[col]])
} else {
digits <- if(!is.null(digit_list) && col %in% names(digit_list)) digit_list[[col]] else 0
result[[col]] <- format_number(df[[col]], digits)
}
}
}
return(result)
}Sử dụng hàm foramt_number(x) để chuẩn hóa dữ liệu số nhập từ file csv.
Tiếp theo sử dụng hàm format_currency(x) để tạo chuỗi tiền tệ
Và cuối cùng là hàm formar_dataframe(x) để làm sạch bồ dữ liệu.Giảm lỗi khi tính toán (vì “$1,200” không thể dùng trong phép tính nếu chưa chuyển đổi).
dim_info <- data.frame(
Thông_tin = c("Số quan sát", "Số biến"),
Giá_trị = c(nrow(dl), ncol(dl))
)
dim_info## Thông_tin Giá_trị
## 1 Số quan sát 200000
## 2 Số biến 15
Kết quả cho thấy bộ dữ liệu có 200.000 quan sát và 15 biến.
## Rows: 200,000
## Columns: 15
## $ Company <chr> "Innovate Industries", "NexGen Systems", "Alpha Innov…
## $ Campaign_Type <chr> "Email", "Email", "Influencer", "Display", "Email", "…
## $ Target_Audience <chr> "Men 18-24", "Women 35-44", "Men 25-34", "All Ages", …
## $ Duration <chr> "30 days", "60 days", "30 days", "60 days", "15 days"…
## $ Channel_Used <chr> "Google Ads", "Google Ads", "YouTube", "YouTube", "Yo…
## $ Conversion_Rate <dbl> 0.04, 0.12, 0.07, 0.11, 0.05, 0.07, 0.13, 0.08, 0.09,…
## $ Acquisition_Cost <chr> "$16,174.00", "$11,566.00", "$10,200.00", "$12,724.00…
## $ ROI <dbl> 6.29, 5.61, 7.18, 5.55, 6.50, 4.36, 2.86, 5.55, 6.73,…
## $ Location <chr> "Chicago", "New York", "Los Angeles", "Miami", "Los A…
## $ Language <chr> "Spanish", "German", "French", "Mandarin", "Mandarin"…
## $ Clicks <int> 506, 116, 584, 217, 379, 100, 817, 624, 861, 642, 321…
## $ Impressions <int> 1922, 7523, 7698, 1820, 4201, 1643, 8749, 7854, 1754,…
## $ Engagement_Score <int> 6, 7, 1, 7, 3, 1, 10, 7, 6, 3, 10, 1, 10, 4, 1, 5, 3,…
## $ Customer_Segment <chr> "Health & Wellness", "Fashionistas", "Outdoor Adventu…
## $ Date <chr> "01/01/2021", "02/01/2021", "03/01/2021", "04/01/2021…
## Biến
## 1 Company
## 2 Campaign_Type
## 3 Target_Audience
## 4 Duration
## 5 Channel_Used
## 6 Conversion_Rate
## 7 Acquisition_Cost
## 8 ROI
## 9 Location
## 10 Language
## 11 Clicks
## 12 Impressions
## 13 Engagement_Score
## 14 Customer_Segment
## 15 Date
Kết quả trả ra cho thấy bộ dữ liệu có tổng 15 biến.
## Company Campaign_Type Target_Audience Duration Channel_Used
## 1 Innovate Industries Email Men 18-24 30 days Google Ads
## 2 NexGen Systems Email Women 35-44 60 days Google Ads
## 3 Alpha Innovations Influencer Men 25-34 30 days YouTube
## 4 DataTech Solutions Display All Ages 60 days YouTube
## 5 NexGen Systems Email Men 25-34 15 days YouTube
## Conversion_Rate Acquisition_Cost ROI Location Language Clicks Impressions
## 1 0.04 $16,174.00 6.29 Chicago Spanish 506 1922
## 2 0.12 $11,566.00 5.61 New York German 116 7523
## 3 0.07 $10,200.00 7.18 Los Angeles French 584 7698
## 4 0.11 $12,724.00 5.55 Miami Mandarin 217 1820
## 5 0.05 $16,452.00 6.50 Los Angeles Mandarin 379 4201
## Engagement_Score Customer_Segment Date
## 1 6 Health & Wellness 01/01/2021
## 2 7 Fashionistas 02/01/2021
## 3 1 Outdoor Adventurers 03/01/2021
## 4 7 Health & Wellness 04/01/2021
## 5 3 Health & Wellness 05/01/2021
Đây là 5 dòng đầu tiên của bộ dữ liệu.
danh_sach_bien_so <- c("Duration", "Conversion_Rate", "Acquisition_Cost",
"ROI", "Clicks", "Impressions", "Engagement_Score")
danh_sach_bien_chu <- c("Company", "Campaign_Type", "Channel_Used",
"Location", "Customer_Segment")
biến_phân_loại <- data.frame(
Loại = c("Biến số", "Biến phân loại"),
Số_lượng = c(7, 5)
)
biến_phân_loại$Danh_sách <- list(
danh_sach_bien_so,
danh_sach_bien_chu)
print(biến_phân_loại$Danh_sách)## [[1]]
## [1] "Duration" "Conversion_Rate" "Acquisition_Cost" "ROI"
## [5] "Clicks" "Impressions" "Engagement_Score"
##
## [[2]]
## [1] "Company" "Campaign_Type" "Channel_Used" "Location"
## [5] "Customer_Segment"
– 7 biến số: Duration, Conversion_Rate, Acquisition_Cost, ROI, Clicks, Impressions, Engagement_score.
– 5 biến phân loại: Company, Campaign_Type, Channel_Used, Location, Customer_Segment.
summary_stats <- summary(dl[c("Duration", "Conversion_Rate", "Acquisition_Cost", "ROI")])
summary_stats## Duration Conversion_Rate Acquisition_Cost ROI
## Length:200000 Min. :0.01000 Length:200000 Min. :2.000
## Class :character 1st Qu.:0.05000 Class :character 1st Qu.:3.500
## Mode :character Median :0.08000 Mode :character Median :5.010
## Mean :0.08007 Mean :5.002
## 3rd Qu.:0.12000 3rd Qu.:6.510
## Max. :0.15000 Max. :8.000
Đầu tiên, dùng hàm c()tạo 4 vector ký tự chứa 4 tên cột để phân tích (“Duration”, “Conversion_Rate”, “Acquisition_Cost”, “ROI”). Sau đó dùng hàm summary() là hàm kĩ thuật thống kê. Ta sẽ thống kê các chỉ số sau:
Min: Giá trị nhỏ nhất
1st Qu.(Phân vị 25%): 25% dữ liệu nhỏ hơn giá trị này
Median(Trung vị): Giá trị ở giữa (50%)
Mean(Trung bình): Giá trị trung bình cộng
3rd Qu.(Phân vị 75%): 75% dữ liệu nhỏ hơn giá trị này
Max: Giá trị lớn nhất
Ta được kết quả trả về như sau:
– Min.(Tối thiểu): 0.01000(1%)
– 1st Qu.(Phân vị 25%): 0.05000 (5%)
– Median(Trung vị): 0.08000 (8%)
– Mean(Trung bình): độ 0.08007
– 3rd Qu.(Phân vị 75%): 0.12000(12%)
– Max.(Tối đa): 0.15000 (15%)
Nhận xét: Dữ liệu khá tập trung, với 50% giá trị nằm trong khoảng từ 5% đến 12%.
– Min.(Tối thiểu): 2.000
– 1st Qu.(Phân vị 25%): 3.500
– Median(Trung vị): 5.010
– Mean(Trung bình): 5.002
– 3rd Qu.(Phân vị 75%): 6.510
– Max.(Tối đa): 8.000
Nhận xét: Giá trị Trung vị (5.010) và Trung bình (5.002) rất gần nhau, cho thấy phân phối của ROI là khá đối xứng (symmetric).
missing_data <- data.frame(
Tổng_giá_trị_thiếu = sum(is.na(dl)),
Tỷ_lệ_thiếu = round(mean(is.na(dl)) * 100, 2)
)
missing_data## Tổng_giá_trị_thiếu Tỷ_lệ_thiếu
## 1 0 0
Sử dụng tính năng Vector Hóa và quy tắc TRUE=1, FALSE=0 của R.
is.na(dl): Xác định tất cả các ô có giá trị thiếu (NA).
sum(…): Tính tổng số lượng ô bị thiếu (NA) trong toàn bộ data frame.
mean(…): Tính tỷ lệ phần trăm ô bị thiếu so với tổng số ô.
Và kết quả trả ra ta thấy được là bộ dữ liệu không có giá trị bị thiếu.
duplicate_info <- data.frame(
Số_dòng_trùng_lặp = sum(duplicated(dl)),
Tỷ_lệ_trùng_lặp = round(mean(duplicated(dl)) * 100, 2)
)
duplicate_info## Số_dòng_trùng_lặp Tỷ_lệ_trùng_lặp
## 1 0 0
Dùng hàm duplicated() để tìm các dòng bị lặp lại.
duplicated(dl): Trả về TRUE cho mọi dòng mà nội dung toàn bộ dòng đó đã xuất hiện ở các dòng trước.
sum(…): Tính tổng số lượng dòng bị trùng lặp.
mean(…): Tính tỷ lệ phần trăm dòng bị trùng lặp so với tổng số dòng.
Kết quả là bộ dữ liệu không có giá trị trùng lặp.
dl$Date <- as.Date(dl$Date, format = "%d/%m/%Y")
date_range <- data.frame(
Ngày_bắt_đầu = min(dl$Date),
Ngày_kết_thúc = max(dl$Date),
Số_ngày = as.numeric(difftime(max(dl$Date), min(dl$Date), units = "days"))
)
date_range## Ngày_bắt_đầu Ngày_kết_thúc Số_ngày
## 1 2021-01-01 2021-12-31 364
Chuyển đổi cột Date từ dạng ký tự Character sang Ngày (Date) mà R có thể tính toán được.
Dùng as.Date() và chỉ định rõ định dạng gốc (%d/%m/%Y) để R không bị nhầm lẫn.
Tính toán phạm vi (Range Calculation): - Code: min(…), max(…), difftime(…)
min() & max(): Tìm ra ngày bắt đầu và ngày kết thúc của bộ dữ liệu.
difftime(…, units = “days”): Tính toán số ngày chính xác giữa hai mốc thời gian.
Kết quả bộ dữ liệu bắt đầu từ ngày 1-1-2021 đến 31-12-2021 đúng với bộ dữ liệu CSV.
gsub(“[\[\\(]", "", dl\)Acquisition_Cost): Đây là kỹ thuật xử lý chuỗi (string manipulation) sử dụng Biểu thức chính quy(Regex).
“[\[\$]”: Đây là mẫu Regex tìm kiếm ký tự [ và $ (cần phải escape bằng \ vì chúng là các ký tự đặc biệt trong Regex).
““: Thay thế các ký tự tìm thấy bằng chuỗi rỗng.
Kết quả là loại bỏ các ký tự không phải số khỏi cột.
as.numeric(…): Cuối cùng, chuyển đổi chuỗi đã được làm sạch thành kiểu số (numeric).
Ví dụ: Chuyển đổi từ định dạng tiền tệ $1,000 sang số 1000.
gsub(“days”, ““, dl$Duration): Tương tự như trên, dùng gsub() để tìm và thay thế chuỗi ký tự”days” bằng chuỗi rỗng.
as.numeric(…): Chuyển đổi chuỗi kết quả thành kiểu số (numeric).
Ví dụ: Chuyển “30 days” thành số 30.
Tạo ra một biến mới (Revenue) dựa trên công thức kinh doanh: Doanh thu = ROI x Chi phí thu hút.
Tạo ra biến Tỷ lệ nhấp (Click-Through Rate - CTR), là một chỉ số quan trọng trong quảng cáo số.
Tính toán trên Vector. R thực hiện phép chia từng cặp phần tử tương ứng của hai cột.
dl$Date <- as.Date(dl$Date, format = "%Y-%m-%d")
dl$Month <- months(dl$Date)
dl$Quarter <- quarters(dl$Date)as.Date(…, format = “%Y-%m-%d”): Bước này chuẩn hóa lại cột Date sau khi đã làm sạch. Việc sử dụng format %Y-%m-%d giả định rằng sau khi làm sạch các ký tự không phải số ở bước trước, định dạng ngày tháng là chuẩn ISO (Năm-Tháng-Ngày).
months(dl$Date): Hàm này trích xuất tên tháng (ví dụ: “Tháng Ba”, “March”) từ đối tượng ngày tháng.
quarters(dl$Date): Hàm này trích xuất quý (ví dụ: “Q1”, “Q2”) từ đối tượng ngày tháng.
Tạo biến tháng và quý cho phân tích theo thời gian
dl$Gender <- ifelse(grepl("Men", dl$Target_Audience), "Male",
ifelse(grepl("Women", dl$Target_Audience), "Female", "All"))grepl(“Men”, dl$Target_Audience): Hàm này sử dụng Regex để kiểm tra xem chuỗi “Men” có xuất hiện ở bất cứ đâu trong cột Target_Audience. Nó trả về một vector TRUE/FALSE.
ifelse(Điều kiện, Giá trị nếu TRUE, Giá trị nếu FALSE): Điều kiện chéo.
Nếu tìm thấy “Men”, gán là “Male”.
Nếu không (FALSE ở điều kiện 1), nó tiếp tục kiểm tra điều kiện thứ hai: grepl(“Women”, dl$Target_Audience).
Nếu tìm thấy “Women”, gán là “Female”.
Nếu không tìm thấy cả “Men” lẫn “Women”, gán là “All”.
dl$ROI_Tier <- cut(dl$ROI, breaks = c(0, 4, 6, 10), labels = c("Low", "Medium", "High"))
table(dl$ROI_Tier)##
## Low Medium High
## 66822 66438 66740
breaks = c(0, 4, 6, 10): Tự định nghĩa các khoảng : (0-4], (4-6], (6-10].
labels = c(“Low”, “Medium”, “High”): Gán nhãn cho các khoảng này.
Từ kết quả trả về ta thấy: Có 66822 giá trị ở mức Low,66438 ở mức Medium và 66740 ở mức High.
dl$Cost_Tier <- cut(dl$Acquisition_Cost, breaks = 3, labels = c("Low", "Medium", "High"))
table(dl$Cost_Tier)##
## Low Medium High
## 66704 66495 66801
breaks = 3: Yêu cầu R tự động chia cột Acquisition_Cost thành 3 khoảng có kích thước bằng nhau.
labels = c(“Low”, “Medium”, “High”): Gán nhãn cho 3 khoảng đó.
Từ kết quả trả về ta thấy: Có 66704 giá trị ở mức Low,66495 ở mức Medium và 66801 ở mức High.
Hàm trimws() loại bỏ khoảng trắng thừa ở đầu/cuối chuỗi.
Đảm bảo các tên kênh (Channel) giống nhau được nhận diện là một.
Ví dụ: ” Facebook ” → “Facebook”.
Sử dụng hàm scale() để chuẩn hóa hai biến (ROI và Conversion_Rate) về trung bình 0, độ lệch chuẩn 1 trước khi cộng lại.
Tạo điểm số tổng hợp để đánh giá hiệu suất.
categorical_vars <- c("Company", "Campaign_Type", "Channel_Used", "Location",
"Customer_Segment", "Gender")
dl[categorical_vars] <- lapply(dl[categorical_vars], as.factor)Dùng hàm lapply() để sử dụng hàm as.factor() lên tất cả các cột phân loại cùng một lúc.
Chuyển đổi các biến từ character sang kiểu Factor, bắt buộc cho mô hình thống kê.
Chuyển biến phân loại thành factor để phân tích thống kê.Tiết kiệm bộ nhớ, dễ dàng cho modeling.
processing_summary <- data.frame(
Biến_đã_xử_lý = length(categorical_vars) + 7,
Biến_mới_tạo = 6,
Tổng_biến_hiện_có = ncol(dl)
)
processing_summary## Biến_đã_xử_lý Biến_mới_tạo Tổng_biến_hiện_có
## 1 13 6 23
Dùng hàm processing_summary() để tổng hợp các biến đã xử lí và các biến tạo mới.
Kết quả từ bảng ta thấy có 13 biến và tọa thêm 6 biến mới.
Tổng là 23 biến.
stats_summary <- dl %>%
summarise(
ROI_trung_bình = mean(ROI),
Conversion_Rate_trung_bình = mean(Conversion_Rate),
Chi_phí_trung_bình = mean(Acquisition_Cost),
Tổng_doanh_thu = sum(Revenue),
Tổng_lượt_nhấp = sum(Clicks)
)
stats_summary## ROI_trung_bình Conversion_Rate_trung_bình Chi_phí_trung_bình Tổng_doanh_thu
## 1 5.002438 0.08006965 12504.39 12517388674
## Tổng_lượt_nhấp
## 1 109954406
Sử dụng cú pháp pipeline %>% để truyền data frame dl trực tiếp vào hàm summarise() để đi tính các chỉ số ta được kết quả:
ROI trung bình: 5.00 - Hiệu suất ở mức trung bình.
Tỷ lệ chuyển đổi: 8.01% - Khá tốt.
Tổng doanh thu: 12.52 tỷ - Quy mô lớn.
Tỷ lệ thành công: 50.03%(ROI > 5).
roi_company <- dl %>%
group_by(Company) %>%
summarise(ROI_trung_bình = mean(ROI)) %>%
arrange(desc(ROI_trung_bình))
roi_company## # A tibble: 5 × 2
## Company ROI_trung_bình
## <fct> <dbl>
## 1 TechCorp 5.01
## 2 Alpha Innovations 5.01
## 3 DataTech Solutions 5.01
## 4 Innovate Industries 5.00
## 5 NexGen Systems 4.99
group_by(Company): Phân chia bộ dữ liệu dl thành các nhóm riêng biệt dựa trên giá trị của cột Company.
summarise(ROI_trung_bình = mean(ROI)): Tính toán ROI trung bình cho từng nhóm Công ty đã được tạo.
arrange(desc(ROI_trung_bình)): Sắp xếp kết quả theo thứ tự giảm dần (desc) của ROI trung bình.
Ta được kết quả như sau:
TechCorp 5.007
Alpha Innovations 5.006
DataTech Solutions 5.006
Innovate Industries 5.002
NexGen Systems 4.99139913
Các công ty khác nên học hỏi chiến lược của TechCorp
roi_campaign <- dl %>%
group_by(Campaign_Type) %>%
summarise(ROI_trung_bình = mean(ROI))
roi_campaign## # A tibble: 5 × 2
## Campaign_Type ROI_trung_bình
## <fct> <dbl>
## 1 Display 5.01
## 2 Email 4.99
## 3 Influencer 5.01
## 4 Search 5.01
## 5 Social Media 4.99
Sử dụng pipeline (%>%) kết hợp với group_by() và summarise().
group_by(Campaign_Type): Chia data frame dl thành các nhóm nhỏ (ví dụ: nhóm “Influencer”, nhóm “Search”, v.v.).
summarise(ROI_trung_bình = mean(ROI)): Tính toán giá trị trung bình (mean) của cột ROI riêng biệt cho mỗi nhóm.
Xác định loại chiến dịch nào mang lại hiệu suất hoàn vốn cao nhất. Kết quả là:
Influencer & Search cho ROI cao nhất → mở rộng
Social Media & Email thấp hơn → tối ưu lại
## # A tibble: 6 × 2
## Channel_Used ROI_trung_bình
## <fct> <dbl>
## 1 Email 5.00
## 2 Facebook 5.02
## 3 Google Ads 5.00
## 4 Instagram 4.99
## 5 Website 5.01
## 6 YouTube 4.99
Tương tự như trên ta thu được kết quả như sau:
Facebook & Website hiệu quả nhất → tăng ngân sách
YouTube & Email kém hiệu quả → xem xét giảm đầu tư
cr_gender <- dl %>%
group_by(Gender) %>%
summarise(Conversion_Rate_trung_bình = mean(Conversion_Rate))
cr_gender## # A tibble: 3 × 2
## Gender Conversion_Rate_trung_bình
## <fct> <dbl>
## 1 All 0.0800
## 2 Female 0.0800
## 3 Male 0.0802
Vẫn như trên để ta có được kết quả sau:
Tỷ lệ chuyển đổi gần như bằng nhau → chiến dịch không cần phân biệt giới tính.
rev_segment <- dl %>%
group_by(Customer_Segment) %>%
summarise(Tổng_doanh_thu = sum(Revenue)) %>%
arrange(desc(Tổng_doanh_thu))
rev_segment## # A tibble: 5 × 2
## Customer_Segment Tổng_doanh_thu
## <fct> <dbl>
## 1 Foodies 2523856973.
## 2 Tech Enthusiasts 2509875192.
## 3 Outdoor Adventurers 2501349290.
## 4 Health & Wellness 2497220342.
## 5 Fashionistas 2485086878.
Sử dụng cấu trúc group_by() và summarise() của dplyr để tính toán tổng hợp trên từng nhóm.
group_by(Customer_Segment): Chia dữ liệu thành các nhóm dựa trên từng Phân khúc Khách hàng (ví dụ: “Foodies”, “Tech Enthusiasts”).
summarise(Tổng_doanh_thu = sum(Revenue)): Tính Tổng cột Revenue cho từng Phân khúc.
arrange(desc(Tổng_doanh_thu)): Sắp xếp kết quả giảm dần để tìm ra Phân khúc mang lại doanh thu cao nhất.
Từ những phân tích trên ta được kết quả:
Tập trung vào Foodies - đang mang về doanh thu cao nhất
Tech Enthusiasts - vị trí thứ 2 rất ổn định
5 segment có doanh thu rất cân bằng (chênh lêch chỉ ~1.5%)
→ Chiến lược đa dạng hóa đang hiệu quả
→ Không nên bỏ segment nào
## # A tibble: 12 × 2
## Month ROI_trung_bình
## <chr> <dbl>
## 1 April 4.99
## 2 August 5.00
## 3 December 5.00
## 4 February 5.01
## 5 January 5.01
## 6 July 4.98
## 7 June 4.99
## 8 March 4.98
## 9 May 5.02
## 10 November 5.00
## 11 October 5.02
## 12 September 5.03
Vẫn sử dụng group_by() và summarise().
group_by(Month): Nhóm các quan sát dựa trên biến Month (biến đã được tạo ra từ trước).
summarise(ROI_trung_bình = mean(ROI)): Tính ROI trung bình cho từng tháng trong bộ dữ liệu.
cor_matrix <- cor(dl[c("ROI", "Conversion_Rate", "Acquisition_Cost", "Clicks", "Impressions")])
round(cor_matrix, 3)## ROI Conversion_Rate Acquisition_Cost Clicks Impressions
## ROI 1.000 -0.001 0.005 -0.002 0.002
## Conversion_Rate -0.001 1.000 0.001 0.000 -0.003
## Acquisition_Cost 0.005 0.001 1.000 0.000 0.000
## Clicks -0.002 0.000 0.000 1.000 0.000
## Impressions 0.002 -0.003 0.000 0.000 1.000
dl[c(…)]: Trích xuất một data frame con chỉ chứa 5 biến số (vì hàm cor() chỉ hoạt động trên dữ liệu số).
cor(…): Tính toán hệ số tương quan tuyến tính (thường là Pearson) giữa mọi cặp biến số trong data frame con đó, tạo ra một ma trận tương quan (Correlation Matrix).
round(…, 3): Làm tròn kết quả ma trận tương quan đến 3 chữ số thập phân để dễ đọc.
Ta đọc được kết quả: Các biến không tương quan mạnh → không có yếu tố nào quyết định duy nhất đến ROI.
duration_stats <- dl %>%
group_by(Duration) %>%
summarise(ROI_trung_bình = mean(ROI))
duration_stats## # A tibble: 4 × 2
## Duration ROI_trung_bình
## <dbl> <dbl>
## 1 15 5.00
## 2 30 5.01
## 3 45 5.00
## 4 60 5.01
Sử dụng hàm list() để gán các vector (danh_sach_bien_so, danh_sach_bien_chu) vào một cột (Danh_sách) của data frame.
Kết quả: Cột Danh_sách trở thành một List-Column (cột danh sách). Thời gian giữa các chiến dịch không chênh lệch quá nhiều tuy nhiên vẫn nên ưu tiên các chiến dịch 30 ngày.
location_stats <- dl %>%
group_by(Location) %>%
summarise(ROI_trung_bình = mean(ROI))
location_stats## # A tibble: 5 × 2
## Location ROI_trung_bình
## <fct> <dbl>
## 1 Chicago 5.00
## 2 Houston 5.01
## 3 Los Angeles 5.01
## 4 Miami 5.01
## 5 New York 4.98
Sử dụng cấu trúc group_by() và summarise() của dplyr.
Mục đích: Tính ROI trung bình cho từng vị trí địa lý để chọn ra nơi tốt nhất.
Nên ưu tiên Miami, Los Angeles đây là 2 địa điểm trọng yếu.
top_roi <- dl %>%
arrange(desc(ROI)) %>%
head(5) %>%
select(Company, Campaign_Type, Channel_Used, ROI)
top_roi## Company Campaign_Type Channel_Used ROI
## 1 NexGen Systems Display Website 8
## 2 Innovate Industries Influencer Email 8
## 3 NexGen Systems Search Email 8
## 4 Alpha Innovations Display Instagram 8
## 5 TechCorp Social Media Email 8
Chuỗi ba hàm dplyr để trích xuất dữ liệu:
arrange(desc(ROI)): Sắp xếp toàn bộ data frame dl theo cột ROI theo thứ tự giảm dần (desc).
head(5): Lấy 5 dòng đầu tiên (tương đương 5 chiến dịch có ROI cao nhất).
select(…): Chỉ giữ lại các cột cần thiết (Company, Campaign_Type, v.v.) cho báo cáo.
Kết quả trả về cho thấy % chiến dịch có ROI cao nhất đếu bằng 8.
cost_tier_stats <- dl %>%
group_by(Cost_Tier) %>%
summarise(ROI_trung_bình = mean(ROI))
cost_tier_stats## # A tibble: 3 × 2
## Cost_Tier ROI_trung_bình
## <fct> <dbl>
## 1 Low 4.99
## 2 Medium 5.00
## 3 High 5.01
Sử dụng group_by() và summarise() để đánh giá mối quan hệ giữa mức chi phí và ROI trung bình tương ứng.
Từ kết quả trả về ta thấy được sự chênh lệch giữa các loại là rất thấp.
roi_tier_stats <- dl %>%
group_by(ROI_Tier) %>%
summarise(Số_lượng = n(), Tỷ_lệ = n()/nrow(dl)*100)
roi_tier_stats## # A tibble: 3 × 3
## ROI_Tier Số_lượng Tỷ_lệ
## <fct> <int> <dbl>
## 1 Low 66822 33.4
## 2 Medium 66438 33.2
## 3 High 66740 33.4
n(): Đếm số lượng dòng trong mỗi nhóm (Số_lượng).
n()/nrow(dl)*100: Tính toán tỷ lệ phần trăm của mỗi nhóm so với tổng số dòng.
Phân phối ROI đồng đều: 33% mỗi mức (Low/Medium/High)
engagement_stats <- dl %>%
group_by(Channel_Used) %>%
summarise(Engagement_trung_bình = mean(Engagement_Score))
engagement_stats## # A tibble: 6 × 2
## Channel_Used Engagement_trung_bình
## <fct> <dbl>
## 1 Email 5.49
## 2 Facebook 5.50
## 3 Google Ads 5.49
## 4 Instagram 5.49
## 5 Website 5.51
## 6 YouTube 5.48
Đoạn code là phân tích hiệu suất theo kênh. Chia dữ liệu thành các nhóm dựa trên kênh (Channel_Used), sau đó tính giá trị trung bình (mean) của chỉ số hiệu suất (Engagement_Score hoặc CTR) cho từng kênh.
mean(Engagement_Score) / mean(CTR). Tính chỉ số hiệu suất Chính. Tính trung bình của điểm tương tác và tỷ lệ nhấp, cho phép bạn so sánh hiệu quả tương tác và thu hút click của các kênh.
Từ kết quả, ta thấy website là channel được khách yêu thích nhất.
## # A tibble: 6 × 2
## Channel_Used CTR_trung_bình
## <fct> <dbl>
## 1 Email 0.141
## 2 Facebook 0.140
## 3 Google Ads 0.139
## 4 Instagram 0.140
## 5 Website 0.141
## 6 YouTube 0.141
Cũng như code ở trên thống kê từ các kênh như sau:
YouTube cao nhất (14.12%)
Website (14.10%)
Google Ads thấp nhất (13.92%)
variance_stats <- dl %>%
summarise(
Phương_sai_ROI = var(ROI),
Độ_lệch_chuẩn_ROI = sd(ROI)
)
variance_stats## Phương_sai_ROI Độ_lệch_chuẩn_ROI
## 1 3.00845 1.734488
mean(Engagement_Score) / mean(CTR) Tính Chỉ số Hiệu suất Chính. Tính trung bình của Điểm tương tác và Tỷ lệ nhấp, cho phép bạn so sánh hiệu quả tương tác và thu hút click của các kênh.
roi_quantiles <- data.frame(
Phân_vị = c("Q1", "Q2 (Trung vị)", "Q3"),
Giá_trị = quantile(dl$ROI, c(0.25, 0.5, 0.75))
)
roi_quantiles## Phân_vị Giá_trị
## 25% Q1 3.50
## 50% Q2 (Trung vị) 5.01
## 75% Q3 6.51
dl %>% summarise(…),Tính toán thống kê toàn bộ. Áp dụng trực tiếp lên cột ROI của toàn bộ data frame.
var(ROI),Tính Phương sai (Variance). Đo lường mức độ phân tán của các giá trị ROI so với giá trị trung bình của chúng.
sd(ROI),“Tính Độ lệch chuẩn (Standard Deviation). Đây là căn bậc hai của phương sai; nó cho biết trung bình một giá trị ROI lệch khỏi giá trị trung bình bao nhiêu, sử dụng cùng đơn vị với ROI.”
Độ lệch chuẩn thấp cho thấy ROI ổn định và dự đoán được, trong khi độ lệch chuẩn cao cho thấy rủi ro và sự biến động lớn.”
success_stats <- data.frame(
Ngưỡng_ROI = "> 5",
Số_chiến_dịch = sum(dl$ROI > 5),
Tỷ_lệ = mean(dl$ROI > 5) * 100
)
success_stats## Ngưỡng_ROI Số_chiến_dịch Tỷ_lệ
## 1 > 5 100056 50.028
dl$ROI > 5: Tạo ra một vector logic (TRUE/FALSE) cho toàn bộ cột ROI.sum(…): Đếm số lần TRUE (tổng số chiến dịch có ROI \(> 5\)).mean(…): Tính tỷ lệ số lần TRUE so với tổng số quan sát.Mục đích là định lượng tỷ lệ thành công dựa trên một tiêu chí kinh doanh cụ thể (ngưỡng ROI = 5).
Tỉ lệ thành công chỉ là trên 50% cho thấy các chiến dịch vẫn chưa hiệu quả
performance_stats <- dl %>%
summarise(
Điểm_trung_bình = mean(Performance_Score),
Điểm_trung_vị = median(Performance_Score)
)
performance_stats## Điểm_trung_bình Điểm_trung_vị
## 1 0.000000000000001052607 0.00286103
Performance_Score: Đây là biến tổng hợp (Feature Engineered) tạo ra bằng cách cộng các điểm Z-Score (scale(ROI) + scale(Conversion_Rate)).
mean(…) và median(…): Tính giá trị trung bình và trung vị của điểm tổng hợp này.
final_insights <- data.frame(
Chỉ_số = c("ROI Trung bình", "Conversion Rate TB", "Tổng Doanh thu", "Tỷ lệ thành công"),
Giá_trị = c(
round(mean(dl$ROI), 2),
round(mean(dl$Conversion_Rate), 4),
paste0(round(sum(dl$Revenue)/1e6, 1), "M"),
paste0(round(mean(dl$ROI > 5) * 100, 1), "%")
)
)
final_insights## Chỉ_số Giá_trị
## 1 ROI Trung bình 5
## 2 Conversion Rate TB 0.0801
## 3 Tổng Doanh thu 12517.4M
## 4 Tỷ lệ thành công 50%
# 1. Phân phối ROI
p1 <- ggplot(dl, aes(x = ROI)) +
geom_histogram(aes(y = after_stat(density)), fill = "lightblue", bins = 30, alpha = 0.7) +
geom_density(color = "darkblue", linewidth = 1) +
geom_vline(aes(xintercept = mean(ROI)), color = "red", linetype = "dashed", linewidth = 1) +
labs(title = "PHÂN PHỐI ROI", x = "ROI", y = "Mật độ") +
theme_minimal()
# 2. Phân phối Revenue
p2 <- ggplot(dl, aes(x = Revenue)) +
geom_histogram(aes(y = after_stat(density)), fill = "lightgreen", bins = 30, alpha = 0.7) +
geom_density(color = "darkgreen", linewidth = 1) +
geom_vline(aes(xintercept = mean(Revenue)), color = "red", linetype = "dashed", linewidth = 1) +
labs(title = "PHÂN PHỐI DOANH THU", x = "Revenue", y = "Mật độ") +
theme_minimal()
# 3. Xu hướng ROI theo tháng
p3 <- dl %>%
mutate(Month = paste0("T", month(Date))) %>% # Tháng 1 → T1, Tháng 2 → T2, ...
group_by(Month) %>%
summarise(ROI_trung_bình = mean(ROI)) %>%
ggplot(aes(x = factor(Month, levels = paste0("T", 1:12)), y = ROI_trung_bình, group = 1)) +
geom_line(color = "darkgreen", linewidth = 1) +
geom_point(color = "red", size = 2) +
geom_hline(yintercept = mean(dl$ROI), linetype = "dashed", color = "blue") +
labs(title = "XU HƯỚNG ROI THEO THÁNG", x = "Tháng", y = "ROI trung bình") +
theme_minimal()
# 4. ROI theo Cost Tier
p4 <- ggplot(dl, aes(x = Cost_Tier, y = ROI, fill = Cost_Tier)) +
geom_boxplot(alpha = 0.7) +
stat_summary(fun = mean, geom = "point", shape = 18, size = 3, color = "black") +
labs(title = "ROI THEO MỨC CHI PHÍ", x = "Mức chi phí", y = "ROI") +
theme_minimal() +
theme(legend.position = "none")
# Kết hợp 4 đồ thị
(p1 + p2) / (p3 + p4) +
plot_annotation(title = "NHÓM ĐỒ THỊ HIỆU SUẤT TÀI CHÍNH",
theme = theme(plot.title = element_text(face = "bold", size = 16, hjust = 0.5)))
- Xử lí lại các vấn đề:
Bắt đầu bằng việc làm sạch dữ liệu bằng các kỹ thuật cần thiết như: loại bỏ ký tự không phải số ($, days) bằng gsub() và chuyển đổi sang kiểu numeric; chuẩn hóa ngày tháng bằng as.Date().
Tạo ra các biến mới quan trọng cho phân tích kinh doanh: Revenue và CTR (tỷ lệ nhấp).
Thực hiện Chuẩn hóa Z-Score (scale()) và cộng hai chỉ số hiệu suất để tạo ra Performance_Score; Phân loại biến số liên tục (ROI, Acquisition_Cost) thành các bậc rời rạc (Low, Medium, High) bằng hàm cut() (Binning).
Cuối cùng, sử dụng lapply() và as.factor() để chuyển đổi các biến phân loại sang kiểu Factor, tối ưu hóa cho mô hình hóa.
Tận dụng tối đa cấu trúc pipeline (%>%), group_by() và summarise() của dplyr để thực hiện các phân tích phân khúc và tổng hợp:
Xác định Top Performers (Công ty, Kênh, Loại Chiến dịch) bằng cách tính ROI trung bình theo từng nhóm.
Sử dụng arrange(desc(…)) %>% head(5) để trích xuất các chiến dịch hoặc phân khúc có hiệu suất cao nhất.
Sử dụng các hàm thống kê cơ bản như cor() (tương quan), var() (phương sai), sd() (độ lệch chuẩn), và quantile() (phân vị) để hiểu rõ hơn về mối quan hệ và sự biến động của ROI.
Sử dụng logic sum(dl\(ROI > 5) và mean(dl\)ROI > 5) để định lượng tỷ lệ thành công dựa trên ngưỡng kinh doanh.
Sử dụng thư viện ggplot2 để tạo ra các biểu đồ chuyên nghiệp, bao gồm:
Histogram và Density Plot (geom_histogram, geom_density) để phân tích hình dạng phân phối của ROI và Doanh thu.
Biểu đồ đường (geom_line) kết hợp với group_by() và mutate() để trực quan hóa Xu hướng ROI theo thời gian (tháng).
Box Plot (geom_boxplot) kết hợp với stat_summary() để so sánh phân phối ROI giữa các nhóm (ví dụ: Cost_Tier), làm nổi bật cả Trung vị và Trung bình của từng nhóm.
Sử dụng thư viện patchwork (/ và +) để sắp xếp và kết hợp các biểu đồ một cách khoa học.
Phân phối ROI cho thấy một đặc điểm đáng chú ý của danh mục đầu tư marketing. ROI tập trung chủ yếu quanh mức trung bình 5.0 với phân phối gần như chuẩn, phản ánh tính ổn định và khả năng dự báo cao trong hiệu suất các chiến dịch. Sự phân bố này chỉ ra rằng doanh nghiệp đã xây dựng được một mô hình đầu tư marketing khá đồng đều và kiểm soát được rủi ro, với phần lớn các chiến dịch đều đạt hiệu suất ở mức trung bình khá, ít có các trường hợp ngoại lệ quá thấp hoặc quá cao.
Xu hướng ROI theo tháng càng khẳng định tính ổn định này khi biểu đồ cho thấy ROI trung bình hầu như không có biến động đáng kể qua các tháng, luôn duy trì quanh mức 5.0 với sai số rất nhỏ. Điều này cho thấy hiệu suất đầu tư marketing của doanh nghiệp ít chịu ảnh hưởng của yếu tố mùa vụ, đồng thời phản ánh năng lực quản lý và tối ưu chiến dịch xuyên suốt các tháng trong năm đều rất ổn định.
Tuy nhiên, insight kinh tế quan trọng nhất đến từ mối quan hệ giữa mức chi phí và hiệu suất ROI. Biểu đồ ROI theo mức chi phí thể hiện rõ quy luật “tiền nào của nấy” trong đầu tư marketing: các chiến dịch với mức chi phí cao đem lại ROI cao nhất, tiếp theo là mức trung bình và thấp nhất là những chiến dịch có ngân sách thấp. Điều này cho thấy việc đầu tư mạnh tay vào các chiến dịch chất lượng cao, có quy mô lớn thực sự mang lại hiệu quả vượt trội về mặt tài chính.
Nhìn tổng thể, dữ liệu này ủng hộ cho chiến lược đầu tư marketing tập trung và mạnh mẽ thay vì dàn trải ngân sách quá mỏng. Việc phân bổ ngân sách lớn hơn cho các chiến dịch chất lượng cao, được đầu tư bài bản sẽ mang lại hiệu quả kinh tế tốt hơn so với việc chia nhỏ ngân sách thành nhiều chiến dịch quy mô nhỏ. Đây là bài học kinh tế quan trọng cho việc hoạch định ngân sách marketing trong tương lai.
# Tổng hợp dữ liệu cần thiết cho biểu đồ cột (p6, p7, p8) ---
channel_stats <- dl %>%
group_by(Channel_Used) %>%
summarise(
Tổng_doanh_thu = sum(Revenue),
CTR_trung_bình = mean(CTR),
Engagement_trung_bình = mean(Engagement_Score)
)
# 5. ROI theo Channel
p5 <- ggplot(dl, aes(x = ROI, y = Channel_Used, fill = Channel_Used)) +
geom_boxplot(alpha = 0.7) +
labs(title = "ROI", x = "ROI", y = "") +
theme_minimal() +
theme(legend.position = "none")
channel_stats <- dl %>%
group_by(Channel_Used) %>%
summarise(
Tổng_doanh_thu = sum(Revenue),
CTR_trung_bình = mean(CTR),
Engagement_trung_bình = mean(Engagement_Score))
# 6. Revenue theo Channel
p6 <- channel_stats %>% # Dùng data frame đã tổng hợp
ggplot(aes(x = reorder(Channel_Used, Tổng_doanh_thu), y = Tổng_doanh_thu, fill = Channel_Used)) +
geom_col(alpha = 0.8) +
scale_y_continuous(expand = expansion(mult = c(0, 0.40)),
labels = scales::label_number(scale = 1e6, suffix = "M")) +
geom_text(aes(label = scales::dollar(Tổng_doanh_thu/1e6, suffix = "USD")),
vjust = -0.3, size = 2.5) +
coord_flip() +
labs(title = "DOANH THU", x = "", y = "Tổng doanh thu (USD)") +
theme_minimal() +
theme(legend.position = "none") +
theme(axis.text.x = element_blank())
# 7. CTR theo Channel
p7 <- channel_stats %>% # Dùng data frame đã tổng hợp
ggplot(aes(x = reorder(Channel_Used, CTR_trung_bình), y = CTR_trung_bình, fill = Channel_Used)) +
geom_col(alpha = 0.8) +
scale_y_continuous(expand = expansion(mult = c(0, 0.35))) +
geom_text(aes(label = round(CTR_trung_bình * 100, 2)),
vjust = -0.3, size = 2.5) +
coord_flip() +
labs(title = "CTR TRUNG BÌNH (%)", x = "", y = "CTR trung bình") +
theme_minimal() +
theme(legend.position = "none")
# 8. Engagement theo Channel
p8 <- channel_stats %>% # Dùng data frame đã tổng hợp
ggplot(aes(x = reorder(Channel_Used, Engagement_trung_bình),
y = Engagement_trung_bình, fill = Channel_Used)) +
geom_col(alpha = 0.8) +
scale_y_continuous(expand = expansion(mult = c(0, 0.35))) +
geom_text(aes(label = round(Engagement_trung_bình, 2)),
vjust = -0.3, size = 2.5) +
coord_flip() +
labs(title = "ENGAGEMENT", x = "", y = "Engagement trung bình") +
theme_minimal() +
theme(legend.position = "none")
# Kết hợp 4 đồ thị bằng patchwork
(p5 + p6) / (p7 + p8) +
plot_annotation(title = "NHÓM ĐỒ THỊ PHÂN TÍCH KÊNH MARKETING",
theme = theme(plot.title = element_text(face = "bold", size = 16, hjust = 0.5)))
Tạo một Data Frame Trung gian (channel_stats) bằng cách sử dụng
group_by() và summarise() để tính toán đồng thời ba chỉ số
(Tổng_doanh_thu, CTR_trung_bình, Engagement_trung_bình) cho mỗi
kênh.
Sử dụng kết hợp Violin Plot và Box Plot.
Violin Plot (geom_violin): Cho thấy mật độ phân phối (hình dạng) của ROI trong mỗi kênh, hữu ích hơn Box Plot khi muốn xem sự tập trung của dữ liệu.
Box Plot (geom_boxplot): Làm nổi bật Trung vị (Median), Tứ phân vị (Quartiles) và các giá trị ngoại lai (Outliers).
reorder(Channel_Used, …): Sắp xếp các kênh trên trục Y theo thứ tự giá trị tăng dần hoặc giảm dần của chỉ số, giúp việc so sánh Top/Low Performer dễ dàng hơn.
coord_flip()-Chuyển đổi trục: Biến biểu đồ cột dọc thành ngang. Điều này là bắt buộc khi các nhãn kênh (Email, Facebook,…) dài, giúp tránh bị chồng chéo.
geom_text(…, vjust = -0.3, size = 2.5)-Đặt nhãn giá trị: Đặt số liệu chính xác lên cột. Tham số vjust = -0.3 dịch chuyển nhãn ra khỏi đầu cột (sau khi coord_flip), giải quyết vấn đề chồng chéo nhãn cuối cùng.
scales::dollar(…) / scales::label_number(…)-Định dạng số: Chuyển đổi các số lớn (Tổng_doanh_thu) thành định dạng tiền tệ hoặc số có hậu tố (M), làm cho biểu đồ dễ đọc hơn.
Sử dụng thư viện patchwork để bố cục 4 biểu đồ thành một hình ảnh tổng hợp: p5 và p6 nằm trên hàng trên, p7 và p8 nằm trên hàng dưới.
Dựa trên biểu đồ phân tích hiệu suất các kênh marketing, có thể đưa ra nhận định toàn diện về hiệu quả hoạt động của từng kênh trong việc đóng góp vào mục tiêu kinh doanh. Phân tích được thực hiện dựa trên ba chỉ số quan trọng: ROI đo lường hiệu quả tài chính, CTR đánh giá khả năng thu hút tương tác, và doanh thu phản ánh khả năng tạo ra thu nhập thực tế.
Xét về góc độ hiệu quả tài chính (ROI), Facebook và Website thể hiện vị trí dẫn đầu rõ rệt, chứng tỏ đây là hai kênh mang lại giá trị đầu tư tốt nhất. Các kênh này không chỉ thu hút được sự quan tâm của khách hàng mà còn chuyển đổi thành hiệu quả kinh tế thực tế. Ở nhóm giữa, Google Ads duy trì được mức ROI tương đối ổn định, trong khi Email, Instagram và YouTube cho thấy hiệu suất tài chính thấp hơn đáng kể, điều này đặt ra câu hỏi về tính hiệu quả trong việc phân bổ ngân sách cho các kênh này.
Khi phân tích khả năng thu hút tương tác thông qua chỉ số CTR, một bức tranh khác xuất hiện khi YouTube vượt trội với CTR cao nhất, tiếp theo là Website và Email. Điều này cho thấy YouTube có sức hút lớn trong việc thu hút sự chú ý và tương tác của người dùng, tuy nhiên khả năng chuyển đổi những tương tác này thành giá trị kinh tế lại chưa tương xứng. Facebook và Instagram thể hiện mức CTR ở tầm trung, trong khi Google Ads có CTR thấp nhất trong tất cả các kênh.
Về khả năng tạo ra doanh thu, Email khẳng định vị thế là kênh bán hàng chủ lực khi dẫn đầu về doanh thu, minh chứng cho hiệu quả của việc tiếp cận khách hàng trực tiếp. Google Ads và Website theo sát ở vị trí thứ hai và ba, cho thấy đây là những kênh quan trọng trong việc tạo ra nguồn thu. Đáng chú ý, YouTube, Instagram và Facebook mặc dù có những ưu điểm nhất định về tương tác hoặc ROI nhưng lại cho doanh thu thấp hơn hẳn.
Tổng hợp cả ba chỉ số, Website nổi lên như kênh marketing toàn diện nhất khi có ROI cao, CTR tốt và doanh thu ổn định. Facebook cũng thể hiện sự vượt trội về ROI mặc dù doanh thu chưa thực sự nổi bật. YouTube cho thấy tiềm năng lớn về mặt thu hút tương tác nhưng cần tối ưu hóa để chuyển đổi thành hiệu quả tài chính. Email vẫn giữ vị trí quan trọng trong việc tạo doanh thu dù hiệu quả đầu tư không thực sự nổi bật. Instagram và Google Ads cần được xem xét lại về chiến lược triển khai để cải thiện hiệu quả tổng thể.
Dựa trên phân tích này, chiến lược tối ưu nên tập trung ngân sách mạnh vào Website và Facebook để tận dụng hiệu quả tài chính cao, đồng thời cần có giải pháp cải thiện khả năng chuyển đổi của YouTube để biến lợi thế về CTR thành giá trị kinh tế thực tế. Đối với Email, cần duy trì như kênh bán hàng chủ lực nhưng cần tối ưu chi phí để nâng cao ROI. Instagram và Google Ads cần được đánh giá lại toàn diện về chiến lược triển khai và hiệu quả sử dụng ngân sách.
campaign_stats <- dl %>%
group_by(Campaign_Type) %>%
summarise(Tổng_doanh_thu = sum(Revenue))
duration_stats <- dl %>%
group_by(Duration) %>%
summarise(ROI_trung_bình = mean(ROI))
# 9. Revenue theo Campaign Type
p9 <- campaign_stats %>%
ggplot(aes(x = reorder(Campaign_Type, Tổng_doanh_thu), y = Tổng_doanh_thu, fill = Campaign_Type)) +
geom_col(alpha = 0.8) +
scale_y_continuous(expand = expansion(mult = c(0, 0.30)),
labels = scales::label_number(scale = 1e6, suffix = "USD")) +
geom_text(aes(label = scales::dollar(Tổng_doanh_thu/1e6, suffix = "USD")),
vjust = -0.3,
size = 2.5) +
coord_flip() +
labs(title = "DOANH THU", x = "", y = "Tổng doanh thu (USD)") +
theme_minimal() +
theme(legend.position = "none")+
theme(axis.text.x = element_blank())
# 10. ROI theo Campaign Type
p10 <- ggplot(dl, aes(x = Campaign_Type, y = ROI, fill = Campaign_Type)) +
geom_boxplot(alpha = 0.7) +
stat_summary(fun = mean, geom = "point", shape = 18, size = 3, color = "black") +
labs(title = "ROI", x = "Loại chiến dịch", y = "ROI") +
theme_minimal() +
theme(legend.position = "none")
# 11. Phân bố Duration
p11 <- ggplot(dl, aes(x = factor(Duration), fill = factor(Duration))) +
geom_bar(alpha = 0.7) +
labs(title = "PHÂN BỐ", x = "Thời lượng (ngày)", y = "Số lượng") +
theme_minimal() +
theme(legend.position = "none")
# 12. ROI theo Duration
p12 <- duration_stats %>%
ggplot(aes(x = factor(Duration), y = ROI_trung_bình, fill = factor(Duration))) +
geom_col(alpha = 0.8) +
scale_y_continuous(expand = expansion(mult = c(0, 0.15))) +
geom_text(aes(label = round(ROI_trung_bình, 2)), vjust = -0.5, size = 3) +
labs(title = "ROI", x = "Thời lượng (ngày)", y = "ROI trung bình") +
theme_minimal() +
theme(legend.position = "none")
# Kết hợp 4 đồ thị
(p9 + p10) / (p11 + p12) +
plot_annotation(title = "NHÓM ĐỒ THỊ PHÂN TÍCH CHIẾN DỊCH",
theme = theme(plot.title = element_text(face = "bold", size = 16, hjust = 0.5)))
reorder(Channel_Used, …) (Sắp xếp Dữ liệu): Đây là một hàm tiện ích cơ
bản nhưng cực kỳ quan trọng. Nó xác định thứ tự hiển thị của các nhóm
(Channel_Used) trên trục phân loại (trục Y sau khi coord_flip).Giá trị:
Thay vì để các kênh sắp xếp theo thứ tự bảng chữ cái (mặc định), việc
sắp xếp theo giá trị của chỉ số (ví dụ: Tổng_doanh_thu) giúp người đọc
dễ dàng so sánh Top Performers và Low Performers chỉ bằng một cái nhìn,
tăng hiệu quả báo cáo
coord_flip() (Chuyển đổi Tọa độ): Hàm này hoán đổi trục X và trục Y. Nó chuyển biểu đồ cột dọc truyền thống thành biểu đồ cột ngang.Giá trị: Bắt buộc phải sử dụng khi các nhãn phân loại (như tên kênh Email, Facebook, Google Ads…) quá dài. Nếu để cột dọc, các nhãn này sẽ bị chồng chéo hoặc phải xoay, làm giảm khả năng đọc. Biểu đồ cột ngang là giải pháp lý tưởng cho việc hiển thị phân loại dữ liệu.
scale_y_continuous(expand = expansion(mult = c(0, 0.40))) (Tối ưu hóa Hiển thị Trục)Chức năng: Điều chỉnh giới hạn của trục liên tục (trục giá trị, là trục Y sau khi coord_flip).Giá trị: Đây là kỹ thuật khắc phục lỗi hiển thị. Tham số mult = c(0, 0.40) yêu cầu R mở rộng giới hạn trục thêm \(40\%\) không gian ở phía trên. Không gian bổ sung này là nơi để đặt nhãn giá trị (geom_text) mà không bị cắt hoặc chạm mép biểu đồ.
geom_text(…, vjust = -0.3, size = 2.5) (Đặt Nhãn Giá trị): Đặt các giá trị thống kê chính xác lên đỉnh của mỗi cột.Giá trị: Tham số vjust = -0.3 đóng vai trò quyết định sau khi coord_flip(). Nó dịch chuyển nhãn theo chiều dọc của cột nhưng ra xa khỏi thanh cột, kết hợp với expansion ở mục 3 để ngăn chặn hoàn toàn lỗi chồng chéo hoặc nhãn bị cắt.
scales::dollar(…) / scales::label_number(…) (Định dạng Số liệu)Chức năng: Các hàm từ thư viện scales được sử dụng để định dạng số liệu thô thành chuỗi dễ đọc (ví dụ: \(2,100,000,000\) thành $2.10B hoặc $2.10M).Giá trị: Cải thiện tính chuyên nghiệp và khả năng đọc của biểu đồ, đặc biệt với các số tiền hoặc số liệu lớn.
Dựa trên biểu đồ phân tích hiệu suất các loại chiến dịch marketing, có thể đưa ra đánh giá toàn diện về hiệu quả của từng loại hình chiến dịch dựa trên khả năng tạo ra doanh thu. Phân tích này cung cấp cái nhìn sâu sắc về việc phân bổ ngân sách marketing tối ưu cho các loại hình chiến dịch khác nhau.
Theo thứ tự hiệu quả về mặt doanh thu, chiến dịch Influencer (tiếp thị thông qua người có ảnh hưởng) dẫn đầu rõ rệt, chứng tỏ đây là loại hình chiến dịch mang lại hiệu quả kinh doanh cao nhất. Vị trí này phản ánh xu hướng marketing hiện đại khi người tiêu dùng ngày càng tin tưởng vào các đề xuất từ những người có ảnh hưởng hơn là các hình thức quảng cáo truyền thống. Sự thành công của chiến dịch Influencer cho thấy khả năng tiếp cận đúng đối tượng mục tiêu và tạo ra sự tin tưởng mạnh mẽ đối với khách hàng tiềm năng.
Ở vị trí thứ hai là chiến dịch Search (tìm kiếm), thể hiện hiệu quả bền vững của việc tiếp cận khách hàng thông qua các công cụ tìm kiếm. Điều này cho thấy nhu cầu tìm kiếm chủ động từ phía người dùng vẫn là kênh mang lại giá trị kinh doanh cao, khi khách hàng đã có sẵn nhu cầu và tìm kiếm giải pháp. Chiến dịch Search thường đi kèm với ý định mua hàng cao, dẫn đến tỷ lệ chuyển đổi tốt và doanh thu ổn định.
Chiến dịch Display (quảng cáo hiển thị) chiếm vị trí thứ ba, cho thấy hiệu quả của việc xây dựng nhận thức thương hiệu và tiếp cận khách hàng ở quy mô lớn. Mặc dù không mang lại doanh thu cao như hai loại hình trên, Display vẫn duy trì được vị trí quan trọng trong việc xây dựng sự hiện diện thương hiệu và hỗ trợ các kênh marketing khác.
Đáng chú ý, chiến dịch Email - từng là công cụ marketing chủ lực - nay chỉ xếp ở vị trí thứ tư. Điều này phản ánh sự thay đổi trong thói quen tiếp nhận thông tin của người tiêu dùng.
customer_stats <- dl %>%
group_by(Customer_Segment) %>%
summarise(
Tổng_doanh_thu = sum(Revenue),
Engagement_trung_bình = mean(Engagement_Score))
gender_stats <- dl %>%
group_by(Gender) %>%
summarise(Conversion_Rate_trung_bình = mean(Conversion_Rate))
# 13. ROI theo Customer Segment
p13 <- ggplot(dl, aes(x = Customer_Segment, y = ROI, fill = Customer_Segment)) +
geom_boxplot(alpha = 0.7) +
coord_flip() +
labs(title = "ROI THEO KHÁCH HÀNG", x = "", y = "ROI") +
theme_minimal() +
theme(legend.position = "none")
# 14. Revenue theo Customer Segment
p14 <- customer_stats %>%
ggplot(aes(x = reorder(Customer_Segment, Tổng_doanh_thu), y = Tổng_doanh_thu, fill = Customer_Segment)) +
geom_col(alpha = 0.8) +
scale_y_continuous(expand = expansion(mult = c(0, 0.30)),
labels = scales::label_number(scale = 1e6, suffix = "USD")) +
geom_text(aes(label = scales::dollar(Tổng_doanh_thu/1e6, suffix = "USD")),
vjust = -0.3, size = 2.5) +
coord_flip() +
labs(title = "DOANH THU", x = "", y = "Tổng doanh thu (USD)") +
theme_minimal() +
theme(legend.position = "none")+
theme(axis.text.x = element_blank())
# 15. Conversion Rate theo Gender
p15 <- gender_stats %>%
ggplot(aes(x = Gender, y = Conversion_Rate_trung_bình, fill = Gender)) +
geom_col(alpha = 0.8) +
scale_y_continuous(expand = expansion(mult = c(0, 0.15))) +
geom_text(aes(label = round(Conversion_Rate_trung_bình, 4)),
vjust = -0.5, size = 3) +
labs(title = "CR THEO GIỚI TÍNH", x = "Giới tính", y = "Conversion Rate trung bình") +
theme_minimal() +
theme(legend.position = "none")
# 16. Engagement theo Customer Segment
p16 <- customer_stats %>%
ggplot(aes(x = reorder(Customer_Segment, Engagement_trung_bình), y = Engagement_trung_bình, fill = Customer_Segment)) +
geom_col(alpha = 0.8) +
coord_flip() +
scale_y_continuous(expand = expansion(mult = c(0, 0.15))) +
geom_text(aes(label = round(Engagement_trung_bình, 2)),
hjust = -0.5, # Dịch nhãn ra ngoài cột ngang
size = 3) +
labs(title = "ENGAGEMENT", x = "", y = "Engagement trung bình") +
theme_minimal() +
theme(legend.position = "none")+
theme(axis.text.x = element_blank())
# Kết hợp 4 đồ thị
(p13 + p14) / (p15 + p16) +
plot_annotation(title = "NHÓM ĐỒ THỊ PHÂN TÍCH KHÁCH HÀNG",
theme = theme(plot.title = element_text(face = "bold", size = 16, hjust = 0.5)))
- (ROI theo Customer Segment):
Sử dụng geom_boxplot kết hợp với coord_flip() (chuyển Box Plot thành ngang). Đây là cách tuyệt vời để so sánh phân phối ROI giữa các phân khúc một cách trực quan.
Sử dụng group_by/summarise và geom_col kết hợp coord_flip() và reorder() để hiển thị tổng doanh thu theo thứ tự.
Tương tự như p14, sử dụng cột dọc và reorder() để so sánh mức độ tương tác (Engagement) giữa các nhóm khách hàng.
Sử dụng geom_col để so sánh tỷ lệ chuyển đổi (Conversion_Rate) trung bình giữa các nhóm giới tính (All, Female, Male).
Phân tích ROI theo nhóm khách hàng cho thấy sự khác biệt đáng kể về hiệu quả đầu tư marketing giữa các phân khúc. Nhóm Tech Enthusiasts (những người đam mê công nghệ) thể hiện ROI cao nhất, điều này phản ánh khả năng sẵn sàng chi trả và độ trung thành của nhóm khách hàng này đối với các sản phẩm công nghệ. Tiếp theo là nhóm Outdoor Adventurers (những người yêu thích phiêu lưu ngoài trời) và Health & Wellness (sức khỏe và thể chất), cả hai đều cho thấy tiềm năng lớn trong việc mang lại lợi nhuận cho các chiến dịch marketing. Ngược lại, nhóm Foodies (người sành ăn) và Fashionistas (tín đồ thời trang) có ROI thấp hơn, cho thấy có thể các chiến dịch hướng đến nhóm này cần được tối ưu để cải thiện hiệu quả đầu tư.
Tuy nhiên, khi xem xét về tổng doanh thu, bức tranh lại hoàn toàn khác biệt. Nhóm Foodies dẫn đầu về doanh thu, chứng tỏ đây là phân khúc có quy mô thị trường lớn và khả năng chi tiêu mạnh mẽ. Tech Enthusiasts và Outdoor Adventurers theo sát ở vị trí thứ hai và ba, khẳng định tầm quan trọng của các nhóm khách hàng này trong cơ cấu doanh thu tổng thể. Health & Wellness và Fashionistas có doanh thu thấp hơn, nhưng vẫn đóng góp đáng kể vào tổng doanh thu.
Phân tích tỷ lệ chuyển đổi (Conversion Rate) theo giới tính cho thấy một kết quả thú vị: không có sự khác biệt đáng kể nào về tỷ lệ chuyển đổi giữa các nhóm giới tính. Cả ba nhóm “All” (tất cả), “Female” (nữ) và “Male” (nam) đều có tỷ lệ chuyển đổi tương đương nhau. Điều này cho thấy chiến lược marketing hiện tại đang tiếp cận hiệu quả với tất cả các nhóm giới tính, và không có nhóm nào thể hiện sự vượt trội rõ rệt về khả năng chuyển đổi. Tuy nhiên, điều này cũng gợi ý rằng có thể cần phân tích sâu hơn về giá trị đơn hàng trung bình hoặc tỷ lệ duy trì khách hàng theo giới tính để có cái nhìn toàn diện hơn.
Về chỉ số Engagement (mức độ tương tác), dữ liệu cho thấy sự phân bổ tương tác khá đồng đều trên thang điểm từ 1 đến 10, với xu hướng tập trung vào các mức điểm trung bình. Điều này cho thấy khách hàng có mức độ tương tác ổn định với thương hiệu, nhưng vẫn còn dư địa để cải thiện mức độ tương tác cao hơn. Các điểm engagement thấp có thể phản ánh những khách hàng mới hoặc những người ít tương tác, trong khi các điểm engagement cao thường đại diện cho những khách hàng trung thành hoặc những người đã có trải nghiệm tích cực với thương hiệu.
Tổng hợp các insights từ ba góc độ phân tích này, có thể thấy rằng mặc dù nhóm Foodies có ROI thấp hơn nhưng lại đóng góp doanh thu lớn nhất, điều này cho thấy đây là phân khúc cần được duy trì và tối ưu hóa để cải thiện hiệu quả đầu tư. Ngược lại, nhóm Tech Enthusiasts vừa có ROI cao vừa có doanh thu lớn, xứng đáng được ưu tiên đầu tư marketing. Việc không có sự khác biệt về tỷ lệ chuyển đổi theo giới tính cho phép doanh nghiệp tập trung vào các yếu tố khác trong segmentation thay vì tập trung quá nhiều vào giới tính. Cuối cùng, chỉ số engagement ổn định nhưng chưa cao cho thấy cơ hội trong việc phát triển các chiến lược tăng cường tương tác và xây dựng lòng trung thành khách hàng.
Dựa trên những phân tích này, chiến lược marketing nên ưu tiên phân bổ ngân sách cho nhóm Tech Enthusiasts và Foodies, đồng thời phát triển các chương trình tăng cường engagement cho tất cả các nhóm khách hàng. Việc cá nhân hóa trải nghiệm và cải thiện chất lượng dịch vụ có thể giúp nâng cao cả ROI và doanh thu từ tất cả các phân khúc khách hàng.
# 17. Tương quan ROI vs Conversion Rate
p17 <- ggplot(dl, aes(x = Conversion_Rate, y = ROI)) +
geom_point(alpha = 0.3, color = "blue") +
geom_smooth(method = "lm", color = "red", se = TRUE) +
geom_hline(yintercept = mean(dl$ROI), linetype = "dashed", color = "gray") +
geom_vline(xintercept = mean(dl$Conversion_Rate), linetype = "dashed", color = "gray") +
labs(title = "ROI VS CONVERSION RATE", x = "Conversion Rate", y = "ROI") +
theme_minimal()
# 18. Tương quan Clicks vs Impressions
p18 <- ggplot(dl, aes(x = Impressions, y = Clicks)) +
geom_point(alpha = 0.3, color = "brown") +
geom_smooth(method = "lm", color = "darkblue", se = TRUE) +
labs(title = "CLICKS VS IMPRESSIONS", x = "Impressions", y = "Clicks") +
theme_minimal()
# 19. Phân phối Engagement Score
p19 <- ggplot(dl, aes(x = Engagement_Score)) +
geom_histogram(fill = "purple", bins = 15, alpha = 0.7) +
geom_vline(aes(xintercept = mean(Engagement_Score)), color = "red", linetype = "dashed", linewidth = 1) +
labs(title = "PHÂN PHỐI ĐIỂM TƯƠNG TÁC", x = "Engagement Score", y = "Tần số") +
theme_minimal()
# 20. Phân bố ROI Tier
p20 <- ggplot(dl, aes(x = ROI_Tier, fill = ROI_Tier)) +
geom_bar(alpha = 0.7) +
# TĂNG expansion trục Y lên 30% (từ 15%) để đảm bảo nhãn không bị cắt
scale_y_continuous(expand = expansion(mult = c(0, 0.30))) +
# Đặt nhãn số lượng
geom_text(stat = 'count', aes(label = after_stat(count)), vjust = -0.5, size = 3) +
labs(title = "PHÂN BỐ THEO MỨC ROI", x = "Mức ROI", y = "Số lượng") +
theme_minimal() +
theme(legend.position = "none")
# Kết hợp 4 đồ thị
(p17 + p18) / (p19 + p20) +
plot_annotation(title = "NHÓM ĐỒ THỊ TƯƠNG QUAN VÀ TƯƠNG TÁC",
theme = theme(plot.title = element_text(face = "bold", size = 16, hjust = 0.5)))
- Phân tích Tương quan (p17, p18) geom_point(alpha = 0.3): Dùng Scatter
Plot để hiển thị mối quan hệ giữa hai biến, sử dụng alpha để giảm độ đậm
đặc của các điểm dữ liệu.
geom_smooth(method = “lm”, …): Thêm đường hồi quy tuyến tính (Linear Model - LM) để định lượng xu hướng. Vùng màu xám xung quanh đường thẳng (se = TRUE) là khoảng tin cậy (Confidence Interval), cho thấy mức độ chắc chắn của mối quan hệ.
geom_hline / geom_vline: Trong p17, thêm các đường tham chiếu ngang và dọc (yintercept và xintercept) tại giá trị trung bình, giúp dễ dàng xác định bốn góc phần tư của dữ liệu (Ví dụ: ROI cao, CR thấp).
Dùng geom_histogram để thể hiện tần suất.
Thêm geom_vline tại vị trí giá trị trung bình (mean), giúp người xem nhanh chóng xác định vị trí trung tâm của phân phối.
Dùng geom_bar(stat = ‘count’) để đếm số lượng các chiến dịch thuộc ba mức ROI (Low, Medium, High).
Dựa trên nhóm đồ thị phân tích tương quan và tương tác, có thể rút ra những insights quan trọng về mối quan hệ giữa các chỉ số hiệu suất marketing và phân phối của chúng.
Đồ thị tương quan giữa ROI và Conversion Rate cho thấy một phát hiện đáng chú ý: không có mối tương quan tuyến tính rõ rệt nào giữa hai chỉ số này. Các điểm dữ liệu phân tán rộng mà không hình thành một xu hướng cụ thể, chứng tỏ một Conversion Rate cao không đảm bảo ROI cao và ngược lại. Điều này cho thấy có những yếu tố khác ngoài tỷ lệ chuyển đổi ảnh hưởng đến hiệu quả tài chính của chiến dịch, như giá trị đơn hàng trung bình, chi phí acquisition, hay tỷ lệ giữ chân khách hàng. Các marketer cần nhìn nhận rằng việc tối ưu Conversion Rate chỉ là một phần của bài toán, và cần kết hợp với các chỉ số khác để đánh giá toàn diện hiệu quả.
Đồ thị tương quan giữa Clicks và Impressions thể hiện mối quan hệ tích cực và khá chặt chẽ giữa hai chỉ số này - khi số lượng impressions tăng thì clicks cũng có xu hướng tăng theo. Tuy nhiên, mật độ tập trung của các điểm dữ liệu cho thấy có một ngưỡng hiệu quả nhất định, vượt qua ngưỡng đó thì việc tăng thêm impressions không mang lại sự gia tăng tương xứng về clicks. Điều này gợi ý về quy luật giảm dần lợi ích trong việc mở rộng phạm vi tiếp cận, và nhấn mạnh tầm quan trọng của việc tối ưu hóa targeting thay vì chỉ tập trung vào việc gia tăng impressions.
Biểu đồ phân phối điểm Engagement Score tiết lộ một phân phối gần như chuẩn với đỉnh điểm quanh mức 5-6, cho thấy đa số khách hàng có mức độ tương tác trung bình. Phân phối này khá cân đối với cả hai phía của điểm trung bình, nhưng có sự sụt giảm đáng kể ở các mức engagement cao (8-10). Điều này chỉ ra rằng mặc dù doanh nghiệp đang duy trì được mức độ tương tục cơ bản với đa số khách hàng, nhưng vẫn còn dư địa lớn để chuyển đổi những khách hàng có engagement trung bình thành những người ủng hộ nhiệt thành.
Cuối cùng, biểu đồ phân bổ theo mức ROI cho thấy sự cân bằng tương đối giữa ba nhóm: Low, Medium và High. Sự phân bổ khá đồng đều này phản ánh một danh mục chiến dịch marketing đa dạng, trong đó có những chiến dịch hiệu quả cao, những chiến dịch trung bình và cả những chiến dịch cần cải thiện. Điều đáng chú ý là số lượng chiến dịch ở mức ROI High vẫn chiếm tỷ trọng đáng kể, chứng tỏ doanh nghiệp có khả năng tạo ra những chiến dịch chất lượng và nên tập trung học hỏi từ những thành công này để nhân rộng mô hình.
Tổng hợp lại, các đồ thị này cung cấp một cái nhìn toàn diện về hiệu suất marketing: Conversion Rate và ROI cần được phân tích độc lập, mối quan hệ giữa Clicks và Impressions tuân theo quy luật giảm dần, engagement của khách hàng tập trung ở mức trung bình, và danh mục chiến dịch có sự phân bổ ROI khá cân bằng. Những insights này gợi ý rằng chiến lược tối ưu nên tập trung vào việc nâng cao engagement từ mức trung bình lên cao, tối ưu targeting thay vì tăng impressions, và phân tích sâu các chiến dịch ROI cao để nhân rộng thành công.
Trong suốt giai đoạn 10 năm từ 2015 đến 2024, doanh nghiệp đã chứng kiến sự tăng trưởng vượt bậc về quy mô và lợi nhuận. Lợi nhuận sau thuế tăng trưởng liên tục và ấn tượng, từ mức 92.275 tỷ đồng năm 2015 lên đến 320.862 tỷ đồng năm 2024, gấp khoảng 3.5 lần, cho thấy khả năng mở rộng thị phần và hiệu quả kinh doanh ngày càng được cải thiện. Đặc biệt, các năm 2019-2020 và 2022-2023 là những giai đoạn tăng tốc mạnh mẽ, đưa lợi nhuận vượt mốc 200.000 tỷ và sau đó là 300.000 tỷ đồng.
Tuy nhiên, đằng sau thành công về lợi nhuận là những thách thức tài chính không nhỏ. Năm 2023 trở thành điểm đáng lo ngại khi lần đầu tiên sau nhiều năm, dòng tiền từ hoạt động kinh doanh (CFO) rơi vào trạng thái âm (~30.308 tỷ đồng). Nguyên nhân chính đến từ sự gia tăng mạnh của các khoản phải thu (~199.919 tỷ) và tồn kho (~260.749 tỷ), phản ánh áp lực thanh khoản và hiệu quả quản lý vốn lưu động chưa thực sự tốt. Bên cạnh đó, doanh nghiệp có xu hướng đầu tư mạnh qua nhiều năm, thể hiện ở dòng tiền đầu tư (CFI) âm liên tục, chủ yếu cho mua sắm tài sản cố định và gửi tiền tiết kiệm. Để duy trì hoạt động và mở rộng đầu tư, doanh nghiệp đã phải dựa nhiều vào vay nợ, với các khoản vay mới và trả nợ gốc luân phiên ở quy mô lớn.
Đến năm 2024, tín hiệu tích cực đã trở lại khi dòng tiền hoạt động phục hồi mạnh mẽ, đạt 216.267 tỷ đồng, đồng thời doanh nghiệp tiếp tục chú trọng trả nợ gốc, cho thấy nỗ lực cải thiện cơ cấu tài chính và giảm sự phụ thuộc vào đòn bẩy. Dù vậy, bài toán về quản lý vốn lưu động, kiểm soát công nợ và nâng cao hiệu suất sử dụng tài sản vẫn là những thách thức then chốt cần giải quyết để đảm bảo sự phát triển bền vững trong tương lai.
## # A tibble: 10 × 18
## year LoiNhuanSauThue Tien_DauKy Tien_CuoiKy CFO_Tong KhauHao
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 2015 92275349999 178550050326 87841659460 81130888888 38402557093
## 2 2016 101159344647 87841659460 100127453686 84650650055 37320990534
## 3 2017 117360040786 100127453686 106457131642 97212899364 31379088060
## 4 2018 138683041628 106457131642 190436654283 132094454149 30515092412
## 5 2019 162386686793 190436654283 75035614726 66590387415 41208658249
## 6 2020 209696878289 75035614726 85268705365 73153422780 53360966033
## 7 2021 189094874963 85268705365 271272865376 234881036040 60412122442
## 8 2022 223540317602 271272865376 178845070328 378603401448 60385696030
## 9 2023 299556005542 178845070328 106200569241 -30308428665 82642281566
## 10 2024 320862393082 106200569241 161983318837 216267565018 105636226909
## # ℹ 12 more variables: BienDong_PhaiThu <dbl>, BienDong_TonKho <dbl>,
## # BienDong_PhaiTra <dbl>, LaiVay_DaTra <dbl>, Thue_DaNop <dbl>,
## # CFI_Tong <dbl>, Chi_MuaTSCD <dbl>, Chi_TienGui <dbl>, Thu_TienGui <dbl>,
## # CFF_Tong <dbl>, VayMoi <dbl>, TraNoGoc <dbl>
Dùng hàm show() để tóm tắt bộ dữ liệu, kết hợp toán tử pipe(%>%)để kết quả trả ra là bảng.
## Rows: 10
## Columns: 18
## $ year <dbl> 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023,…
## $ LoiNhuanSauThue <dbl> 92275349999, 101159344647, 117360040786, 138683041628…
## $ Tien_DauKy <dbl> 178550050326, 87841659460, 100127453686, 106457131642…
## $ Tien_CuoiKy <dbl> 87841659460, 100127453686, 106457131642, 190436654283…
## $ CFO_Tong <dbl> 81130888888, 84650650055, 97212899364, 132094454149, …
## $ KhauHao <dbl> 38402557093, 37320990534, 31379088060, 30515092412, 4…
## $ BienDong_PhaiThu <dbl> -41333661601, -8928274802, -1437631837, 22334105781, …
## $ BienDong_TonKho <dbl> 50382333195, 10749182912, -47523201453, -43797978420,…
## $ BienDong_PhaiTra <dbl> -35669331173, -25111605021, 23575925481, -13724008827…
## $ LaiVay_DaTra <dbl> -605820692, -55154439, -618733502, -1275879713, -3707…
## $ Thue_DaNop <dbl> -26094252845, -22380008319, -31711798648, -3208302429…
## $ CFI_Tong <dbl> -204828797781, -14340785224, -443246932809, -48101241…
## $ Chi_MuaTSCD <dbl> -116451196931, -103904028053, -274456614870, -2724400…
## $ Chi_TienGui <dbl> -100000000000, -12000000000, -357729700000, -43817250…
## $ Thu_TienGui <dbl> NA, 100000000000, 183075000000, 221737811648, 2629776…
## $ CFF_Tong <dbl> 32990722640, -58008892000, 352371798300, NA, -6136326…
## $ VayMoi <dbl> 95894850000, NA, 120000000000, 160076187844, 21888822…
## $ TraNoGoc <dbl> -95894850000, NA, -120000000000, -160076187844, -1813…
Dùng hàm glimpse() thay thế hàm str() để cung cấp dữ liệu ngắn gọn, tổng thể.
## year LoiNhuanSauThue Tien_DauKy
## Min. :2015 Min. : 92275349999 Min. : 75035614726
## 1st Qu.:2017 1st Qu.:122690790996 1st Qu.: 90913108016
## Median :2020 Median :175740780878 Median :106328850442
## Mean :2020 Mean :185461493333 Mean :138003577443
## 3rd Qu.:2022 3rd Qu.:220079457774 3rd Qu.:178771315328
## Max. :2024 Max. :320862393082 Max. :271272865376
##
## Tien_CuoiKy CFO_Tong KhauHao
## Min. : 75035614726 Min. :-30308428665 Min. : 30515092412
## 1st Qu.: 90913108016 1st Qu.: 75147789307 1st Qu.: 37591382174
## Median :106328850442 Median : 90931774710 Median : 47284812141
## Mean :136346904294 Mean :133427627649 Mean : 54126367933
## 3rd Qu.:174629632455 3rd Qu.:195224287301 3rd Qu.: 60405515839
## Max. :271272865376 Max. :378603401448 Max. :105636226909
##
## BienDong_PhaiThu BienDong_TonKho BienDong_PhaiTra
## Min. :-83306984898 Min. :-260749238157 Min. :-49525833086
## 1st Qu.:-55960084902 1st Qu.: -61477533455 1st Qu.:-33029899635
## Median :-14460118668 Median : -34622213581 Median : -8277667477
## Mean :-12166658588 Mean : -41154397712 Mean : -7535274795
## 3rd Qu.: 14742465394 3rd Qu.: 6516640084 3rd Qu.: 16895829534
## Max. :115759490658 Max. : 52398387880 Max. : 39579670960
##
## LaiVay_DaTra Thue_DaNop CFI_Tong
## Min. :-6699943903 Min. :-83992016063 Min. :-443246932809
## 1st Qu.:-4413178073 1st Qu.:-56045224314 1st Qu.:-183596885752
## Median :-3598954722 Median :-41597605868 Median :-123911128404
## Mean :-3046559562 Mean :-45519649979 Mean :-130736762123
## 3rd Qu.: -783020055 3rd Qu.:-31804605059 3rd Qu.: -56861445622
## Max. : -55154439 Max. :-22380008319 Max. : 69894262492
##
## Chi_MuaTSCD Chi_TienGui Thu_TienGui
## Min. :-274456614870 Min. :-451171580000 Min. : 26297761332
## 1st Qu.:-127456519988 1st Qu.:-335047275000 1st Qu.:100000000000
## Median :-101628608786 Median :-176494739041 Median :195897929613
## Mean :-130057173899 Mean :-198920800808 Mean :204128349936
## 3rd Qu.: -91456180145 3rd Qu.: -57862937500 3rd Qu.:221737811648
## Max. : -52856687303 Max. : -12000000000 Max. :491300000000
## NA's :1
## CFF_Tong VayMoi TraNoGoc
## Min. :-271718144243 Min. :-315649453686 Min. :-351293662887
## 1st Qu.: -61363261179 1st Qu.: 95894850000 1st Qu.:-231513531376
## Median : -33304800015 Median : 160076187844 Median :-181308771504
## Mean : -4797122112 Mean : 142392327092 Mean :-183894915875
## 3rd Qu.: 34495813019 3rd Qu.: 229739387189 3rd Qu.:-120000000000
## Max. : 352371798300 Max. : 387993511872 Max. : -49387359000
## NA's :1 NA's :1 NA's :1
Hàm đã được giải thích ở Phần 1
Năm: Biến thời gian của dữ liệu quan sát. Phân bố từ 2015 đến 2024. Đây là dữ liệu rời rạc, các chỉ số thống kê (Min, Q1, Median, Mean, Max) chỉ cho biết phạm vi thời gian của mẫu.
Lợi nhuận sau thuế: Doanh nghiệp thể hiện sự tăng trưởng lợi nhuận sau thuế ấn tượng trong giai đoạn 2015-2024, từ mức sàn 92.275 tỷ đồng lên đến mức trần 320.862 tỷ đồng. Với giá trị trung bình đạt 185.461 tỷ đồng và trung vị ở 175.741 tỷ đồng, có thể thấy hiệu quả kinh doanh được cải thiện đáng kể theo thời gian, mặc dù vẫn tồn tại sự chênh lệch khá lớn giữa các năm.
Về dòng tiền hoạt động (CFO): Sức khỏe dòng tiền từ hoạt động kinh doanh có dấu hiệu bất ổn. Giá trị âm sâu nhất lên tới -30.308 tỷ đồng, trong khi năm đỉnh điểm đạt 378.603 tỷ đồng, cho thấy khả năng tạo tiền không ổn định và có thể phụ thuộc nhiều vào yếu tố mùa vụ hoặc chu kỳ kinh doanh. Trung bình dòng tiền ở mức 133.428 tỷ đồng là tích cực, nhưng sự dao động mạnh là một điểm đáng lưu ý.
Tiền đầu kỳ (Cash at the beginning of the period): Số dư tiền và các khoản tương đương tiền tại thời điểm đầu kỳ. Phân bố tương đối ổn định với Median là 1,063 tỷ. Mức cao nhất là 2,712 tỷ, cho thấy có những thời điểm dự trữ tiền mặt rất cao.
Tiền cuối kỳ (Cash at the end of the period): Số dư tiền và các khoản tương đương tiền tại thời điểm cuối kỳ. Rất gần với Tien_DauKy, cho thấy dòng tiền ròng trong kỳ không thay đổi đáng kể, với Median là 1,063 tỷ và Max là 2,712 tỷ.
Dòng tiền thuần từ hoạt động tài chính (Net Cash Flow from Financing Activities): Tổng lượng tiền mặt thu được hoặc chi ra từ việc phát hành/mua lại cổ phiếu, vay/trả nợ, và chi trả cổ tức. Phạm vi rất rộng (Min: -2,717 tỷ, Max: 3,523 tỷ). Median là -333 tỷ (âm) và Mean là -479 tỷ (âm), cho thấy xu hướng chung là công ty chi tiền cho hoạt động tài chính (có thể là trả nợ, mua lại cổ phiếu hoặc chi cổ tức).
Dòng tiền thuần từ hoạt động đầu tư (Net Cash Flow from Investing Activities): Tổng lượng tiền mặt thu được hoặc chi ra từ việc mua/thanh lý tài sản cố định hoặc đầu tư tài chính dài hạn. Toàn bộ các chỉ số (Min, Median, Mean, Max) đều là số âm (Mean: -1,307 tỷ). Điều này mạnh mẽ cho thấy công ty thường xuyên chi tiền cho hoạt động đầu tư, tức là mua sắm tài sản cố định (nhà xưởng, máy móc) hoặc các khoản đầu tư dài hạn.
Biến động các khoản phải thu (Change in Receivables): Sự thay đổi trong khoản tiền khách hàng nợ công ty (Thường là Phải thu cuối kỳ - Phải thu đầu kỳ). Median là -144 tỷ (âm), cho thấy trung bình các khoản phải thu giảm (tức là công ty thu được tiền từ khách hàng nhanh hơn), đây là dấu hiệu tốt về quản lý vốn lưu động. Phạm vi rất rộng (Max: 1,157 tỷ).
Biến động tồn kho (Change in Inventory): Sự thay đổi trong giá trị hàng tồn kho. Median là -346 tỷ (âm), cho thấy trung bình hàng tồn kho giảm. Nếu không phải là do mùa vụ, sự giảm này có thể là tín hiệu tốt về khả năng tiêu thụ. Phạm vi lớn (Min: -2,607 tỷ, Max: 523 tỷ).
Biến động các khoản phải trả (Change in Payables): Sự thay đổi trong khoản tiền công ty nợ nhà cung cấp. Median là -753 tỷ (âm), cho thấy trung bình các khoản phải trả giảm (tức là công ty chi tiền trả cho nhà cung cấp nhanh hơn hoặc vay ít hơn).
Chi mua tài sản cố định (Cash Paid for Fixed Assets/PPE): Lượng tiền mặt chi ra để mua sắm tài sản cố định (Chi đầu tư). Toàn bộ đều âm (Median: -1,016 tỷ; Mean: -1,300 tỷ), khẳng định công ty thường xuyên đầu tư mua sắm tài sản cố định.
Chi tiền gửi (Increase in Cash Deposits/Investments): Lượng tiền mặt dùng để gửi vào ngân hàng hoặc đầu tư ngắn hạn. Toàn bộ đều âm (Median: -1,764 tỷ; Mean: -1,989 tỷ), cho thấy công ty thường xuyên sử dụng tiền mặt để gửi tiết kiệm hoặc đầu tư an toàn.
Thu tiền gửi (Decrease in Cash Deposits/Investments): Lượng tiền mặt thu về từ việc rút tiền gửi hoặc thanh lý các khoản đầu tư ngắn hạn. Toàn bộ đều dương (Median: 1,958 tỷ; Mean: 2,041 tỷ). Có 1 giá trị NA (Not Available), cho thấy dữ liệu này có sự thiếu hụt.
Vay mới (New Debt Raised): Tổng số tiền mới vay thêm trong kỳ. Phạm vi từ -315 tỷ đến 3,879 tỷ. Median là 160 tỷ (dương), cho thấy công ty có xu hướng vay thêm vốn, nhưng mức độ rất đa dạng. Có 1 giá trị NA.
Trả nợ gốc (Principal Repayment): Lượng tiền mặt dùng để trả nợ gốc (không bao gồm lãi). Toàn bộ đều âm (Median: -1,813 tỷ; Mean: -1,838 tỷ). Mức trả nợ gốc rất lớn và ổn định, cao hơn nhiều so với VayMoi, phản ánh chính sách giảm nợ của công ty trong mẫu. Có 1 giá trị NA.
Tổng quan rủi ro: Mặc dù có tăng trưởng lợi nhuận tốt và chiến lược đầu tư bài bản, sự dao động mạnh của các chỉ số tài chính cùng với sự hiện diện của một số giá trị thiếu (NA) trong dữ liệu là những rủi ro tiềm ẩn. Việc ổn định dòng tiền và nâng cao hiệu quả quản lý vốn lưu động là chìa khóa để đảm bảo sự phát triển bền vững trong tương lai.
## [1] "year" "LoiNhuanSauThue" "Tien_DauKy" "Tien_CuoiKy"
## [5] "CFO_Tong" "KhauHao" "BienDong_PhaiThu" "BienDong_TonKho"
## [9] "BienDong_PhaiTra" "LaiVay_DaTra" "Thue_DaNop" "CFI_Tong"
## [13] "Chi_MuaTSCD" "Chi_TienGui" "Thu_TienGui" "CFF_Tong"
## [17] "VayMoi" "TraNoGoc"
Dùng hàm name() để lấy ra danh sách tên các cột (biến).Kết quả hiển thị một danh sách 18 tên biến.
## [1] 10
## [1] 10 18
Hàm n_distinct() đếm số lượng các giá trị duy nhất của biến year.
Hàm dim() trả về kích thước của đối tượng dữ liệu ta dưới dạng một vector số nguyên, với phần tử đầu tiên là số hàng và phần tử thứ hai là số cột.
Kết quả:
[1] 10 (Kết quả từ n_distinct(ta$year)):
Điều này có nghĩa là có 10 giá trị năm duy nhất trong dữ liệu (ví dụ: từ 2015 đến 2024, như đã thấy trong phân tích summary() trước đó).
[1] 10 18 (Kết quả từ dim(ta)):
10: Là số hàng (Row) hay số quan sát (Observation).
18: Là số cột (Column) hay số biến (Variable).
| x | |
|---|---|
| year | numeric |
| LoiNhuanSauThue | numeric |
| Tien_DauKy | numeric |
| Tien_CuoiKy | numeric |
| CFO_Tong | numeric |
| KhauHao | numeric |
| BienDong_PhaiThu | numeric |
| BienDong_TonKho | numeric |
| BienDong_PhaiTra | numeric |
| LaiVay_DaTra | numeric |
| Thue_DaNop | numeric |
| CFI_Tong | numeric |
| Chi_MuaTSCD | numeric |
| Chi_TienGui | numeric |
| Thu_TienGui | numeric |
| CFF_Tong | numeric |
| VayMoi | numeric |
| TraNoGoc | numeric |
Dùng hàm sapply() để xác định kiểu dữ liệu từng biến và trong bộ dữ liệu này 18 biến đều có kiểu dữ liệu numeric.
## [1] 4
| x | |
|---|---|
| year | 0 |
| LoiNhuanSauThue | 0 |
| Tien_DauKy | 0 |
| Tien_CuoiKy | 0 |
| CFO_Tong | 0 |
| KhauHao | 0 |
| BienDong_PhaiThu | 0 |
| BienDong_TonKho | 0 |
| BienDong_PhaiTra | 0 |
| LaiVay_DaTra | 0 |
| Thue_DaNop | 0 |
| CFI_Tong | 0 |
| Chi_MuaTSCD | 0 |
| Chi_TienGui | 0 |
| Thu_TienGui | 1 |
| CFF_Tong | 1 |
| VayMoi | 1 |
| TraNoGoc | 1 |
Kiểm tra có dữ liệu bị thiếu ở cột, ta thấy được có 14 cột không bị thiếu và 4 cột bị thiếu.
## [1] 0
Kết quả trả ra cho thấy dữ liệu không bị trùng lặp.
ta %>%
summarise(across(where(is.numeric),
function(x) {
q1 <- quantile(x, 0.25, na.rm = TRUE)
q3 <- quantile(x, 0.75, na.rm = TRUE)
iqr <- IQR(x, na.rm = TRUE)
lower_bound <- q1 - 1.5 * iqr
upper_bound <- q3 + 1.5 * iqr
sum(x < lower_bound | x > upper_bound, na.rm = TRUE)
})) %>%
print(n = Inf, width = Inf)## # A tibble: 1 × 18
## year LoiNhuanSauThue Tien_DauKy Tien_CuoiKy CFO_Tong KhauHao BienDong_PhaiThu
## <int> <int> <int> <int> <int> <int> <int>
## 1 0 0 0 0 1 1 0
## BienDong_TonKho BienDong_PhaiTra LaiVay_DaTra Thue_DaNop CFI_Tong Chi_MuaTSCD
## <int> <int> <int> <int> <int> <int>
## 1 1 0 0 0 1 2
## Chi_TienGui Thu_TienGui CFF_Tong VayMoi TraNoGoc
## <int> <int> <int> <int> <int>
## 1 0 1 2 1 0
ta %>% summarise(…): Bắt đầu bằng việc áp dụng các phép toán tóm tắt lên đối tượng dữ liệu ta.
across(where(is.numeric), function(x) {…}):across(): Áp dụng cùng một hàm cho nhiều cột.where(is.numeric): Chỉ áp dụng hàm cho tất cả các cột có kiểu dữ liệu là số (numeric).
Tính toán ranh giới ngoại lai:q1 <- quantile(x, 0.25, na.rm = TRUE): Tính Tứ phân vị thứ nhất (Q1).q3 <- quantile(x, 0.75, na.rm = TRUE): Tính Tứ phân vị thứ ba (Q3).iqr <- IQR(x, na.rm = TRUE): Tính Khoảng tứ phân vị (IQR): \(IQR = Q3 - Q1\).lower_bound <- q1 - 1.5 * iqr: Tính Ranh giới dưới.upper_bound <- q3 + 1.5 * iqr: Tính Ranh giới trên.sum(x < lower_bound | x > upper_bound, na.rm = TRUE):
Đây là bước đếm số lượng ngoại lai. Hàm này đếm tổng số các giá trị x (trong cột hiện tại) mà nhỏ hơn ranh giới dưới HOẶC lớn hơn ranh giới trên.
Tỷ lệ dữ liệu ngoại lai tương đối thấp, với chỉ 8/18 biến có giá trị ngoại lai và số lượng ngoại lai trên mỗi biến rất ít (chỉ 1-2 giá trị).
## ta %>% select(where(is.numeric))
##
## 18 Variables 10 Observations
## --------------------------------------------------------------------------------
## year
## n missing distinct Info Mean pMedian Gmd .05
## 10 0 10 1 2020 2020 3.667 2015
## .10 .25 .50 .75 .90 .95
## 2016 2017 2020 2022 2023 2024
##
## Value 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024
## Frequency 1 1 1 1 1 1 1 1 1 1
## Proportion 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1
## --------------------------------------------------------------------------------
## LoiNhuanSauThue
## n missing distinct Info Mean pMedian
## 10 0 10 1 185461493333 181111679615
## Gmd .05 .10 .25 .50 .75
## 93704691028 96273147591 100270945182 122690790997 175740780878 220079457774
## .90 .95
## 301686644296 311274518689
##
## Value 92275349999 101159344647 117360040786 138683041628 162386686793
## Frequency 1 1 1 1 1
## Proportion 0.1 0.1 0.1 0.1 0.1
##
## Value 189094874963 209696878289 223540317602 299556005542 320862393082
## Frequency 1 1 1 1 1
## Proportion 0.1 0.1 0.1 0.1 0.1
## --------------------------------------------------------------------------------
## Tien_DauKy
## n missing distinct Info Mean pMedian
## 10 0 10 1 138003577443 133343364894
## Gmd .05 .10 .25 .50 .75
## 70952273443 79640505514 84245396301 90913108017 106328850442 178771315328
## .90 .95
## 198520275392 234896570384
##
## Value 75035614726 85268705365 87841659460 100127453686 106200569241
## Frequency 1 1 1 1 1
## Proportion 0.1 0.1 0.1 0.1 0.1
##
## Value 106457131642 178550050326 178845070328 190436654283 271272865376
## Frequency 1 1 1 1 1
## Proportion 0.1 0.1 0.1 0.1 0.1
## --------------------------------------------------------------------------------
## Tien_CuoiKy
## n missing distinct Info Mean pMedian
## 10 0 10 1 136346904294 132736134505
## Gmd .05 .10 .25 .50 .75
## 69847824677 79640505514 84245396301 90913108017 106328850442 174629632455
## .90 .95
## 198520275392 234896570384
##
## Value 75035614726 85268705365 87841659460 100127453686 106200569241
## Frequency 1 1 1 1 1
## Proportion 0.1 0.1 0.1 0.1 0.1
##
## Value 106457131642 161983318837 178845070328 190436654283 271272865376
## Frequency 1 1 1 1 1
## Proportion 0.1 0.1 0.1 0.1 0.1
## --------------------------------------------------------------------------------
## CFO_Tong
## n missing distinct Info Mean pMedian
## 10 0 10 1 133427627649 108372552102
## Gmd .05 .10 .25 .50 .75
## 127539214837 13296038571 56900505807 75147789307 90931774710 195224287301
## .90 .95
## 249253272581 313928337014
##
## Value -30308428665 66590387415 73153422780 81130888888 84650650055
## Frequency 1 1 1 1 1
## Proportion 0.1 0.1 0.1 0.1 0.1
##
## Value 97212899364 132094454149 216267565018 234881036040 378603401448
## Frequency 1 1 1 1 1
## Proportion 0.1 0.1 0.1 0.1 0.1
## --------------------------------------------------------------------------------
## KhauHao
## n missing distinct Info Mean pMedian
## 10 0 10 1 54126367933 49407339768
## Gmd .05 .10 .25 .50 .75
## 27299776648 30903890454 31292688495 37591382174 47284812141 60405515839
## .90 .95
## 84941676100 95288951505
##
## Value 30515092412 31379088060 37320990534 38402557093 41208658249
## Frequency 1 1 1 1 1
## Proportion 0.1 0.1 0.1 0.1 0.1
##
## Value 53360966033 60385696030 60412122442 82642281566 105636226909
## Frequency 1 1 1 1 1
## Proportion 0.1 0.1 0.1 0.1 0.1
## --------------------------------------------------------------------------------
## BienDong_PhaiThu
## n missing distinct Info Mean pMedian
## 10 0 10 1 -12166658588 -19991962534
## Gmd .05 .10 .25 .50 .75
## 65155095978 -74646713996 -65986443094 -55960084902 -14460118668 14742465394
## .90 .95
## 31676644269 73718067463
##
## Value -83306984898 -64061938449 -60835559336 -41333661601 -19991962534
## Frequency 1 1 1 1 1
## Proportion 0.1 0.1 0.1 0.1 0.1
##
## Value -8928274802 -1437631837 20135831138 22334105781 115759490658
## Frequency 1 1 1 1 1
## Proportion 0.1 0.1 0.1 0.1 0.1
## --------------------------------------------------------------------------------
## BienDong_TonKho
## n missing distinct Info Mean
## 10 0 10 1 -41154397712
## pMedian Gmd .05 .10 .25
## -27689897272 93877850593 -177273252799 -93797267441 -61477533455
## .50 .75 .90 .95
## -34622213581 6516640084 50583938664 51491163272
##
## -260749238157 (1, 0.1), -75247048473 (1, 0.1), -66128977456 (1, 0.1),
## -47523201453 (1, 0.1), -43797978420 (1, 0.1), -25446448742 (1, 0.1),
## -6180988401 (1, 0.1), 10749182912 (1, 0.1), 50382333195 (1, 0.1), 52398387880
## (1, 0.1)
## --------------------------------------------------------------------------------
## BienDong_PhaiTra
## n missing distinct Info Mean pMedian
## 10 0 10 1 -7535274795 -7695765269
## Gmd .05 .10 .25 .50 .75
## 36086924875 -44642488855 -39759144624 -33029899635 -8277667477 16895829534
## .90 .95
## 25176300029 32377985494
##
## Value -49525833086 -38673957017 -35669331173 -25111605021 -13724008827
## Frequency 1 1 1 1 1
## Proportion 0.1 0.1 0.1 0.1 0.1
##
## Value -2831326127 6749916226 20277800636 23575925481 39579670960
## Frequency 1 1 1 1 1
## Proportion 0.1 0.1 0.1 0.1 0.1
## --------------------------------------------------------------------------------
## LaiVay_DaTra
## n missing distinct Info Mean pMedian
## 10 0 10 1 -3046559562 -2957747374
## Gmd .05 .10 .25 .50 .75
## 2690738115 -6074322471 -5448701040 -4413178073 -3598954722 -783020055
## .90 .95
## -550754067 -302954253
##
## Value -6699943903 -5309674055 -4475116208 -4227363668 -3707340260
## Frequency 1 1 1 1 1
## Proportion 0.1 0.1 0.1 0.1 0.1
##
## Value -3490569184 -1275879713 -618733502 -605820692 -55154439
## Frequency 1 1 1 1 1
## Proportion 0.1 0.1 0.1 0.1 0.1
## --------------------------------------------------------------------------------
## Thue_DaNop
## n missing distinct Info Mean pMedian
## 10 0 10 1 -45519649979 -43083226117
## Gmd .05 .10 .25 .50 .75
## 23293691764 -78058454868 -72124893673 -56045224314 -41597605868 -31804605059
## .90 .95
## -25722828392 -24051418356
##
## Value -83992016063 -70806324518 -59623516944 -45310346424 -42339105925
## Frequency 1 1 1 1 1
## Proportion 0.1 0.1 0.1 0.1 0.1
##
## Value -40856105810 -32083024291 -31711798648 -26094252845 -22380008319
## Frequency 1 1 1 1 1
## Proportion 0.1 0.1 0.1 0.1 0.1
## --------------------------------------------------------------------------------
## CFI_Tong
## n missing distinct Info Mean
## 10 0 10 1 -130736762123
## pMedian Gmd .05 .10 .25
## -123702553600 152761727925 -335958772046 -228670611284 -183596885752
## .50 .75 .90 .95
## -123911128404 -56861445623 -5917280452 31988491020
##
## -443246932809 (1, 0.1), -204828797781 (1, 0.1), -199303865931 (1, 0.1),
## -136475945213 (1, 0.1), -127199192457 (1, 0.1), -120623064351 (1, 0.1),
## -83142058686 (1, 0.1), -48101241268 (1, 0.1), -14340785224 (1, 0.1),
## 69894262492 (1, 0.1)
## --------------------------------------------------------------------------------
## Chi_MuaTSCD
## n missing distinct Info Mean
## 10 0 10 1 -130057173899
## pMedian Gmd .05 .10 .25
## -107902193225 82834794453 -273549149043 -272641683216 -127456519988
## .50 .75 .90 .95
## -101628608786 -91456180145 -62462345838 -57659516571
##
## -274456614870 (1, 0.1), -272440024143 (1, 0.1), -131124961007 (1, 0.1),
## -116451196931 (1, 0.1), -103904028053 (1, 0.1), -99353189519 (1, 0.1),
## -96770733614 (1, 0.1), -89684662322 (1, 0.1), -63529641231 (1, 0.1),
## -52856687303 (1, 0.1)
## --------------------------------------------------------------------------------
## Chi_TienGui
## n missing distinct Info Mean
## 10 0 10 1 -198920800808
## pMedian Gmd .05 .10 .25
## -197500000000 193215909957 -420494369000 -389817158000 -335047275000
## .50 .75 .90 .95
## -176494739041 -57862937500 -20550000000 -16275000000
##
## -451171580000 (1, 0.1), -383000000000 (1, 0.1), -357729700000 (1, 0.1),
## -267000000000 (1, 0.1), -247049478082 (1, 0.1), -105940000000 (1, 0.1),
## -100000000000 (1, 0.1), -43817250000 (1, 0.1), -21500000000 (1, 0.1),
## -12000000000 (1, 0.1)
## --------------------------------------------------------------------------------
## Thu_TienGui
## n missing distinct Info Mean pMedian
## 9 1 9 1 204128349936 200423323415
## Gmd
## 169716617638
##
## Value 26297761332 47675066830 100000000000 183075000000 195897929613
## Frequency 1 1 1 1 1
## Proportion 0.111 0.111 0.111 0.111 0.111
##
## Value 218000000000 221737811648 353171580000 491300000000
## Frequency 1 1 1 1
## Proportion 0.111 0.111 0.111 0.111
## --------------------------------------------------------------------------------
## CFF_Tong
## n missing distinct Info Mean pMedian
## 9 1 9 1 -4797122112 -13433724080
## Gmd
## 185363554013
##
## -271718144243 (1, 0.111), -112229740937 (1, 0.111), -61363261179 (1, 0.111),
## -58008892000 (1, 0.111), -33304800015 (1, 0.111), 32990722640 (1, 0.111),
## 34495813019 (1, 0.111), 73592405403 (1, 0.111), 352371798300 (1, 0.111)
## --------------------------------------------------------------------------------
## VayMoi
## n missing distinct Info Mean pMedian
## 9 1 9 1 142392327092 162817118595
## Gmd
## 220894300500
##
## -315649453686 (1, 0.111), 59802742133 (1, 0.111), 95894850000 (1, 0.111),
## 120000000000 (1, 0.111), 160076187844 (1, 0.111), 218888228325 (1, 0.111),
## 229739387189 (1, 0.111), 324785490153 (1, 0.111), 387993511872 (1, 0.111)
## --------------------------------------------------------------------------------
## TraNoGoc
## n missing distinct Info Mean
## 9 1 9 1 -183894915875
## pMedian Gmd
## -181308771504 111059252054
##
## -351293662887 (1, 0.111), -275297558126 (1, 0.111), -231513531376 (1, 0.111),
## -190282322134 (1, 0.111), -181308771504 (1, 0.111), -160076187844 (1, 0.111),
## -120000000000 (1, 0.111), -95894850000 (1, 0.111), -49387359000 (1, 0.111)
## --------------------------------------------------------------------------------
Mô tả chi tiết các biến số tài chính dạng số, được tạo ra bằng hàm describe(), cung cấp thông tin thống kê chuyên sâu hơn, bao gồm:
Khả năng sinh lời Lợi nhuận sau thuế (LoiNhuanSauThue) cho thấy xu hướng tăng trưởng mạnh mẽ và liên tục. Giá trị trung bình đạt 185.461 tỷ đồng và trung vị là 181.112 tỷ đồng, cho thấy sự phân bố khá cân đối. Điều đáng chú ý là giá trị nhỏ nhất là 92.275 tỷ đồng (2015) và lớn nhất lên tới 320.862 tỷ đồng (2024), phản ánh quy mô lợi nhuận được mở rộng đáng kể sau 10 năm.
Dòng tiền hoạt động (CFO) & Chi phí Dòng tiền từ hoạt động kinh doanh (CFO_Tong) có trung bình tích cực (133.428 tỷ đồng) nhưng biến động rất lớn (Gmd = 127.539 tỷ đồng), từ mức âm sâu -30.308 tỷ đồng đến mức dương kỷ lục 378.603 tỷ đồng. Điều này cho thấy khả năng tạo tiền không ổn định. Chi phí khấu hao (KhauHao) có xu hướng tăng đều qua các năm, với giá trị trung bình n Đây là điểm nghẽn đáng quan tâm: - Biến động phải thu (BienDong_PhaiThu): Trung bình âm ở -12.167 tỷ đồng, dao động từ -83.307 tỷ đến +115.759 tỷ đồng, cho thấy có những năm doanh nghiệp bị chiếm dụng vốn rất lớn. - Biến động tồn kho (BienDong_TonKho): Trung bình âm sâu ở -41.154 tỷ đồng, với biên độ rất rộng (từ -260.749 tỷ đến +52.398 tỷ đồng), phản ánh sự bất ổn trong quản lý hàng tồn kho. - Biến động phải trả (BienDong_PhaiTra): Trung bình âm (-7.535 tỷ đồng), cho thấy áp lực thanh toán cho nhà cung cấp.
Hoạt động đầu tư (CFI) Dòng tiền đầu tư (CFI_Tong) chủ yếu là âm (trung bình -130.737 tỷ đồng), khẳng định chiến lược đầu tư mở rộng liên tục. Các khoản chi chính bao gồm: - Chi mua TSCD (Chi_MuaTSCD): Trung bình -130.057 tỷ đồng. - Chi tiền gửi (Chi_TienGui): Trung bình -198.921 tỷ đồng, một khoản đầu tư tài chính đáng kể. - Thu tiền gửi (Thu_TienGui): Có trung bình dương (204.128 tỷ đồng), cho thấy hoạt động thu hồi các khoản đầu tư này cũng diễn ra thường xuyên.
Hoạt động tài trợ (CFF) & Cơ cấu nợ - Dòng tiền tài trợ (CFF_Tong): Trung bình gần bằng 0 (-4.797 tỷ đồng) nhưng biến động cực lớn, từ -271.718 tỷ đến +352.372 tỷ đồng, phản ánh sự thay đổi thất thường trong cơ cấu vốn. - Vay mới (VayMoi): Trung bình 142.392 tỷ đồng, cho thấy nhu cầu vay liên tục để tài trợ. - Trả nợ gốc (TraNoGoc): Trung bình -183.895 tỷ đồng, lớn hơn cả vay mới, chứng tỏ doanh nghiệp có chính sách quản lý nợ chủ động, ưu tiên giảm đòn bẩy.
variable_types <- data.frame(
Bien = names(ta),
Kieu = sapply(ta, class),
So_NA = colSums(is.na(ta)),
So_Gia_Tri_Duy_Nhat = sapply(ta, function(x) length(unique(x)))
)
kable(variable_types, caption = "PHÂN LOẠI BIẾN TRONG BỘ DỮ LIỆU")| Bien | Kieu | So_NA | So_Gia_Tri_Duy_Nhat | |
|---|---|---|---|---|
| year | year | numeric | 0 | 10 |
| LoiNhuanSauThue | LoiNhuanSauThue | numeric | 0 | 10 |
| Tien_DauKy | Tien_DauKy | numeric | 0 | 10 |
| Tien_CuoiKy | Tien_CuoiKy | numeric | 0 | 10 |
| CFO_Tong | CFO_Tong | numeric | 0 | 10 |
| KhauHao | KhauHao | numeric | 0 | 10 |
| BienDong_PhaiThu | BienDong_PhaiThu | numeric | 0 | 10 |
| BienDong_TonKho | BienDong_TonKho | numeric | 0 | 10 |
| BienDong_PhaiTra | BienDong_PhaiTra | numeric | 0 | 10 |
| LaiVay_DaTra | LaiVay_DaTra | numeric | 0 | 10 |
| Thue_DaNop | Thue_DaNop | numeric | 0 | 10 |
| CFI_Tong | CFI_Tong | numeric | 0 | 10 |
| Chi_MuaTSCD | Chi_MuaTSCD | numeric | 0 | 10 |
| Chi_TienGui | Chi_TienGui | numeric | 0 | 10 |
| Thu_TienGui | Thu_TienGui | numeric | 1 | 10 |
| CFF_Tong | CFF_Tong | numeric | 1 | 10 |
| VayMoi | VayMoi | numeric | 1 | 10 |
| TraNoGoc | TraNoGoc | numeric | 1 | 10 |
names(): Lấy ra danh sách tên các cột (biến) trong tập dữ liệu ta.
sapply(…, class): Xác định kiểu dữ liệu (ví dụ: numeric, character) cho từng cột trong ta.
colSums(is.na(…)): Đếm số lượng giá trị bị thiếu (NA) trong từng cột.
sapply(…, unique): Đếm số lượng giá trị duy nhất (distinct) cho từng cột.
Về cấu trúc và độ bao phủ của dữ liệu: Bộ dữ liệu bao gồm 18 biến số (numeric), ghi nhận thông tin tài chính trong vòng 10 năm liên tục (từ 2015 đến 2024). Một điểm đáng chú ý là tất cả các biến đều có đúng 10 giá trị duy nhất, tương ứng với mỗi năm, cho thấy dữ liệu được thu thập một cách nhất quán, không có sự trùng lặp hay thiếu sót theo trục thời gian.
Về tính toàn vẹn và chất lượng: Chất lượng dữ liệu
được đánh giá là rất tốt khi có tới 15/18 biến hoàn toàn không chứa giá
trị thiếu (NA). Chỉ có 4 biến là Thu_TienGui,
CFF_Tong, VayMoi và TraNoGoc là
có 1 giá trị thiếu. Tỷ lệ hoàn chỉnh cao này đảm bảo độ tin cậy cho hầu
hết các phân tích, và việc xử lý số ít giá trị thiếu kia cũng sẽ không
gây khó khăn đáng kể.
Về ý nghĩa và cách phân nhóm biến: Các biến được thiết kế một cách có hệ thống, phản ánh toàn diện bức tranh tài chính của doanh nghiệp. Có thể phân loại chúng thành các nhóm ý nghĩa kinh tế rõ rệt: nhóm chỉ tiêu kết quả kinh doanh (như lợi nhuận, khấu hao), nhóm dòng tiền (hoạt động, đầu tư, tài trợ), nhóm vốn lưu động (các khoản phải thu, phải trả, tồn kho), nhóm thuế và chi phí tài chính, và nhóm huy động vốn (vay mới, trả nợ gốc).
Về tiềm năng khai thác và phân tích: Với cấu trúc hoàn chỉnh và đa dạng chỉ tiêu như trên, bộ dữ liệu này mở ra nhiều hướng phân tích chuyên sâu. Nó rất phù hợp để phân tích xu hướng biến động của các chỉ số tài chính qua 10 năm, đánh giá mối quan hệ nhân quả giữa các hoạt động (như tác động của đầu tư đến lợi nhuận), kiểm tra hiệu quả quản lý vốn lưu động, hoặc thậm chí xây dựng các mô hình dự báo cho tương lai.
year_summary <- ta %>%
group_by(year) %>%
summarise(
So_Bien = n(),
Tong_Loi_Nhuan = sum(LoiNhuanSauThue, na.rm = TRUE),
Tong_CFO = sum(CFO_Tong, na.rm = TRUE)
) %>%
mutate(Phan_Tram_Loi_Nhuan = Tong_Loi_Nhuan/sum(Tong_Loi_Nhuan)*100)
kable(year_summary, caption = "TỔNG QUAN GIÁ TRỊ THEO NĂM")| year | So_Bien | Tong_Loi_Nhuan | Tong_CFO | Phan_Tram_Loi_Nhuan |
|---|---|---|---|---|
| 2015 | 1 | 92275349999 | 81130888888 | 4.975445 |
| 2016 | 1 | 101159344647 | 84650650055 | 5.454466 |
| 2017 | 1 | 117360040786 | 97212899364 | 6.328000 |
| 2018 | 1 | 138683041628 | 132094454149 | 7.477727 |
| 2019 | 1 | 162386686793 | 66590387415 | 8.755817 |
| 2020 | 1 | 209696878289 | 73153422780 | 11.306761 |
| 2021 | 1 | 189094874963 | 234881036040 | 10.195910 |
| 2022 | 1 | 223540317602 | 378603401448 | 12.053193 |
| 2023 | 1 | 299556005542 | -30308428665 | 16.151925 |
| 2024 | 1 | 320862393082 | 216267565018 | 17.300755 |
summarise()Tạo ra bảng tổng hợp với các cột mới
So_Bien = n()Đếm số lượng quan sát trong mỗi nhóm năm (luôn là 1, vì dữ liệu đã là hàng năm).
Tong_Loi_Nhuan = sum(LoiNhuanSauThue, na.rm = TRUE)Tính Tổng Lợi nhuận Sau Thuế cho mỗi năm.
Tong_CFO = sum(CFO_Tong, na.rm = TRUE)Tính Tổng Dòng tiền từ Hoạt động Kinh doanh (CFO) cho mỗi năm.
mutate(…)mutate()Tạo một cột mới: Phần trăm Lợi nhuận.
Phan_Tram_Loi_Nhuan = Tong_Loi_Nhuan / sum(Tong_Loi_Nhuan) x 100
Tính Tỷ trọng Lợi nhuận của năm đó so với Tổng Lợi nhuận của toàn bộ 10 năm của công ty (kết quả đã được chia cho tổng lợi nhuận của toàn bộ tập dữ liệu, sau đó nhân 100).
Về tổng lợi nhuận sau thuế: Doanh nghiệp thể hiện đà tăng trưởng lợi nhuận sau thuế liên tục và rất ấn tượng trong suốt 10 năm. Từ mức 92.275 tỷ đồng năm 2015, lợi nhuận đã tăng lên hơn 320.862 tỷ đồng vào năm 2024, tăng gấp khoảng 3.5 lần. Tốc độ tăng trưởng đặc biệt mạnh mẽ trong giai đoạn 2020-2024, giúp tỷ trọng lợi nhuận năm 2024 chiếm tới 17.3% tổng lợi nhuận cả giai đoạn.
Về dòng tiền hoạt động (CFO): Dòng tiền từ hoạt động kinh doanh có diễn biến phức tạp hơn. Giai đoạn 2015-2018 chứng kiến CFO tăng trưởng ổn định và đạt đỉnh 132.094 tỷ đồng năm 2018. Tuy nhiên, năm 2019 và 2020 ghi nhận sự sụt giảm đáng kể. Đặc biệt, năm 2023 là một dấu hiệu bất thường nghiêm trọng khi CFO rơi vào trạng thái âm (-30.308 tỷ đồng), phản ánh khủng hoảng trong khả năng tạo tiền từ hoạt động cốt lõi. May mắn thay, đến năm 2024, CFO đã phục hồi mạnh mẽ lên 216.267 tỷ đồng.
Về mối quan hệ giữa lợi nhuận và dòng tiền: Sự chênh lệch lớn giữa lợi nhuận và dòng tiền ở một số năm (như 2019, 2020, 2023) cho thấy chất lượng lợi nhuận có vấn đề. Lợi nhuận cao không đồng nghĩa với tiền mặt tốt, có thể do doanh nghiệp ghi nhận doanh thu nhưng chưa thu được tiền (phải thu tăng) hoặc hàng tồn kho tích trữ nhiều. Ngược lại, năm 2021 và 2022 là những năm dòng tiền hoạt động vượt trội hơn hẳn so với lợi nhuận, cho thấy khả năng quản lý vốn lư động hiệu quả trong các năm này.
| year | LoiNhuanSauThue |
|---|---|
| 2020 | 209696878289 |
| 2021 | 189094874963 |
| 2022 | 223540317602 |
| 2023 | 299556005542 |
| 2024 | 320862393082 |
Dùng hàm top_n() để lọc ra 5 năm có lợi nhuận sau thuế cao nhất.
## [1] "year" "loi_nhuan_sau_thue" "tien_dau_ky"
## [4] "tien_cuoi_ky" "cfo_tong" "khau_hao"
## [7] "bien_dong_phai_thu" "bien_dong_ton_kho" "bien_dong_phai_tra"
## [10] "lai_vay_da_tra" "thue_da_nop" "cfi_tong"
## [13] "chi_mua_tscd" "chi_tien_gui" "thu_tien_gui"
## [16] "cff_tong" "vay_moi" "tra_no_goc"
| x | |
|---|---|
| year | 0 |
| loi_nhuan_sau_thue | 0 |
| tien_dau_ky | 0 |
| tien_cuoi_ky | 0 |
| cfo_tong | 0 |
| khau_hao | 0 |
| bien_dong_phai_thu | 0 |
| bien_dong_ton_kho | 0 |
| bien_dong_phai_tra | 0 |
| lai_vay_da_tra | 0 |
| thue_da_nop | 0 |
| cfi_tong | 0 |
| chi_mua_tscd | 0 |
| chi_tien_gui | 0 |
| thu_tien_gui | 1 |
| cff_tong | 1 |
| vay_moi | 1 |
| tra_no_goc | 1 |
ta_clean1 <- ta_clean %>%
mutate(across(where(is.numeric),
~ifelse(is.na(.), median(., na.rm = TRUE), .)))
colSums(is.na(ta_clean1)) %>% kable()| x | |
|---|---|
| year | 0 |
| loi_nhuan_sau_thue | 0 |
| tien_dau_ky | 0 |
| tien_cuoi_ky | 0 |
| cfo_tong | 0 |
| khau_hao | 0 |
| bien_dong_phai_thu | 0 |
| bien_dong_ton_kho | 0 |
| bien_dong_phai_tra | 0 |
| lai_vay_da_tra | 0 |
| thue_da_nop | 0 |
| cfi_tong | 0 |
| chi_mua_tscd | 0 |
| chi_tien_gui | 0 |
| thu_tien_gui | 0 |
| cff_tong | 0 |
| vay_moi | 0 |
| tra_no_goc | 0 |
Kiểm tra lại các giá trị bị thiếu và thay bằng trung vị.
ta_clean1 <- ta_clean1 %>%
mutate(across(where(is.numeric),
list(
standardized = ~scale(.),
log_transformed = ~log(abs(.) + 1)
)))%>% (Pipe): Tiếp tục xử lý trên tập dữ liệu đã được làm sạch trước đó (ta_clean1).
mutate(): Thêm các cột mới (biến đã được biến đổi) vào tập dữ liệu ta_clean1.
across(…, where(is.numeric)): Áp dụng các hàm biến đổi sau cho tất cả các cột có kiểu dữ liệu là số (is.numeric).
scale()Chuẩn hóa (Standardization): Biến đổi dữ liệu sao cho Mean (Trung bình) bằng 0 và Standard Deviation (Độ lệch chuẩn) bằng 1.
log(abs(.) + 1): Áp dụng phép toán logarit tự nhiên để giảm độ lệch (skewness) của phân phối. Việc sử dụng abs(.) + 1 là để: - Đảm bảo dữ liệu luôn dương (abs(.) vì dữ liệu tài chính có thể âm, ví dụ: Chi phí, Dòng tiền Đầu tư).
ta_clean1 <- ta_clean1 %>%
mutate(bien_dong_tien_rong = tien_cuoi_ky - tien_dau_ky,
KiemTra_BaoCaoLuuChuyenTienTe = cff_tong + cfi_tong + cfo_tong)
ta_clean1 <- ta_clean1 %>%
mutate(ChenhLech = if_else(bien_dong_tien_rong == KiemTra_BaoCaoLuuChuyenTienTe,
0,
bien_dong_tien_rong - KiemTra_BaoCaoLuuChuyenTienTe))
kable(ta_clean1 %>% select(year, bien_dong_tien_rong, KiemTra_BaoCaoLuuChuyenTienTe, ChenhLech))| year | bien_dong_tien_rong | KiemTra_BaoCaoLuuChuyenTienTe | ChenhLech |
|---|---|---|---|
| 2015 | -90708390866 | -90707186253 | -1204613 |
| 2016 | 12285794226 | 12300972831 | -15178605 |
| 2017 | 6329677956 | 6337764855 | -8086899 |
| 2018 | 83979522641 | 50688412866 | 33291109775 |
| 2019 | -115401039557 | -115395938115 | -5101442 |
| 2020 | 10233090639 | 10269882970 | -36792331 |
| 2021 | 186004160011 | 186234790373 | -230630362 |
| 2022 | -92427795048 | -92418608726 | -9186322 |
| 2023 | -72644501087 | -72643907110 | -593977 |
| 2024 | 55782749596 | 55763572546 | 19177050 |
Chênh lệch nhỏ (Hầu hết các năm):
Hầu hết các năm (ví dụ: 2015, 2023), giá trị ChênhLệch rất nhỏ (-1.2 triệu VNĐ hoặc -0.5 triệu VNĐ).
Ý nghĩa: Điều này xác nhận rằng dữ liệu tiền tệ được thu thập có tính nhất quán cao; sự khác biệt nhỏ này thường là do sai số làm tròn trong quá trình tính toán hoặc báo cáo.
Chênh lệch lớn (Năm 2018):
Năm 2018, giá trị ChênhLệch là 33.29 tỷ VNĐ.
Ý nghĩa: Đây là một sai số lớn trong bối cảnh dữ liệu này. Nó có nghĩa là Biến động Tiền Ròng theo Bảng Cân đối Kế toán (83.97 tỷ VNĐ) không khớp với Tổng Dòng tiền từ 3 hoạt động (50.68 tỷ VNĐ).
ta_clean1 <- ta_clean1 %>%
mutate(DongTienTuDo = cfo_tong + chi_mua_tscd)
kable(ta_clean1 %>% select(year, DongTienTuDo))| year | DongTienTuDo |
|---|---|
| 2015 | -35320308043 |
| 2016 | -19253377998 |
| 2017 | -177243715506 |
| 2018 | -140345569994 |
| 2019 | -64534573592 |
| 2020 | -16531239542 |
| 2021 | 182024348737 |
| 2022 | 279250211929 |
| 2023 | -93838069896 |
| 2024 | 119496831404 |
Giai đoạn FCF Âm (2015 - 2020):
FCF chủ yếu âm sâu trong giai đoạn này (ví dụ: -353 tỷ VNĐ năm 2015).
Ý nghĩa: Công ty đang trong giai đoạn tăng trưởng và mở rộng mạnh mẽ. Mặc dù hoạt động kinh doanh tạo ra tiền (CFO dương), nhưng chi tiêu cho tài sản cố định (Chi_MuaTSCD) quá lớn (âm mạnh, Mean -1,300 tỷ VNĐ), vượt quá khả năng tạo ra tiền mặt của hoạt động kinh doanh. Điều này buộc công ty phải dùng tiền mặt dự trữ hoặc đi vay để tài trợ cho việc mở rộng này.
Giai đoạn FCF Dương (2021 - 2022 và 2024):
FCF chuyển sang dương lớn (ví dụ: 182 tỷ VNĐ năm 2021 và 119 tỷ VNĐ năm 2024).
Ý nghĩa: Công ty đã hoàn tất một phần lớn giai đoạn đầu tư ban đầu và tài sản mới bắt đầu tạo ra dòng tiền lớn hơn chi phí duy trì hoặc đầu tư thêm. FCF dương cho thấy công ty có tiền mặt sẵn sàng để trả cổ tức, mua lại cổ phiếu, hoặc giảm nợ (phù hợp với việc TraNoGoc âm mạnh).
FCF Âm trở lại (Năm 2023):
FCF chuyển sang âm -93.8 tỷ VNĐ trong năm 2023.
Ý nghĩa: Điều này có thể do một đợt chi tiêu vốn lớn khác trong năm đó, hoặc do CFO âm bất thường trong năm 2023 (như đã thấy trong phân tích CFO trước đó), làm giảm mạnh khả năng tài trợ vốn đầu tư bằng tiền mặt nội bộ.
ta_clean1 <- ta_clean1 %>%
mutate(TangGiam_LoiNhuan = ifelse(loi_nhuan_sau_thue > lag(loi_nhuan_sau_thue), "Tang", "Giam"))
kable(ta_clean1 %>% select(year, loi_nhuan_sau_thue, TangGiam_LoiNhuan))| year | loi_nhuan_sau_thue | TangGiam_LoiNhuan |
|---|---|---|
| 2015 | 92275349999 | NA |
| 2016 | 101159344647 | Tang |
| 2017 | 117360040786 | Tang |
| 2018 | 138683041628 | Tang |
| 2019 | 162386686793 | Tang |
| 2020 | 209696878289 | Tang |
| 2021 | 189094874963 | Giam |
| 2022 | 223540317602 | Tang |
| 2023 | 299556005542 | Tang |
| 2024 | 320862393082 | Tang |
Năm 2015: Kết quả là NA vì không có dữ liệu năm trước để so sánh (hàm lag() không có giá trị ở hàng đầu tiên).
Xu hướng chung: Lợi nhuận có xu hướng Tăng trưởng liên tục trong hầu hết các năm, đặc biệt là giai đoạn 2016-2020 và 2022-2024.
Sự sụt giảm: Có một sự sụt giảm lợi nhuận xảy ra vào năm 2021 (“Giam”), sau đó lợi nhuận lại tiếp tục tăng mạnh trở lại.
Ý nghĩa: Sự sụt giảm trong năm 2021 có thể phản ánh tác động của các yếu tố kinh tế vĩ mô (ví dụ: đại dịch COVID-19) hoặc chu kỳ kinh doanh, nhưng công ty đã nhanh chóng phục hồi và đạt mức lợi nhuận kỷ lục vào các năm tiếp theo (2023 và 2024).
Kết luận: Phân tích này khẳng định xu hướng tăng trưởng lợi nhuận bền vững trong dài hạn, chỉ bị gián đoạn nhẹ trong một năm.
ta_clean1 <- ta_clean1 %>%
mutate(VayRong = vay_moi + tra_no_goc,
ChinhSachNo = case_when(
VayRong > 0 ~ "Vay Them",
VayRong < 0 ~ "Tra No",
TRUE ~ "Can Bang" ))
kable(ta_clean1 %>% select(year, vay_moi, tra_no_goc, VayRong, ChinhSachNo))| year | vay_moi | tra_no_goc | VayRong | ChinhSachNo |
|---|---|---|---|---|
| 2015 | 95894850000 | -95894850000 | 0 | Can Bang |
| 2016 | 160076187844 | -181308771504 | -21232583660 | Tra No |
| 2017 | 120000000000 | -120000000000 | 0 | Can Bang |
| 2018 | 160076187844 | -160076187844 | 0 | Can Bang |
| 2019 | 218888228325 | -181308771504 | 37579456821 | Vay Them |
| 2020 | -315649453686 | -49387359000 | -365036812686 | Tra No |
| 2021 | 324785490153 | -190282322134 | 134503168019 | Vay Them |
| 2022 | 59802742133 | -231513531376 | -171710789243 | Tra No |
| 2023 | 229739387189 | -275297558126 | -45558170937 | Tra No |
| 2024 | 387993511872 | -351293662887 | 36699848985 | Vay Them |
Giai đoạn “Cân Bằng” (2015, 2017, 2018):
Công ty duy trì mức nợ ổn định khi khoản Vay Mới và Trả Nợ Gốc gần như triệt tiêu nhau, dẫn đến VayRong bằng 0.
Giai đoạn “Trả Nợ” (2016, 2020, 2022, 2023):
Chiếm đa số các năm (4/10 năm), đặc biệt là năm 2020 và 2023, công ty chi trả nợ gốc nhiều hơn khoản vay mới. Điều này phù hợp với việc công ty có Dòng tiền Tự Do dương (hoặc sắp dương) trong giai đoạn sau 2020, ưu tiên giảm gánh nặng nợ.
Giai đoạn “Vay Thêm” (2019, 2021, 2024):
Có 3 năm công ty Vay Thêm (Vay Ròng dương).
Ý nghĩa: Việc vay thêm diễn ra trong các năm có nhu cầu chi tiêu vốn lớn (Chi mua TSCĐ) hoặc để tài trợ cho các dự án mở rộng, cho thấy công ty vẫn linh hoạt trong việc sử dụng đòn bẩy khi cần thiết.
Kết luận: Chiến lược nợ của công ty chủ yếu là thận trọng và linh hoạt. Công ty có xu hướng giảm nợ (Tra No) khi có dòng tiền mạnh, nhưng sẵn sàng vay thêm (Vay Them) để tài trợ cho các cơ hội đầu tư và mở rộng.
ta_clean1 <- ta_clean1 %>%
mutate(XuHuong_TonKho = case_when(
bien_dong_ton_kho > 0 ~ "Tang",
bien_dong_ton_kho < 0 ~ "Giam",
TRUE ~ "On Dinh"
))
kable(ta_clean1 %>% select(year, bien_dong_ton_kho, XuHuong_TonKho))| year | bien_dong_ton_kho | XuHuong_TonKho |
|---|---|---|
| 2015 | 50382333195 | Tang |
| 2016 | 10749182912 | Tang |
| 2017 | -47523201453 | Giam |
| 2018 | -43797978420 | Giam |
| 2019 | -25446448742 | Giam |
| 2020 | -75247048473 | Giam |
| 2021 | -66128977456 | Giam |
| 2022 | 52398387880 | Tang |
| 2023 | -260749238157 | Giam |
| 2024 | -6180988401 | Giam |
Xu hướng: Biến động Tồn kho chuyển sang “Giảm” liên tục trong giai đoạn 2017-2021 và 2023-2024, cho thấy công ty quản lý và tiêu thụ hàng tồn kho rất hiệu quả.
ta_clean1 <- ta_clean1 %>%
mutate(
Quy_Trong_Nam = case_when(
year %% 4 == 0 ~ "Năm nhuận",
TRUE ~ "Năm thường"
),
Giai_Doan_Phat_Trien = case_when(
year <= 2017 ~ "Giai đoạn ổn định",
year <= 2020 ~ "Giai đoạn tăng trưởng",
year <= 2023 ~ "Giai đoạn biến động",
TRUE ~ "Giai đoạn phục hồi"
)
)Kiểm soát Yếu tố Thời gian: Biến Quy_Trong_Nam giúp kiểm soát ảnh hưởng của số ngày khác biệt trong năm (366 ngày so với 365 ngày) đối với các chỉ số doanh thu/lợi nhuận/dòng tiền.
Mô hình hóa Hành vi: Biến Giai_Doan_Phat_Trien cho phép các mô hình hồi quy hoặc phân tích thống kê kiểm tra xem hành vi tài chính (ví dụ: chi tiêu vốn, chiến lược nợ) có thay đổi đáng kể qua các giai đoạn phát triển kinh doanh đã được định nghĩa hay không.
ta_clean1 <- ta_clean1 %>%
mutate(muc_loi_nhuan = cut2(loi_nhuan_sau_thue, g = 3, levels.only = FALSE)) %>%
mutate(muc_loi_nhuan = case_when(
muc_loi_nhuan == levels(muc_loi_nhuan)[1] ~ "Thấp",
muc_loi_nhuan == levels(muc_loi_nhuan)[2] ~ "Trung bình",
muc_loi_nhuan == levels(muc_loi_nhuan)[3] ~ "Cao",
TRUE ~ as.character(muc_loi_nhuan)
))
kable(ta_clean1 %>% select(year, loi_nhuan_sau_thue, muc_loi_nhuan))| year | loi_nhuan_sau_thue | muc_loi_nhuan |
|---|---|---|
| 2015 | 92275349999 | Thấp |
| 2016 | 101159344647 | Thấp |
| 2017 | 117360040786 | Thấp |
| 2018 | 138683041628 | Thấp |
| 2019 | 162386686793 | Trung bình |
| 2020 | 209696878289 | Trung bình |
| 2021 | 189094874963 | Trung bình |
| 2022 | 223540317602 | Cao |
| 2023 | 299556005542 | Cao |
| 2024 | 320862393082 | Cao |
Giai đoạn Lợi nhuận “Thấp” (2015-2018): Đây là giai đoạn đầu của tập dữ liệu. Mặc dù công ty đã có lãi, mức lợi nhuận vẫn nằm trong nhóm thấp nhất so với chính công ty trong 10 năm.
Giai đoạn Lợi nhuận “Trung bình” (2019-2021): Lợi nhuận đã tăng lên và ổn định ở mức giữa.
Giai đoạn Lợi nhuận “Cao” (2022-2024): Công ty đã đạt được hiệu suất kinh doanh vượt trội, với lợi nhuận nằm trong nhóm cao nhất. Điều này khẳng định xu hướng tăng trưởng lợi nhuận mạnh mẽ và bền vững trong những năm gần đây.
Ý nghĩa: Phân tổ này giúp phân tích tác động của các yếu tố kinh tế (ví dụ: Chiến lược Nợ, FCF) lên các mức lợi nhuận khác nhau, thay vì chỉ dựa vào giá trị tuyệt đối.
ta_clean1 <- ta_clean1 %>%
mutate(muc_ton_kho = ifelse(bien_dong_ton_kho < mean(bien_dong_ton_kho), "Thap", "Cao"))
kable(ta_clean1 %>% select(year, bien_dong_ton_kho, muc_ton_kho))| year | bien_dong_ton_kho | muc_ton_kho |
|---|---|---|
| 2015 | 50382333195 | Cao |
| 2016 | 10749182912 | Cao |
| 2017 | -47523201453 | Thap |
| 2018 | -43797978420 | Thap |
| 2019 | -25446448742 | Cao |
| 2020 | -75247048473 | Thap |
| 2021 | -66128977456 | Thap |
| 2022 | 52398387880 | Cao |
| 2023 | -260749238157 | Thap |
| 2024 | -6180988401 | Cao |
Giai đoạn “Cao” (2015, 2016, 2022, 2024): Trong các năm này, tồn kho có xu hướng tăng nhẹ (dương) hoặc giảm không đáng kể so với mức giảm trung bình 10 năm. Ví dụ, năm 2015-2016, tồn kho tăng (dương), được xếp vào nhóm “Cao” vì lớn hơn Mean -41.15 tỷ VNĐ. Năm 2024 có giá trị -6,180,988,401 (khoảng -6.18 tỷ VNĐ), cũng lớn hơn Mean -41.15 tỷ VNĐ, cho thấy tồn kho giảm rất nhẹ.
Giai đoạn “Thấp” (2017-2021, 2023): Trong các năm này, tồn kho có xu hướng giảm rất mạnh (các giá trị đều âm sâu, nhỏ hơn Mean -41.15 tỷ VNĐ). Đặc biệt năm 2023 là -260.7 tỷ VNĐ, cho thấy hoạt động bán hàng hoặc thanh lý tồn kho diễn ra cực kỳ hiệu quả trong những năm này.
Phân tổ này giúp thấy rõ sự khác biệt trong quản lý tồn kho: Giai đoạn sau 2017 công ty có vẻ quản lý tồn kho chặt chẽ và bán hàng hiệu quả hơn, chỉ bị gián đoạn nhẹ bởi năm 2022.
ta_clean1 %>%
summarise(
Mean = mean(loi_nhuan_sau_thue) / 1000000,
Median = median(loi_nhuan_sau_thue) / 1000000,
SD = sd(loi_nhuan_sau_thue) / 1000000,
Variance = var(loi_nhuan_sau_thue) / 1000000,
Min = min(loi_nhuan_sau_thue) / 1000000,
Max = max(loi_nhuan_sau_thue) / 1000000,
Range = Max - Min
) %>% kable(caption = "THỐNG KÊ LỢI NHUẬN SAU THUẾ")| Mean | Median | SD | Variance | Min | Max | Range |
|---|---|---|---|---|---|---|
| 185461.5 | 175740.8 | 79267.83 | 6283389026124500 | 92275.35 | 320862.4 | 228587 |
summarise(): Tính toán các chỉ số thống kê từ cột loi_nhuan_sau_thue của tập dữ liệu.
mean(): Tính giá trị trung bình (Mean) của lợi nhuận.
median(): Tính giá trị trung vị (Median) của lợi nhuận.
sd(): Tính độ lệch chuẩn (Standard Deviation – SD), đo lường độ phân tán của dữ liệu.
var(): Tính phương sai (Variance), bình phương của độ lệch chuẩn.
min(): Tìm giá trị nhỏ nhất (Minimum) của lợi nhuận.
max(): Tìm giá trị lớn nhất (Maximum) của lợi nhuận.
Phép trừ: Tính phạm vi (Range), khoảng cách giữa giá trị lớn nhất và nhỏ nhất.
Mean (Trung bình): Lợi nhuận trung bình trong 10 năm là khoảng 1,855 tỷ VNĐ.
Median (Trung vị): Giá trị nằm giữa là 1,757 tỷ VNĐ. Giá trị này gần Mean, cho thấy phân phối khá đối xứng và không bị ảnh hưởng mạnh bởi ngoại lai.
SD (Độ lệch chuẩn): Lợi nhuận có độ lệch chuẩn lớn (khoảng 793 tỷ VNĐ), phản ánh sự tăng trưởng mạnh qua các năm, không chỉ là sự ổn định ở một mức duy nhất.
Variance (Phương sai) = 628,338,902,612,449,951,764,000. Phương sai rất lớn, do giá trị lợi nhuận lớn và sự chênh lệch đáng kể giữa các năm.
Min (Nhỏ nhất): Lợi nhuận thấp nhất là 922 tỷ VNĐ (năm 2015).
Max (Lớn nhất): Lợi nhuận cao nhất là 3,209 tỷ VNĐ (năm 2024).
Range (Phạm vi): Phạm vi lợi nhuận là 2,286 tỷ VNĐ, chứng minh sự tăng trưởng mạnh mẽ: lợi nhuận cao nhất gấp 3.47 lần lợi nhuận thấp nhất.
ta_clean1 %>%
summarise(
Mean = mean(cfo_tong) / 1000000,
Median = median(cfo_tong) / 1000000,
SD = sd(cfo_tong) / 1000000,
Variance = var(cfo_tong) / 1000000,
Min = min(cfo_tong) / 1000000,
Max = max(cfo_tong) / 1000000,
Range = Max - Min
) %>%
kable(
caption = "THỐNG KÊ DÒNG TIỀN HOẠT ĐỘNG",
digits = 2,
format.args = list(
big.mark = ",",
scientific = FALSE
)
)| Mean | Median | SD | Variance | Min | Max | Range |
|---|---|---|---|---|---|---|
| 133,427.6 | 90,931.77 | 114,796.2 | 13,178,169,807,990,848 | -30,308.43 | 378,603.4 | 408,911.8 |
mean(cfo_tong): Giá trị Trung bình, đo lường xu hướng trung tâm của cfo_tong.
median(cfo_tong): Giá trị Trung vị, là giá trị nằm chính giữa tập dữ liệu khi sắp xếp, ít bị ảnh hưởng bởi giá trị ngoại lai (outliers) hơn Mean.
sd(cfo_tong): Độ lệch chuẩn (Standard Deviation), đo lường mức độ phân tán/dao động của dữ liệu so với giá trị Mean.
var(cfo_tong): Phương sai, là bình phương của SD, cũng đo lường mức độ phân tán.
min(cfo_tong): Giá trị nhỏ nhất của cfo_tong.
max(cfo_tong): Giá trị lớn nhất của cfo_tong.
Mean Giá trị Trung bình, thể hiện xu hướng trung tâm của dữ liệu (trên 1.33 tỷ).
Median Giá trị Trung vị, là giá trị chính giữa, cao hơn Mean, cho thấy dữ liệu bị lệch (trên 4.99 tỷ).
SD Độ lệch chuẩn, đo lường độ phân tán của dữ liệu (rất lớn, trên 9 tỷ). Variance Phương sai, là bình phương của SD, xác nhận mức độ phân tán cực kỳ lớn.
Min Giá trị nhỏ nhất (âm), chỉ ra có ít nhất một quan sát có dòng tiền hoạt động âm (-3.03 tỷ).
Max Giá trị lớn nhất (rất lớn, trên 53.7 tỷ).
Range Phạm vi (Max - Min), thể hiện khoảng cách biến động rộng giữa giá trị cao nhất và thấp nhất (trên 40.8 tỷ).
stats_detailed <- ta_clean1 %>%
mutate(across(where(is.numeric) & !c(year), ~ . / 1000000000)) %>%
select(where(is.numeric)) %>%
psych::describe() %>%
rownames_to_column("Bien") %>%
select(Bien, n, mean, sd, min, max, skew, kurtosis) %>%
mutate(across(where(is.numeric), ~ round(., 2)))
kable(stats_detailed,
caption = "THỐNG KÊ MÔ TẢ CHI TIẾT TÀI CHÍNH (Đơn vị: Tỷ VND)",
format = "pipe",
digits = 2,
format.args = list(big.mark = ",", scientific = FALSE)
)| Bien | n | mean | sd | min | max | skew | kurtosis |
|---|---|---|---|---|---|---|---|
| year | 10 | 2,019.50 | 3.03 | 2,015.00 | 2,024.00 | 0.00 | -1.56 |
| loi_nhuan_sau_thue | 10 | 185.46 | 79.27 | 92.28 | 320.86 | 0.44 | -1.33 |
| tien_dau_ky | 10 | 138.00 | 63.71 | 75.04 | 271.27 | 0.78 | -0.80 |
| tien_cuoi_ky | 10 | 136.35 | 62.74 | 75.04 | 271.27 | 0.86 | -0.59 |
| cfo_tong | 10 | 133.43 | 114.80 | -30.31 | 378.60 | 0.74 | -0.39 |
| khau_hao | 10 | 54.13 | 24.31 | 30.52 | 105.64 | 0.87 | -0.58 |
| bien_dong_phai_thu | 10 | -12.17 | 57.50 | -83.31 | 115.76 | 0.80 | -0.17 |
| bien_dong_ton_kho | 10 | -41.15 | 89.04 | -260.75 | 52.40 | -1.26 | 0.95 |
| bien_dong_phai_tra | 10 | -7.54 | 29.92 | -49.53 | 39.58 | 0.10 | -1.59 |
| lai_vay_da_tra | 10 | -3.05 | 2.27 | -6.70 | -0.06 | -0.04 | -1.61 |
| thue_da_nop | 10 | -45.52 | 20.10 | -83.99 | -22.38 | -0.63 | -1.08 |
| cfi_tong | 10 | -130.74 | 137.80 | -443.25 | 69.89 | -0.80 | 0.17 |
| chi_mua_tscd | 10 | -130.06 | 78.92 | -274.46 | -52.86 | -1.02 | -0.66 |
| chi_tien_gui | 10 | -198.92 | 162.82 | -451.17 | -12.00 | -0.21 | -1.74 |
| thu_tien_gui | 10 | 203.31 | 138.52 | 26.30 | 491.30 | 0.63 | -0.54 |
| cff_tong | 10 | -7.65 | 158.83 | -271.72 | 352.37 | 0.69 | 0.43 |
| vay_moi | 10 | 144.16 | 190.60 | -315.65 | 387.99 | -1.10 | 0.75 |
| tra_no_goc | 10 | -183.64 | 87.68 | -351.29 | -49.39 | -0.33 | -0.86 |
| year_standardized | 10 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | -1.56 |
| year_log_transformed | 10 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | -1.56 |
| loi_nhuan_sau_thue_standardized | 10 | 0.00 | 0.00 | 0.00 | 0.00 | 0.44 | -1.33 |
| loi_nhuan_sau_thue_log_transformed | 10 | 0.00 | 0.00 | 0.00 | 0.00 | 0.03 | -1.55 |
| tien_dau_ky_standardized | 10 | 0.00 | 0.00 | 0.00 | 0.00 | 0.78 | -0.80 |
| tien_dau_ky_log_transformed | 10 | 0.00 | 0.00 | 0.00 | 0.00 | 0.40 | -1.49 |
| tien_cuoi_ky_standardized | 10 | 0.00 | 0.00 | 0.00 | 0.00 | 0.86 | -0.59 |
| tien_cuoi_ky_log_transformed | 10 | 0.00 | 0.00 | 0.00 | 0.00 | 0.45 | -1.37 |
| cfo_tong_standardized | 10 | 0.00 | 0.00 | 0.00 | 0.00 | 0.74 | -0.39 |
| cfo_tong_log_transformed | 10 | 0.00 | 0.00 | 0.00 | 0.00 | 0.08 | -1.02 |
| khau_hao_standardized | 10 | 0.00 | 0.00 | 0.00 | 0.00 | 0.87 | -0.58 |
| khau_hao_log_transformed | 10 | 0.00 | 0.00 | 0.00 | 0.00 | 0.42 | -1.29 |
| bien_dong_phai_thu_standardized | 10 | 0.00 | 0.00 | 0.00 | 0.00 | 0.80 | -0.17 |
| bien_dong_phai_thu_log_transformed | 10 | 0.00 | 0.00 | 0.00 | 0.00 | -0.94 | -0.07 |
| bien_dong_ton_kho_standardized | 10 | 0.00 | 0.00 | 0.00 | 0.00 | -1.26 | 0.95 |
| bien_dong_ton_kho_log_transformed | 10 | 0.00 | 0.00 | 0.00 | 0.00 | -0.20 | -0.62 |
| bien_dong_phai_tra_standardized | 10 | 0.00 | 0.00 | 0.00 | 0.00 | 0.10 | -1.59 |
| bien_dong_phai_tra_log_transformed | 10 | 0.00 | 0.00 | 0.00 | 0.00 | -0.94 | -0.45 |
| lai_vay_da_tra_standardized | 10 | 0.00 | 0.00 | 0.00 | 0.00 | -0.04 | -1.61 |
| lai_vay_da_tra_log_transformed | 10 | 0.00 | 0.00 | 0.00 | 0.00 | -1.11 | 0.03 |
| thue_da_nop_standardized | 10 | 0.00 | 0.00 | 0.00 | 0.00 | -0.63 | -1.08 |
| thue_da_nop_log_transformed | 10 | 0.00 | 0.00 | 0.00 | 0.00 | 0.17 | -1.40 |
| cfi_tong_standardized | 10 | 0.00 | 0.00 | 0.00 | 0.00 | -0.80 | 0.17 |
| cfi_tong_log_transformed | 10 | 0.00 | 0.00 | 0.00 | 0.00 | -0.58 | -0.28 |
| chi_mua_tscd_standardized | 10 | 0.00 | 0.00 | 0.00 | 0.00 | -1.02 | -0.66 |
| chi_mua_tscd_log_transformed | 10 | 0.00 | 0.00 | 0.00 | 0.00 | 0.47 | -1.00 |
| chi_tien_gui_standardized | 10 | 0.00 | 0.00 | 0.00 | 0.00 | -0.21 | -1.74 |
| chi_tien_gui_log_transformed | 10 | 0.00 | 0.00 | 0.00 | 0.00 | -0.53 | -1.38 |
| thu_tien_gui_standardized | 10 | 0.00 | 0.00 | 0.00 | 0.00 | 0.63 | -0.54 |
| thu_tien_gui_log_transformed | 10 | 0.00 | 0.00 | 0.00 | 0.00 | -0.70 | -0.77 |
| cff_tong_standardized | 10 | 0.00 | 0.00 | 0.00 | 0.00 | 0.69 | 0.43 |
| cff_tong_log_transformed | 10 | 0.00 | 0.00 | 0.00 | 0.00 | 0.71 | -1.13 |
| vay_moi_standardized | 10 | 0.00 | 0.00 | 0.00 | 0.00 | -1.10 | 0.75 |
| vay_moi_log_transformed | 10 | 0.00 | 0.00 | 0.00 | 0.00 | -0.38 | -1.19 |
| tra_no_goc_standardized | 10 | 0.00 | 0.00 | 0.00 | 0.00 | -0.33 | -0.86 |
| tra_no_goc_log_transformed | 10 | 0.00 | 0.00 | 0.00 | 0.00 | -0.68 | -0.44 |
| bien_dong_tien_rong | 10 | -1.66 | 94.51 | -115.40 | 186.00 | 0.49 | -0.96 |
| KiemTra_BaoCaoLuuChuyenTienTe | 10 | -4.96 | 91.76 | -115.40 | 186.23 | 0.57 | -0.68 |
| ChenhLech | 10 | 3.30 | 10.54 | -0.23 | 33.29 | 2.28 | 3.57 |
| DongTienTuDo | 10 | 3.37 | 145.78 | -177.24 | 279.25 | 0.58 | -1.10 |
| VayRong | 10 | -39.48 | 137.65 | -365.04 | 134.50 | -1.17 | 0.49 |
ta_clean1 %>%: Đặt tập dữ liệu ta_clean1 làm đầu vào cho chuỗi lệnh tiếp theo . select(where(is.numeric)): Chọn lọc ra tất cả các cột có kiểu dữ liệu là số (numeric). Các cột không phải số (ví dụ: văn bản, ngày tháng) sẽ bị loại bỏ khỏi tính toán.
psych::describe(): Sử dụng hàm describe từ gói psych để tính toán thống kê mô tả chi tiết cho các cột đã chọn. Hàm này tính các chỉ số như n, mean, sd, min, max, skew (độ xiên), và kurtosis (độ nhọn).
rownames_to_column(“Bien”): Chuyển tên các hàng (là tên các biến/cột dữ liệu sau khi chạy describe()) thành một cột mới có tên là Bien.
select(Bien, n, mean, sd, min, max, skew, kurtosis): Chọn lọc ra một tập hợp con các cột kết quả cụ thể để hiển thị, sắp xếp theo thứ tự mong muốn: Tên biến, số lượng quan sát, trung bình, độ lệch chuẩn, giá trị nhỏ nhất, lớn nhất, độ xiên, và độ nhọn.
mutate(across(where(is.numeric), ~ round(., 2))): Định dạng lại các cột số bằng cách áp dụng hàm round(., 2) (làm tròn đến 2 chữ số thập phân) cho tất cả các cột có kiểu số.
stats_detailed: Lưu trữ kết quả của toàn bộ chuỗi lệnh vào một đối tượng (biến) mới có tên là stats_detailed.
caption: “THỐNG KÊ MÔ TẢ CHI TIẾT TÀI CHÍNH” Đặt tiêu đề cho bảng.
format “pipe”: Đảm bảo định dạng đầu ra phù hợp (ví dụ: cho tài liệu Markdown).
digits: 2 Giới hạn số chữ số thập phân hiển thị là 2 (phù hợp với lệnh round đã làm trước đó).
format.args = list(…): Cung cấp các đối số để định dạng số lớn.
big.mark = “,”: Sử dụng dấu phẩy (,) làm ký hiệu phân tách hàng nghìn.
scientific = FALSE: Tắt định dạng số khoa học (scientific notation). Xu hướng Trung tâm:
Mean (Trung bình): Khoảng 133.42 tỷ. Đây là dòng tiền hoạt động trung bình của các quan sát.
Độ Phân tán:
SD (Độ lệch chuẩn): Khoảng 90.31 tỷ. SD rất lớn so với Mean, cho thấy sự biến động và khác biệt rất lớn về dòng tiền hoạt động giữa các công ty/quan sát.
Phạm vi (Min - Max): Dòng tiền hoạt động dao động từ khoảng 3.03 tỷ (giá trị nhỏ nhất - Min) đến 401.44 tỷ (giá trị lớn nhất - Max).
Kết quả:
Skew (Độ xiên): 0.44 (dương). Giá trị này nằm giữa 0 và 1, cho thấy phân phối hơi lệch sang phải. Điều này có thể do có một vài giá trị dòng tiền hoạt động rất cao (Max) kéo trung bình lên.
Kurtosis (Độ nhọn): -0.39 (âm). Cho thấy phân phối hơi bẹt hơn so với phân phối chuẩn (platykurtic).
Kết luận: Dữ liệu tài chính trong mẫu nhỏ này có mức độ phân tán cực kỳ cao và hơi bị lệch dương, cho thấy sự không đồng nhất lớn giữa các công ty/quan sát.
yearly_stats <- ta_clean1 %>%
mutate(
across(c(loi_nhuan_sau_thue, cfo_tong, cfi_tong, cff_tong),
~ . / 1000000)
) %>%
group_by(year) %>%
summarise(
across(c(loi_nhuan_sau_thue, cfo_tong, cfi_tong, cff_tong),
list(
mean = ~mean(., na.rm = TRUE),
sd = ~sd(., na.rm = TRUE),
cv = ~sd(., na.rm = TRUE)/mean(., na.rm = TRUE)
)
)
)
kable(yearly_stats, caption = "THỐNG KÊ BIẾN ĐỘNG THEO NĂM (TRIỆU VND)")| year | loi_nhuan_sau_thue_mean | loi_nhuan_sau_thue_sd | loi_nhuan_sau_thue_cv | cfo_tong_mean | cfo_tong_sd | cfo_tong_cv | cfi_tong_mean | cfi_tong_sd | cfi_tong_cv | cff_tong_mean | cff_tong_sd | cff_tong_cv |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2015 | 92275.35 | NA | NA | 81130.89 | NA | NA | -204828.80 | NA | NA | 32990.72 | NA | NA |
| 2016 | 101159.34 | NA | NA | 84650.65 | NA | NA | -14340.79 | NA | NA | -58008.89 | NA | NA |
| 2017 | 117360.04 | NA | NA | 97212.90 | NA | NA | -443246.93 | NA | NA | 352371.80 | NA | NA |
| 2018 | 138683.04 | NA | NA | 132094.45 | NA | NA | -48101.24 | NA | NA | -33304.80 | NA | NA |
| 2019 | 162386.69 | NA | NA | 66590.39 | NA | NA | -120623.06 | NA | NA | -61363.26 | NA | NA |
| 2020 | 209696.88 | NA | NA | 73153.42 | NA | NA | -136475.95 | NA | NA | 73592.41 | NA | NA |
| 2021 | 189094.87 | NA | NA | 234881.04 | NA | NA | -83142.06 | NA | NA | 34495.81 | NA | NA |
| 2022 | 223540.32 | NA | NA | 378603.40 | NA | NA | -199303.87 | NA | NA | -271718.14 | NA | NA |
| 2023 | 299556.01 | NA | NA | -30308.43 | NA | NA | 69894.26 | NA | NA | -112229.74 | NA | NA |
| 2024 | 320862.39 | NA | NA | 216267.57 | NA | NA | -127199.19 | NA | NA | -33304.80 | NA | NA |
Dữ liệu thô phân tán mạnh: Hầu hết các biến tiền tệ gốc (như loi_nhuan_sau_thue, cfo_tong, DongTienTuDo) có Độ lệch chuẩn (SD) rất lớn so với Mean, và Phạm vi (Min-Max) cực rộng. Điều này khẳng định sự không đồng nhất cao trong dữ liệu mẫu.
Dữ liệu bị lệch (Skewness): Nhiều biến gốc có Độ xiên dương (ví dụ: cfo_tong là 0.74, ChenhLech là 2.28), cho thấy phân phối bị kéo dài về phía các giá trị dương lớn (có thể là outliers).
Hiệu quả của Biến đổi:
Các biến đã được chuẩn hóa (_standardized) luôn có Mean = 0.00 và SD = 1.00 theo định nghĩa Z-score.
Các biến đã được logarit hóa (_log_transformed) thường có độ xiên và độ nhọn giảm đáng kể (ví dụ: loi_nhuan_sau_thue_log_transformed có Skew là 0.03 so với 0.44 của bản gốc), chứng minh phép biến đổi logarit đã giúp phân phối gần với phân phối chuẩn hơn.
quantile_analysis <- ta_clean1 %>%
mutate(across(c(loi_nhuan_sau_thue, cfo_tong, cfi_tong),
~ . / 1000000)) %>%
summarise(
across(c(loi_nhuan_sau_thue, cfo_tong, cfi_tong),
list(
Q0 = ~quantile(., 0, na.rm = TRUE),
Q1 = ~quantile(., 0.25, na.rm = TRUE),
Q2 = ~quantile(., 0.5, na.rm = TRUE),
Q3 = ~quantile(., 0.75, na.rm = TRUE),
Q4 = ~quantile(., 1, na.rm = TRUE)
)))
kable(quantile_analysis,
caption = "PHÂN TÍCH PHÂN VỊ CÁC CHỈ TIÊU CHÍNH (TRIỆU VND)",
digits = 2,
format.args = list(big.mark = ",", scientific = FALSE))| loi_nhuan_sau_thue_Q0 | loi_nhuan_sau_thue_Q1 | loi_nhuan_sau_thue_Q2 | loi_nhuan_sau_thue_Q3 | loi_nhuan_sau_thue_Q4 | cfo_tong_Q0 | cfo_tong_Q1 | cfo_tong_Q2 | cfo_tong_Q3 | cfo_tong_Q4 | cfi_tong_Q0 | cfi_tong_Q1 | cfi_tong_Q2 | cfi_tong_Q3 | cfi_tong_Q4 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 92,275.35 | 122,690.8 | 175,740.8 | 220,079.5 | 320,862.4 | -30,308.43 | 75,147.79 | 90,931.77 | 195,224.3 | 378,603.4 | -443,246.9 | -183,596.9 | -123,911.1 | -56,861.45 | 69,894.26 |
mutate(…)Biến đổi các cột tài chính (loi_nhuan_sau_thue, cfo_tong, cfi_tong) bằng cách chia giá trị cho \(1,000,000\) để chuyển đơn vị sang Triệu VND.
summarise(…)Tạo ra bảng tóm tắt, thực hiện các phép tính phân vị trên toàn bộ tập dữ liệu (sau khi đã chuyển đơn vị).
across(…)Áp dụng các phép tính phân vị cho nhiều cột tài chính cùng một lúc.quantile(., 0, na.rm = TRUE)Tính Phân vị 0 (Q0), tương đương với Giá trị nhỏ nhất (Min) của dữ liệu.
quantile(., 0.25, na.rm = TRUE)Tính Phân vị 1 (Q1), hay Tứ phân vị thứ nhất. 25% dữ liệu nhỏ hơn hoặc bằng giá trị này.
quantile(., 0.5, na.rm = TRUE)Tính Phân vị 2 (Q2), hay Trung vị (Median). 50% dữ liệu nhỏ hơn hoặc bằng giá trị này.
quantile(., 0.75, na.rm = TRUE)Tính Phân vị 3 (Q3), hay Tứ phân vị thứ ba. 75% dữ liệu nhỏ hơn hoặc bằng giá trị này.
quantile(., 1, na.rm = TRUE)Tính Phân vị 4 (Q4), tương đương với Giá trị lớn nhất (Max) của dữ liệu.
kable(…)Định dạng bảng kết quả. Tham số digits và format.args giúp làm gọn số và hiển thị đơn vị Triệu VND rõ ràng trong chú thích.
Lợi nhuận sau thuế (loi_nhuan_sau_thue)
Phân vị 1 (Q1 = 122,690.81 Triệu): 25% các công ty/quan sát có lợi nhuận dưới 122.69 tỷ VND. Phân vị 2 (Median = 175,740.82 Triệu): Trung vị của lợi nhuận là 175.74 tỷ VND. Phân vị 3 (Q3 = 220,079.53 Triệu): 75% các công ty/quan sát có lợi nhuận dưới 220.07 tỷ VND. Kết luận: Phân phối tập trung khá đều giữa Q1 và Q3 (khoảng cách Q3-Q1 là 97.38 tỷ), cho thấy phần lớn lợi nhuận nằm trong khoảnG 122.69 tỷ đến 220.07 tỷ.2.
Dòng tiền hoạt động (cfo_tong) Q0 (Min = -30,308.43 Triệu): Tồn tại các công ty/quan sát có dòng tiền hoạt động âm (-30.3 tỷ VND), cho thấy không đủ tiền mặt từ hoạt động kinh doanh cốt lõi.
Q2 (Median = 90,931.77 Triệu): Trung vị là 90.93 tỷ VND (dương), cho thấy hơn một nửa số quan sát có dòng tiền hoạt động tốt.
Q4 (Max = 378,603.40 Triệu): Giá trị tối đa rất cao, 378.6 tỷ VND.Kết luận: Dữ liệu có sự chênh lệch lớn, từ âm đến dương rất cao.
Phạm vi giữa Q3 và Q1 (195.22 - 75.14 = 120.08 tỷ) cho thấy sự đa dạng lớn trong hiệu quả kinh doanh.
Dòng tiền đầu tư (cfi_tong):
Q0 đến Q3 đều là giá trị âm: Điều này rất phổ biến. Dòng tiền đầu tư chủ yếu là chi cho tài sản cố định, vì vậy Q0 (Min) đến Q3 (75%) đều là giá trị âm (ví dụ, 75% các công ty chi từ 56.86 tỷ VND trở lên cho hoạt động đầu tư).
Q4 (Max = 69,894.26 Triệu): Có một số quan sát có dòng tiền đầu tư dương, nghĩa là họ đã bán tài sản đầu tư để thu tiền mặt.
Kết luận: Hoạt động đầu tư chủ yếu là chi tiêu (âm). Khoảng cách giữa Q3 và Q1 rất lớn (Phạm vi Liên Tứ phân vịIQR = Q3 - Q1), xác nhận mức độ biến động cao trong chi tiêu đầu tư.
normality_tests <- ta_clean1 %>%
summarise(across(c(loi_nhuan_sau_thue, cfo_tong, cfi_tong),
list(
shapiro_p = ~shapiro.test(.)$p.value
))) %>%
# Chuyển đổi định dạng bảng
pivot_longer(everything(), names_to = "Bien", values_to = "p_value") %>%
mutate(
Bien = gsub("_shapiro_p", "", Bien),
p_value = round(p_value, 4),
Ket_qua = ifelse(p_value > 0.05, "Phân phối chuẩn", "Không phân phối chuẩn")
)
kable(normality_tests,
caption = "KIỂM ĐỊNH PHÂN PHỐI CHUẨN (Shapiro-Wilk)",
col.names = c("Biến", "Giá trị p", "Kết quả"))| Biến | Giá trị p | Kết quả |
|---|---|---|
| loi_nhuan_sau_thue | 0.4191 | Phân phối chuẩn |
| cfo_tong | 0.2409 | Phân phối chuẩn |
| cfi_tong | 0.3481 | Phân phối chuẩn |
normality_tests <- …Lưu trữ kết quả kiểm định vào biến normality_tests.
across(…, list(shapiro_p = ~shapiro.test(.) p.value))Áp dụng hàm shapiro.test() cho ba cột (loi_nhuan_sau_thue, cfo_tong, cfi_tong) và chỉ trích xuất Giá trị p ($p.value) của bài kiểm định.
pivot_longer(everything(), …)Chuyển đổi cấu trúc dữ liệu từ định dạng rộng (wide) sang định dạng dài (long), giúp mỗi biến và giá trị p của nó nằm trên một hàng riêng biệt.
mutate(…)Thực hiện các biến đổi sau: Bien = gsub(…)Làm sạch tên biến, loại bỏ hậu tố _shapiro_p để tên cột Bien gọn gàng hơn p_value = round(p_value, 4)Làm tròn giá trị p về 4 chữ số thập phân.
Ket_qua = ifelse(p_value > 0.05, “Phân phối chuẩn”, …)Đưa ra kết luận kiểm định: Nếu p.value > 0.05 (Mức ý nghĩa ), chấp nhận giả thuyết H_0 (Phân phối chuẩn); ngược lại, bác bỏ giả thuyết H_0 (Không phân phối chuẩn).
kable(…, col.names = c(“Biến”, “Giá trị p”, “Kết quả”))Định dạng kết quả thành bảng với tiêu đề cột thân thiện.
Tất cả các biến tài chính chính (loi_nhuan_sau_thue, cfo_tong, cfi_tong) đều có Giá trị p lớn hơn 0.05. có thể kết luận rằng cả ba biến đều tuân theo phân phối chuẩn (hoặc ít nhất, phân phối của chúng không khác biệt đáng kể so với phân phối chuẩn). Điều này là một điều kiện thuận lợi, cho phép bạn sử dụng các phương pháp thống kê tham số (parametric tests) như kiểm định t-test hoặc phân tích hồi quy tuyến tính cổ điển, vốn yêu cầu giả định về tính chuẩn của dữ liệu.
anova_data <- ta_clean1 %>%
select(year, loi_nhuan_sau_thue, cfo_tong, cfi_tong) %>%
pivot_longer(-year, names_to = "variable", values_to = "value")
anova_result <- aov(value ~ variable, data = anova_data)
summary(anova_result)## Df Sum Sq Mean Sq F value
## variable 2 574905615849926177086222 287452807924963088548666 22.43
## Residuals 27 346050169844670467680826 12816672957210017399444
## Pr(>F)
## variable 0.00000182 ***
## Residuals
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
select(…) Chọn ba cột tài chính (loi_nhuan_sau_thue, cfo_tong, cfi_tong) và cột year từ tập dữ liệu.
pivot_longer(…) Chuyển đổi cấu trúc dữ liệu từ định dạng rộng (wide) sang định dạng dài (long). Điều này là cần thiết để chuẩn bị dữ liệu cho ANOVA: names_to = “variable” Tạo cột mới variable chứa tên của ba biến tài chính. values_to = “value” Tạo cột mới value chứa giá trị của ba biến tài chính.
anova_result <- aov(value ~ variable, data = anova_data) Thực hiện phân tích phương sai (ANOVA). Mô hình kiểm tra xem liệu giá trị trung bình của cột value có bị ảnh hưởng bởi nhóm (variable) hay không.
summary(anova_result) In ra bảng kết quả ANOVA chính thức.
Bảng ANOVA kiểm tra giả thuyết rằng giá trị trung bình của loi_nhuan_sau_thue, cfo_tong, và cfi_tong là bằng nhau. Giả thuyết \(H_0\): \(\mu_{\text{loi\_nhuan}} = \mu_{\text{cfo}} = \mu_{\text{cfi}}\) (Không có sự khác biệt giữa các trung bình). Giả thuyết \(H_a\): Ít nhất một cặp trung bình là khác nhau.
Kết quả: Giá trị p (Pr(>F)): Giá trị p là 0.00000182.So sánh với \(\alpha\): 0.00000182 rất nhỏ hơn 0.05 (mức ý nghĩa tiêu chuẩn). Kết luận: Bác bỏ giả thuyết \(H_0\).
group_comparison <- ta_clean1 %>%
mutate(High_Profit = loi_nhuan_sau_thue > median(loi_nhuan_sau_thue)) %>%
summarise(
t_test_cfo = t.test(cfo_tong ~ High_Profit)$p.value,
t_test_cfi = t.test(cfi_tong ~ High_Profit)$p.value,
t_test_cff = t.test(cff_tong ~ High_Profit)$p.value
)
kable(group_comparison, caption = "KIỂM ĐỊNH T-TEST THEO NHÓM LỢI NHUẬN")| t_test_cfo | t_test_cfi | t_test_cff |
|---|---|---|
| 0.3105355 | 0.4531494 | 0.3092235 |
mutate(High_Profit = loi_nhuan_sau_thue > median(loi_nhuan_sau_thue))Tạo biến phân nhóm (High_Profit): Phân chia tập dữ liệu thành hai nhóm: Lợi nhuận Cao (những công ty có lợi nhuận sau thuế lớn hơn Trung vị) và Lợi nhuận Thấp (nhỏ hơn hoặc bằng Trung vị).
summarise(…)Tính toán các kết quả kiểm định t-test.
t_test_cfo = t.test(cfo_tong ~ High_Profit)$p.valueThực hiện Kiểm định t-test để so sánh Trung bình Dòng tiền HĐ (cfo_tong) giữa nhóm Lợi nhuận Cao và nhóm Lợi nhuận Thấp, và chỉ lấy Giá trị p (p-value).
t_test_cfi = t.test(cfi_tong ~ High_Profit)$p.valueThực hiện Kiểm định t-test để so sánh Trung bình Dòng tiền ĐT (cfi_tong) giữa hai nhóm Lợi nhuận.
t_test_cff = t.test(cff_tong ~ High_Profit)$p.valueThực hiện Kiểm định t-test để so sánh Trung bình Dòng tiền TC (cff_tong) giữa hai nhóm Lợi nhuận.
kable(…)Định dạng kết quả thành bảng với tiêu đề phù hợp.
Kiểm định T-test kiểm tra giả thuyết rằng trung bình của hai nhóm là bằng nhau. Giả thuyết \(H_0\): Trung bình dòng tiền của Nhóm Lợi nhuận Cao = Trung bình dòng tiền của Nhóm Lợi nhuận Thấp. Mức ý nghĩa (\(\alpha\)): Thường là \(0.05\).
Tất cả các giá trị p đều lớn hơn 0.05. Ý nghĩa:
Không có sự khác biệt có ý nghĩa thống kê về Dòng tiền hoạt động (cfo_tong) giữa nhóm công ty có lợi nhuận cao và nhóm công ty có lợi nhuận thấp.
Không có sự khác biệt có ý nghĩa thống kê về Dòng tiền đầu tư (cfi_tong) giữa hai nhóm lợi nhuận.
Không có sự khác biệt có ý nghĩa thống kê về Dòng tiền tài chính (cff_tong) giữa hai nhóm lợi nhuận.
lm_simple <- lm(loi_nhuan_sau_thue ~ cfo_tong, data = ta_clean1)
summary_lm_simple <- summary(lm_simple)
kable(broom::tidy(lm_simple), caption = "HỒI QUY TUYẾN TÍNH ĐƠN: LỢI NHUẬN ~ DÒNG TIỀN")| term | estimate | std.error | statistic | p.value |
|---|---|---|---|---|
| (Intercept) | 169896933550.1840820 | 41442569003.729836 | 4.0995753 | 0.0034398 |
| cfo_tong | 0.1166517 | 0.240623 | 0.4847904 | 0.6408202 |
lm_simple <- lm(loi_nhuan_sau_thue ~ cfo_tong, data = ta_clean1): tạo mô hình hồi quy tuyến tính đơn: Dùng hàm lm() để mô tả mối quan hệ giữa lợi nhuận sau thuế (biến phụ thuộc) và dòng tiền hoạt động (biến độc lập).
summary_lm_simple <- summary(lm_simple) Tính toán và lưu trữ các thống kê mô hình chi tiết (hệ số, sai số chuẩn, giá trị t, giá trị p).
kable(broom::tidy(lm_simple), …) Định dạng kết quả hồi quy thành bảng (tidy giúp trích xuất các hệ số chính).
Mô hình hồi quy có dạng:\[\text{Lợi nhuận} = \beta_0 + \beta_1 \times \text{Dòng tiền HĐ} + \varepsilon\]
Phân tích Hệ số Chặn (Intercept - \(\beta_0\)):
Giá trị Ước tính: \(\approx 169.9\) tỷ VND.
Giá trị p: 0.00344 (\(\mathbf{< 0.05}\) - Có ý nghĩa thống kê).
Ý nghĩa: Khi Dòng tiền hoạt động (cfo_tong) bằng 0, Lợi nhuận sau thuế ước tính là 169.9 tỷ VND. Giá trị này có ý nghĩa thống kê.
Phân tích Hệ số Hồi quy (cfo_tong - \(\beta_1\)):
Giá trị Ước tính: \(0.11665\).
Giá trị p: \(0.64082\) (\(\mathbf{> 0.05}\) - Không có ý nghĩa thống kê).
Ý nghĩa:Về mặt kinh tế, nếu Dòng tiền hoạt động tăng thêm 1 VND, Lợi nhuận sau thuế ước tính sẽ tăng \(0.11665\) VND.Tuy nhiên, do giá trị p rất lớn (\(0.64\)), ta không thể bác bỏ giả thuyết \(H_0\) (Giả thuyết \(\beta_1 = 0\)).
lm_multiple <- lm(loi_nhuan_sau_thue ~ cfo_tong + cfi_tong + cff_tong,
data = ta_clean1)
summary_lm_multiple <- summary(lm_multiple)
kable(broom::tidy(lm_multiple), caption = "HỒI QUY TUYẾN TÍNH ĐA BIẾN")| term | estimate | std.error | statistic | p.value |
|---|---|---|---|---|
| (Intercept) | 191167827191.3656616 | 48221491979.8729858 | 3.9643698 | 0.0074146 |
| cfo_tong | 0.1566295 | 0.3633626 | 0.4310556 | 0.6814841 |
| cfi_tong | 0.2060250 | 0.3660027 | 0.5629057 | 0.5938929 |
| cff_tong | -0.0431501 | 0.3299348 | -0.1307838 | 0.9002212 |
lm_multiple <- lm(loi_nhuan_sau_thue ~ cfo_tong + cfi_tong + cff_tong, data = ta_clean1)Tạo mô hình hồi quy tuyến tính đa biến: Dùng hàm lm() để mô tả mối quan hệ giữa Lợi nhuận sau thuế (biến phụ thuộc) và Dòng tiền hoạt động, Đầu tư, Tài chính (biến độc lập).
summary_lm_multiple <- summary(lm_multiple)Tính toán và lưu trữ các thống kê mô hình chi tiết (bao gồm các hệ số, giá trị t, giá trị p, và \(R^2\)).
kable(broom::tidy(lm_multiple), …)Định dạng kết quả hồi quy thành bảng, trích xuất các hệ số chính.
Mô hình hồi quy có dạng:\[\text{Lợi nhuận} = \beta_0 + \beta_1 \times \text{CFO} + \beta_2 \times \text{CFI} + \beta_3 \times \text{CFF} + \varepsilon\]
Phân tích Hệ số Chặn (Intercept - \(\beta_0\))
Giá trị p: \(0.00741\) (\(\mathbf{< 0.05}\) - Có ý nghĩa thống kê).
Ý nghĩa: Khi tất cả các dòng tiền (CFO, CFI, CFF) đều bằng 0, Lợi nhuận sau thuế ước tính là \(\approx 191.17\) tỷ VND. Giá trị này có ý nghĩa.
Phân tích Hệ số Hồi quy (Các biến dòng tiền)
cfo_tong \(0.6814\). Không có ý nghĩa thống kê (\(p > 0.05\)).
cfi_tong \(0.5938\). Không có ý nghĩa thống kê (\(p > 0.05\)).
cff_tong \(0.9002\). Không có ý nghĩa thống kê (\(p > 0.05\)).
Tính ý nghĩa của Mô hình: Tương tự như hồi quy đơn, trong mô hình đa biến này, không có bất kỳ thành phần dòng tiền nào (CFO, CFI, CFF) có tác động có ý nghĩa thống kê đến Lợi nhuận sau thuế.
Mối quan hệ:
CFO và CFI có mối quan hệ dương với Lợi nhuận (tăng dòng tiền dự kiến tăng lợi nhuận), nhưng không đáng tin cậy về mặt thống kê.
CFF có mối quan hệ âm (tăng dòng tiền tài chính dự kiến giảm lợi nhuận), nhưng cũng không đáng tin cậy về mặt thống kê.
Kết luận chung: Mặc dù mô hình hồi quy đa biến này có vẻ mạnh mẽ hơn hồi quy đơn, nhưng do cỡ mẫu nhỏ (chỉ 10 quan sát) và độ phân tán dữ liệu lớn (như đã thấy ở các bảng thống kê trước), không có biến dòng tiền nào được chứng minh là có ảnh hưởng trực tiếp, có ý nghĩa thống kê đến Lợi nhuận sau thuế.
ts_analysis <- ta_clean1 %>%
select(year, loi_nhuan_sau_thue) %>%
mutate(
LNST_lag1 = lag(loi_nhuan_sau_thue),
LNST_lag2 = lag(loi_nhuan_sau_thue, 2),
LNST_diff = c(NA, diff(loi_nhuan_sau_thue)),
LNST_growth = (loi_nhuan_sau_thue / lag(loi_nhuan_sau_thue) - 1) * 100
)
kable(ts_analysis, caption = "PHÂN TÍCH CHUỖI THỜI GIAN LỢI NHUẬN")| year | loi_nhuan_sau_thue | LNST_lag1 | LNST_lag2 | LNST_diff | LNST_growth |
|---|---|---|---|---|---|
| 2015 | 92275349999 | NA | NA | NA | NA |
| 2016 | 101159344647 | 92275349999 | NA | 8883994648 | 9.627701 |
| 2017 | 117360040786 | 101159344647 | 92275349999 | 16200696139 | 16.015027 |
| 2018 | 138683041628 | 117360040786 | 101159344647 | 21323000842 | 18.168876 |
| 2019 | 162386686793 | 138683041628 | 117360040786 | 23703645165 | 17.091956 |
| 2020 | 209696878289 | 162386686793 | 138683041628 | 47310191496 | 29.134280 |
| 2021 | 189094874963 | 209696878289 | 162386686793 | -20602003326 | -9.824659 |
| 2022 | 223540317602 | 189094874963 | 209696878289 | 34445442639 | 18.215958 |
| 2023 | 299556005542 | 223540317602 | 189094874963 | 76015687940 | 34.005359 |
| 2024 | 320862393082 | 299556005542 | 223540317602 | 21306387540 | 7.112656 |
select(year, loi_nhuan_sau_thue)Lấy ra hai cột chính là Năm và Lợi nhuận sau thuế để phân tích.
mutate(…)Tạo ra các biến chuỗi thời gian mới
LNST_lag1 = lag(loi_nhuan_sau_thue)Tính giá trị độ trễ 1 kỳ (Lag 1) của Lợi nhuận sau thuế. Đây là lợi nhuận của năm trước đó (t-1).
LNST_lag2 = lag(loi_nhuan_sau_thue, 2)Tính giá trị độ trễ 2 kỳ (Lag 2) của Lợi nhuận sau thuế. Đây là lợi nhuận của hai năm trước (t-2).
LNST_diff = c(NA, diff(loi_nhuan_sau_thue))Tính chênh lệch tuyệt đối (First Difference) của Lợi nhuận sau thuế so với năm trước.
LNST_growth = (loi_nhuan_sau_thue / lag(loi_nhuan_sau_thue) - 1) * 100Tính tốc độ tăng trưởng phần trăm của Lợi nhuận sau thuế so với năm trước.
kable(ts_analysis, …)Định dạng bảng kết quả.
Lợi nhuận sau thuế có tính chu kỳ và sự biến động rất lớn qua các năm, với các năm tăng trưởng mạnh (2023: 34%) và năm sụt giảm sâu (2021: -9.824%).
Việc tính toán các biến độ trễ (LNST_lag1, LNST_lag2) cho phép sử dụng các giá trị lợi nhuận quá khứ làm biến độc lập trong các mô hình kinh tế lượng (ví dụ: AR, ARMA, hoặc hồi quy đa biến) để dự báo lợi nhuận tương lai.
volatility_analysis <- ta_clean1 %>%
summarise(
Volatility_LNST = sd(loi_nhuan_sau_thue, na.rm = TRUE) / mean(loi_nhuan_sau_thue, na.rm = TRUE),
Volatility_CFO = sd(cfo_tong, na.rm = TRUE) / mean(cfo_tong, na.rm = TRUE),
Volatility_CFI = sd(cfi_tong, na.rm = TRUE) / mean(cfi_tong, na.rm = TRUE),
Volatility_CFF = sd(cff_tong, na.rm = TRUE) / mean(cff_tong, na.rm = TRUE)
)
kable(volatility_analysis, caption = "PHÂN TÍCH ĐỘ BIẾN ĐỘNG CÁC CHỈ TIÊU")| Volatility_LNST | Volatility_CFO | Volatility_CFI | Volatility_CFF |
|---|---|---|---|
| 0.4274086 | 0.8603631 | -1.054016 | -20.76817 |
summarise(…)Tính toán các tỷ lệ biến động trên toàn bộ tập dữ liệu.
sd(loi_nhuan_sau_thue) / mean(loi_nhuan_sau_thue)Volatility_LNSTHệ số Biến thiên của Lợi nhuận sau thuế: Đo lường độ biến động tương đối của lợi nhuận.
sd(cfo_tong) / mean(cfo_tong)Volatility_CFOHệ số Biến thiên của Dòng tiền HĐ.
sd(cfi_tong) / mean(cfi_tong)Volatility_CFIHệ số Biến thiên của Dòng tiền ĐT.
sd(cff_tong) / mean(cff_tong)Volatility_CFFHệ số Biến thiên của Dòng tiền TC.
kable(…)Định dạng bảng kết quả.
Độ biến động tương đối cao nhất thuộc về Dòng tiền Tài chính (CFF), với CV tuyệt đối lên tới \(20.77\). Điều này cho thấy sự không ổn định rất lớn trong hoạt động huy động và trả nợ của các công ty.
Độ biến động cao thứ hai là Dòng tiền Đầu tư (CFI), với CV tuyệt đối là \(1.05\). Điều này phản ánh sự thiếu ổn định trong chi tiêu và thu hồi đầu tư tài sản dài hạn.
Lợi nhuận sau thuế (LNST) có độ biến động tương đối thấp nhất (\(0.43\)) trong số các chỉ tiêu tiền tệ lớn, cho thấy Lợi nhuận ổn định hơn Dòng tiền từ các hoạt động khác.
trend_analysis <- ta_clean1 %>%
mutate(Trend = 1:n()) %>%
summarise(
Trend_LNST = lm(loi_nhuan_sau_thue ~ Trend)$coefficients[2],
Trend_CFO = lm(cfo_tong ~ Trend)$coefficients[2],
Trend_CFI = lm(cfi_tong ~ Trend)$coefficients[2],
Trend_CFF = lm(cff_tong ~ Trend)$coefficients[2]
)
kable(trend_analysis, caption = "PHÂN TÍCH XU HƯỚNG TUYẾN TÍNH")| Trend_LNST | Trend_CFO | Trend_CFI | Trend_CFF |
|---|---|---|---|
| 25306103573 | 12929647428 | 14466980504 | -22777562748 |
mutate(Trend = 1:n())Tạo biến thời gian (Trend): Gán một chuỗi số tự nhiên tăng dần (1, 2, 3,…) cho mỗi quan sát. Đây là biến độc lập đại diện cho thời gian.
summarise(…)Tính toán các kết quả cho các mô hình hồi quy.Trend_LNST = lm(loi_nhuan_sau_thue ~ Trend)$coefficients[2]Thực hiện hồi quy tuyến tính đơn giữa Lợi nhuận sau thuế và Trend. Sau đó, trích xuất hệ số hồi quy (Coefficient - \(\beta_1\)), thể hiện mức tăng/giảm trung bình của Lợi nhuận sau thuế qua mỗi kỳ thời gian.
Trend_CFO, Trend_CFI, Trend_CFFTương tự, tính toán hệ số xu hướng cho Dòng tiền hoạt động (CFO), Dòng tiền đầu tư (CFI), và Dòng tiền tài chính (CFF).
kable(trend_analysis, …)Định dạng bảng kết quả.
Lợi nhuận và Dòng tiền Hoạt động/Đầu tư có Xu hướng Tăng: Lợi nhuận sau thuế, Dòng tiền hoạt động (CFO), và Dòng tiền đầu tư (CFI) đều có xu hướng tăng dương theo thời gian. Điều này cho thấy hoạt động kinh doanh và đầu tư đang mở rộng.
Dòng tiền Tài chính có Xu hướng Giảm: Dòng tiền tài chính (CFF) có xu hướng giảm âm theo thời gian. Điều này có thể phản ánh việc công ty/các công ty đang:
Giảm vay nợ (trả gốc nhiều hơn vay mới).
Tăng chi trả cổ tức (dòng tiền chi ra).
Tự chủ tài chính hơn, ít phụ thuộc vào huy động vốn bên ngoài.
ta_clean1 <- ta_clean1 %>%
mutate(
TySo_ThanhKhoanHienHanh = (tien_cuoi_ky + bien_dong_phai_thu + bien_dong_ton_kho) / abs(bien_dong_phai_tra),
ROA = loi_nhuan_sau_thue / (tien_cuoi_ky + abs(bien_dong_phai_thu) + abs(bien_dong_ton_kho)),
ROS = loi_nhuan_sau_thue / (loi_nhuan_sau_thue + abs(cfo_tong)),
TySo_No = abs(vay_moi + tra_no_goc) / (loi_nhuan_sau_thue + 1),
VongQuay_PhaiThu = cfo_tong / abs(bien_dong_phai_thu),
VongQuay_TonKho = cfo_tong / abs(bien_dong_ton_kho)
)
kable(ta_clean1 %>% select(year, TySo_ThanhKhoanHienHanh, ROA, ROS, TySo_No),
caption = "CÁC TỶ SỐ TÀI CHÍNH CHỦ CHỐT")| year | TySo_ThanhKhoanHienHanh | ROA | ROS | TySo_No |
|---|---|---|---|---|
| 2015 | 2.716348 | 0.5139037 | 0.5321340 | 0.0000000 |
| 2016 | 4.059811 | 0.8443673 | 0.5444236 | 0.2098925 |
| 2017 | 2.438772 | 0.7551253 | 0.5469471 | 0.0000000 |
| 2018 | 12.312203 | 0.5405298 | 0.5121661 | 0.0000000 |
| 2019 | -2.144141 | 0.9868891 | 0.7091832 | 0.2314196 |
| 2020 | -1.026008 | 0.9473487 | 0.7413705 | 1.7407832 |
| 2021 | 113.340309 | 0.4172794 | 0.4460038 | 0.7112999 |
| 2022 | 6.351222 | 0.8892551 | 0.3712408 | 0.7681424 |
| 2023 | -4.513131 | 0.7741630 | 0.9081185 | 0.1520857 |
| 2024 | 3.575109 | 1.2759404 | 0.5973645 | 0.1143788 |
mutate(…)Thêm các cột tỷ số tài chính mới vào tập dữ liệu.
(tien_cuoi_ky + bien_dong_phai_thu + bien_dong_ton_kho) / abs(bien_dong_phai_tra).Tỷ số Thanh khoản Hiện hành (Current Ratio): Đo lường khả năng thanh toán các khoản nợ ngắn hạn bằng tài sản ngắn hạn.
loi_nhuan_sau_thue / (tien_cuoi_ky + abs(bien_dong_phai_thu) + abs(bien_dong_ton_kho)).Tỷ suất sinh lời trên Tổng tài sản (Return on Assets): Đo lường hiệu quả sử dụng tài sản để tạo ra lợi nhuận.
loi_nhuan_sau_thue / (loi_nhuan_sau_thue + abs(cfo_tong)).Tỷ suất sinh lời trên Doanh thu (Return on Sales): Đo lường hiệu quả của doanh thu đối với lợi nhuận. (Lưu ý: Công thức này có vẻ đã thay thế Doanh thu bằng một tổ hợp Lợi nhuận và Dòng tiền HĐ).
abs(vay_moi + tra_no_goc) / abs(loi_nhuan_sau_thue + 1).Tỷ số Nợ (Debt Ratio): Đo lường mức độ sử dụng nợ. (Công thức này không theo định nghĩa chuẩn, có thể là một tỷ số đặc thù).
cfo_tong / abs(bien_dong_phai_thu)Vòng quay Phải thu: Đo lường tốc độ thu hồi nợ (từ Dòng tiền HĐ so với Biến động Phải thu).
cfo_tong / abs(bien_dong_ton_kho)Vòng quay Tồn kho: Đo lường tốc độ bán hàng (từ Dòng tiền HĐ so với Biến động Tồn kho).
kable(…)Định dạng bảng kết quả.
Thanh khoản Biến động mạnh: Tỷ số Thanh khoản Hiện hành (TySo_ThanhKhoanHienHanh) có sự biến động cực lớn: Âm (-2.14) vào năm 2019 và -4.51 vào năm 2023: Giá trị âm là rất bất thường và có thể chỉ ra lỗi trong việc sử dụng biến abs() (giá trị tuyệt đối) trong công thức hoặc dữ liệu đầu vào. Tỷ số thanh khoản không được phép âm trong thực tế.
Cực cao (113.34) vào năm 2021: Giá trị này cho thấy tài sản ngắn hạn lớn hơn nợ ngắn hạn đến hơn 113 lần, một sự dư thừa thanh khoản không hợp lý, có thể do một giá trị ngoại lai lớn hoặc lỗi dữ liệu.
ROA và ROS: Các tỷ suất sinh lời (ROA và ROS) nhìn chung ổn định và dương, dao động trong khoảng \(0.4\) đến \(0.9\). Điều này cho thấy các công ty vẫn tạo ra lợi nhuận tốt từ tài sản và hoạt động kinh doanh.
Tỷ số Nợ có xu hướng tăng dần từ 2019 đến 2023 (từ \(0.23\) lên \(0.76\)), cho thấy sự phụ thuộc vào nợ hoặc huy động vốn tăng lên trong giai đoạn này.
Kỹ thuật vẽ các biểu đồ đã giải thích ở Phần1
ta_visual <- ta_clean1 %>%
mutate(
loi_nhuan_sau_thue = loi_nhuan_sau_thue / 1000000000,
cfo_tong = cfo_tong / 1000000000,
DongTienTuDo = DongTienTuDo / 1000000000
)
format_number_m <- function(x) {
format(round(x, 0), big.mark = ".", scientific = FALSE)
}
# Đồ thị 1: Xu hướng Lợi nhuận sau thuế (LNST)
p1 <- ggplot(ta_visual, aes(x = year, y = loi_nhuan_sau_thue)) +
geom_line(color = "blue", linewidth = 1) +
geom_point(color = "blue", size = 3) +
geom_text(aes(label = format_number_m(loi_nhuan_sau_thue)), vjust = -1.2, size = 3.5) +
labs(title = "Xu hướng Lợi nhuận sau thuế (LNST)",
subtitle = "Tăng trưởng liên tục qua các năm",
x = " ", y = "Tỷ đồng") +
scale_y_continuous(labels = scales::comma) +
scale_x_continuous(breaks = NULL) +
theme_minimal()
# Đồ thị 2: Xu hướng Dòng tiền từ HĐKD (CFO)
p2 <- ggplot(ta_visual, aes(x = year, y = cfo_tong)) +
geom_line(color = "darkgreen", linewidth = 1) +
geom_point(color = "darkgreen", size = 3) +
geom_hline(yintercept = 0, linetype = "dashed", color = "red") +
geom_text(aes(label = format_number_m(cfo_tong)), vjust = -1.2, size = 3.5) +
labs(title = "Xu hướng (CFO)",
subtitle = "Biến động mạnh và âm nặng",
x = " ", y = "Tỷ đồng") +
scale_y_continuous(labels = scales::comma) +
scale_x_continuous(breaks = NULL) +
theme_minimal()
# Đồ thị 3: Xu hướng Dòng tiền Tự do (FCF)
p3 <- ggplot(ta_visual, aes(x = year, y = DongTienTuDo)) +
geom_line(color = "purple", linewidth = 1) +
geom_point(color = "purple", size = 3) +
geom_hline(yintercept = 0, linetype = "dashed", color = "red") +
geom_text(aes(label = format_number_m(DongTienTuDo)), vjust = -1.2, size = 3.5) +
labs(title = "Xu hướng Dòng tiền Tự do (FCF)",
subtitle = "FCF = CFO - Chi mua TSCD (CAPEX)",
x = "Năm", y = "Tỷ đồng") +
scale_y_continuous(labels = scales::comma) +
scale_x_continuous(breaks = ta_clean1$year) +
theme_minimal()
# Kết hợp 3 đồ thị
(p1 + p2) / p3 + plot_annotation(title = "TỔNG QUAN LỢI NHUẬN VÀ DÒNG TIỀN")
Xu hướng Lợi nhuận sau thuế (LNST): Đồ thị này thể hiện một bức tranh
rất tích cực về mặt kế toán. Lợi nhuận của công ty tăng trưởng liên tục
và mạnh mẽ suốt 10 năm, từ khoảng 92 nghìn tỷ lên đến 320 nghìn tỷ. Điều
này cho thấy khả năng mở rộng thị phần và kiểm soát chi phí (trên sổ
sách) rất tốt.
Xu hướng Dòng tiền từ HĐKD (CFO): Đồ thị này cho thấy một thực tế hoàn toàn trái ngược. Dòng tiền (tiền thật) từ hoạt động kinh doanh cốt lõi rất bất ổn. Đặc biệt, năm 2023, công ty rơi vào khủng hoảng thanh khoản nghiêm trọng khi CFO âm tới 30 nghìn tỷ, mặc dù lợi nhuận sổ sách (Đồ thị 1) vẫn báo lãi rất cao. Đây là dấu hiệu “lãi giả, lỗ thật” (lãi trên giấy nhưng không thu được tiền). Rất may mắn, CFO đã phục hồi mạnh mẽ vào năm 2024.
Xu hướng Dòng tiền Tự do (FCF): Dòng tiền tự do (FCF = CFO - Chi mua TSCD) là số tiền thật sự còn lại sau khi đã chi cho đầu tư tài sản. Đây là tiền để trả nợ, chia cổ tức. Đồ thị cho thấy FCF liên tục âm trong nhiều năm (đỉnh điểm là 2023), nghĩa là công ty không tạo đủ tiền từ kinh doanh để tài trợ cho việc mở rộng, mà phải dựa vào vốn vay hoặc vốn chủ sở hữu bên ngoài.
ta_visual_quality <- ta_clean1 %>%
mutate(
loi_nhuan_sau_thue = loi_nhuan_sau_thue / 1000000000,
cfo_tong = cfo_tong / 1000000000
)
df_gap <- ta_visual_quality %>%
select(year, loi_nhuan_sau_thue, cfo_tong) %>%
pivot_longer(c(loi_nhuan_sau_thue, cfo_tong), names_to = "ChiTieu", values_to = "GiaTri")
# Đồ thị 4: Chênh lệch LNST & CFO
p4 <- ggplot(df_gap, aes(x = factor(year), y = GiaTri, color = ChiTieu, group = ChiTieu)) + # Đổi year sang factor
geom_line(linewidth = 1.2) +
geom_point(size = 3) +
geom_hline(yintercept = 0, linetype = "dashed", color = "black") + # Đổi màu đường 0
# Đổi nhãn và màu sắc cho ChiTieu
scale_color_manual(values = c("cfo_tong" = "darkgreen", "loi_nhuan_sau_thue" = "blue"),
labels = c("cfo_tong" = "Dòng tiền (CFO)", "loi_nhuan_sau_thue" = "Lợi nhuận (LNST)")) +
labs(title = "Chênh lệch LNST & CFO",
subtitle = "Khoảng cách lớn năm 2023",
x = "Năm", y = "Tỷ đồng", color = "Chỉ tiêu") +
# Định dạng trục Y và Theme
scale_y_continuous(labels = scales::comma) +
theme_minimal() +
theme(legend.position = "bottom",
# Đảm bảo nhãn trục X (Năm) hiển thị rõ ràng
axis.text.x = element_text(angle = 0, hjust = 0.5))
# Đồ thị 5: Phân phối LNST (Đường cong màu xanh dương trong cột)
p5 <- ggplot(ta_visual_quality, aes(x = loi_nhuan_sau_thue)) +
# Biểu đồ Histogram (Cột)
geom_histogram(aes(y = after_stat(density)), bins = 5,
fill = "lightblue", color = "black") + # Viền màu đen cho cột
# Đường cong mật độ (Density)
geom_density(color = "blue", fill = "blue", alpha = 0.2, linewidth = 1.2) + # Đổi màu đường cong thành xanh dương
labs(title = "Phân phối LNST",
subtitle = "Lệch phải, thấp & trung bình",
x = "Lợi nhuận sau thuế (Tỷ đồng)", y = "Mật độ") +
# Định dạng trục X (tạm thời sử dụng labels::comma)
scale_x_continuous(labels = scales::comma) +
theme_minimal()
# Kết hợp 2 đồ thị
p4 + p5 + plot_annotation(title = "PHÂN TÍCH CHẤT LƯỢNG LỢI NHUẬN")
Chênh lệch LNST & CFO: Đây là đồ thị quan trọng nhất để đánh giá
chất lượng lợi nhuận. Khoảng cách giữa đường màu xanh (Lợi nhuận) và
đường màu xanh lá (Dòng tiền) chính là các khoản “dồn tích” (accruals) -
tức là lợi nhuận chưa thành tiền. Giai đoạn 2015-2018, hai đường này khá
gần nhau (chất lượng lợi nhuận tốt). Tuy nhiên, năm 2019, 2020 và đặc
biệt là 2023, khoảng cách này giãn ra cực lớn. Điều này khẳng định lợi
nhuận năm 2023 chủ yếu đến từ các khoản phải thu hoặc hàng tồn kho (chưa
bán được), không phải tiền mặt, rủi ro cực cao.
Phân phối LNST: Đồ thị bên phải cho thấy trong 10 năm qua, phần lớn số năm công ty đạt mức lợi nhuận ở khoảng thấp và trung bình (dưới 200 nghìn tỷ). Các năm lợi nhuận “siêu cao” (như 2023, 2024) là các giá trị ngoại lai, cho thấy sự tăng trưởng bứt phá trong thời gian gần đây.
# Đồ thị 6: Dòng tiền HĐKD (CFO)
p6 <- ggplot(ta_clean1, aes(x = year, y = cfo_tong)) +
geom_col(aes(fill = cfo_tong > 0), show.legend = FALSE) +
scale_fill_manual(values = c("TRUE" = "darkgreen", "FALSE" = "red")) +
geom_hline(yintercept = 0) +
labs(title = "Dòng tiền HĐ Kinh doanh (CFO)",
subtitle = "Tạo tiền/Mất tiền từ hoạt động cốt lõi",
x = "Năm", y = "Tỷ đồng") +
scale_y_continuous(labels = scales::comma) +
scale_x_continuous(breaks = ta_clean1$year) +
theme_minimal()
# Đồ thị 7: Dòng tiền Đầu tư (CFI)
p7 <- ggplot(ta_clean1, aes(x = year, y = cfi_tong)) +
geom_col(aes(fill = cfi_tong > 0), show.legend = FALSE) +
scale_fill_manual(values = c("TRUE" = "darkgreen", "FALSE" = "orange")) +
geom_hline(yintercept = 0) +
labs(title = "Dòng tiền Đầu tư (CFI)",
subtitle = "Màu cam: Đang mở rộng đầu tư (Âm)",
x = "Năm", y = "Tỷ đồng") +
scale_y_continuous(labels = scales::comma) +
scale_x_continuous(breaks = ta_clean1$year) +
theme_minimal()
# Đồ thị 8: Dòng tiền Tài trợ (CFF)
p8 <- ggplot(ta_clean1, aes(x = year, y = cff_tong)) +
geom_col(aes(fill = cff_tong > 0), show.legend = FALSE) +
scale_fill_manual(values = c("TRUE" = "blue", "FALSE" = "purple")) +
geom_hline(yintercept = 0) +
labs(title = "Dòng tiền Tài trợ (CFF)",
subtitle = "Màu xanh: Huy động vốn (Dương) | Màu tím: Trả nợ/Cổ tức (Âm)",
x = "Năm", y = "Tỷ đồng") +
scale_y_continuous(labels = scales::comma) +
scale_x_continuous(breaks = ta_clean1$year) +
theme_minimal()
# Kết hợp 3 đồ thị
p6 / p7 / p8 + plot_annotation(title = "PHÂN TÍCH CẤU TRÚC 3 DÒNG TIỀN (CFO, CFI, CFF)")
Dòng tiền HĐ Kinh doanh (CFO): Như đã thấy, dòng tiền kinh doanh (màu
xanh lá) là nguồn sống. Việc nó chuyển sang màu đỏ (âm) năm 2023 là tín
hiệu nguy hiểm nhất cho thấy hoạt động cốt lõi không tạo ra tiền.
Dòng tiền Đầu tư (CFI): Dòng tiền đầu tư liên tục âm (màu cam) trong suốt 10 năm. Đây là đặc điểm của một công ty đang trong giai đoạn tăng trưởng, mở rộng mạnh mẽ. Công ty liên tục chi tiền để mua tài sản, đầu tư…
Dòng tiền Tài trợ (CFF): Dòng tiền tài trợ cho thấy công ty dùng tiền từ đâu để bù đắp cho thâm hụt.
Những năm CFF dương (xanh) như 2017: Công ty đang huy động vốn mạnh (đi vay nợ hoặc phát hành cổ phiếu) để bù đắp cho việc CFO yếu và CFI âm.
Những năm CFF âm (tím) như 2021, 2022: Công ty dùng tiền (thường là từ CFO) để trả nợ gốc hoặc chia cổ tức.
Kết luận: Công ty đang trong mô hình “Tăng trưởng > Đầu tư > Huy động vốn”. Năm 2023 là năm điển hình: Kinh doanh cạn tiền (CFO âm), vẫn phải đầu tư (CFI âm), buộc phải đi vay thêm (CFF dương - dù nhỏ) để tồn tại.
# Đồ thị 9: Biến động Khoản phải thu
p9 <- ggplot(ta_clean1, aes(x = year, y = bien_dong_phai_thu)) +
geom_col(aes(fill = bien_dong_phai_thu > 0), show.legend = FALSE) +
geom_hline(yintercept = 0) +
scale_fill_manual(values = c("TRUE" = "darkgreen", "FALSE" = "red")) +
labs(title = "Biến động Khoản phải thu",
subtitle = "Màu đỏ (Âm): Tăng phải thu (Bán chịu, đọng vốn)",
x = "Năm", y = "Tỷ đồng") +
scale_y_continuous(labels = scales::comma) +
scale_x_continuous(breaks = ta_clean1$year) +
theme_minimal()
# Đồ thị 10: Biến động Hàng tồn kho
p10 <- ggplot(ta_clean1, aes(x = year, y = bien_dong_ton_kho)) +
geom_col(aes(fill = bien_dong_ton_kho > 0), show.legend = FALSE) +
geom_hline(yintercept = 0) +
scale_fill_manual(values = c("TRUE" = "darkgreen", "FALSE" = "red")) +
labs(title = "Biến động Hàng tồn kho",
subtitle = "Màu đỏ (Âm): Tăng tồn kho (Ôm hàng, đọng vốn)",
x = "Năm", y = "Tỷ đồng") +
scale_y_continuous(labels = scales::comma) +
scale_x_continuous(breaks = ta_clean1$year) +
theme_minimal()
# Đồ thị 11: Biến động Khoản phải trả
p11 <- ggplot(ta_clean1, aes(x = year, y = bien_dong_phai_tra)) +
geom_col(aes(fill = bien_dong_phai_tra > 0), show.legend = FALSE) +
geom_hline(yintercept = 0) +
scale_fill_manual(values = c("TRUE" = "darkgreen", "FALSE" = "red")) +
labs(title = "Biến động Khoản phải trả",
subtitle = "Màu xanh (Dương): Tăng phải trả (Chiếm dụng vốn N.C.C)",
x = "Năm", y = "Tỷ đồng") +
scale_y_continuous(labels = scales::comma) +
scale_x_continuous(breaks = ta_clean1$year) +
theme_minimal()
# Kết hợp 3 đồ thị
p9 / p10 / p11 + plot_annotation(title = "PHÂN TÍCH VỐN LƯU ĐỘNG (NGUYÊN NHÂN BIẾN ĐỘNG CFO)")
Biến động Khoản phải thu: Màu đỏ (âm) nghĩa là công ty đang tăng cường
bán chịu, bị khách hàng chiếm dụng vốn. Các năm 2019, 2020 và đặc biệt
là 2024 (âm) cho thấy công ty bán được hàng nhưng không thu được
tiền.
Biến động Hàng tồn kho: Màu đỏ (âm) nghĩa là công ty nhập hàng về kho hoặc sản xuất ra nhưng chưa bán được. Năm 2023 là đỉnh điểm (âm sâu), cho thấy tiền của công ty đã “biến” thành hàng tồn kho, nằm bất động. Đây là nguyên nhân chính gây ra CFO âm năm 2023.
Biến động Khoản phải trả: Màu xanh (dương) nghĩa là công ty chiếm dụng được vốn của nhà cung cấp (mua hàng nhưng chưa trả tiền). Đây là một nguồn tài trợ. Tuy nhiên, năm 2023, khoản này lại âm (màu đỏ), nghĩa là công ty phải trả tiền cho nhà cung cấp, càng làm cạn kiệt dòng tiền.
Khủng hoảng CFO năm 2023 được giải thích rõ ràng: Công ty dùng tiền để trả nhà cung cấp (Phải trả âm), trong khi tiền lại bị kẹt trong Tồn kho (Tồn kho âm sâu).
ta_visual <- ta_clean1 %>%
mutate(
year_factor = factor(year),
cfi_tong = cfi_tong / 1000000000,
chi_mua_tscd = chi_mua_tscd / 1000000000,
loi_nhuan_sau_thue = loi_nhuan_sau_thue / 1000000000,
DongTienTuDo = DongTienTuDo / 1000000000
)
# Đồ thị 12: Dòng tiền đầu tư (CFI) và Chi mua TSCD (CAPEX)
p12 <- ggplot(ta_visual, aes(x = year_factor)) + # Dùng year_factor
geom_line(aes(y = cfi_tong, group = 1, color = "Tổng CFI"), linewidth = 1.2) +
geom_col(aes(y = chi_mua_tscd, fill = "Chi mua TSCD (CAPEX)"), alpha = 0.7) +
labs(title = "Dòng tiền Đầu tư (CFI) và CAPEX",
subtitle = "Chi mua TSCD là hạng mục chính gây âm CFI",
x = "Năm", y = "Tỷ đồng") +
scale_y_continuous(labels = scales::comma) +
scale_color_manual(name = "", values = c("Tổng CFI" = "orange")) +
scale_fill_manual(name = "", values = c("Chi mua TSCD (CAPEX)" = "darkred")) +
theme_minimal() +
theme(legend.position = "bottom",
axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1))
# Đồ thị 13: Lợi nhuận và Dòng tiền tự do
p13 <- ggplot(ta_visual, aes(x = year_factor)) + # Dùng year_factor
geom_line(aes(y = loi_nhuan_sau_thue, group = 1, color = "Lợi nhuận (LNST)"),
linewidth = 1.2) +
geom_line(aes(y = DongTienTuDo, group = 1, color = "Dòng tiền Tự do (FCF)"),
linewidth = 1.2, linetype = "dashed") +
geom_hline(yintercept = 0, linetype = "dotted") +
labs(title = "LN & Dòng tiền Tự do",
subtitle = "Bất cân xứng",
x = "Năm", y = "Tỷ đồng") +
scale_y_continuous(labels = scales::comma) +
scale_color_manual(name = "Chỉ tiêu",
values = c("Lợi nhuận (LNST)" = "blue", "Dòng tiền Tự do (FCF)" = "purple")) +
theme_minimal() +
theme(legend.position = "bottom",
axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1))
# Kết hợp 2 đồ thị
p12 + p13 + plot_annotation(title = "CHIẾN LƯỢC ĐẦU TƯ")
Dòng tiền Đầu tư (CFI) và CAPEX: Đồ thị bên trái xác nhận chi_mua_tscd
(CAPEX, các cột màu xám) là nguyên nhân chính khiến Dòng tiền Đầu tư
(CFI, đường màu cam) liên tục âm. Công ty đang theo đuổi chiến lược thâm
dụng vốn (capital intensive), chi rất nhiều tiền cho nhà xưởng, máy móc
để mở rộng.
LN & Dòng tiền Tự do (FCF): Đồ thị bên phải so sánh lợi nhuận (đường xám) với dòng tiền tự do (đường tím nét đứt). Mặc dù lợi nhuận tăng đều, FCF lại liên tục nằm dưới mức 0 (âm). Điều này có nghĩa là, toàn bộ lợi nhuận kiếm được (và thậm chí còn nhiều hơn) đều bị “đốt” vào việc tái đầu tư (CAPEX). Công ty không còn lại tiền mặt tự do để trả cho cổ đông hoặc chủ nợ.
# Chuẩn bị dữ liệu
df_vay <- ta_clean1 %>%
select(year, vay_moi, tra_no_goc) %>%
mutate(tra_no_goc = abs(tra_no_goc)) %>% # Chuyển số âm thành dương để dễ vẽ
pivot_longer(cols = c(vay_moi, tra_no_goc), names_to = "Loai", values_to = "GiaTri")
# Đồ thị 14: Vay mới vs Trả nợ gốc
p14 <- ggplot(df_vay, aes(x = year, y = GiaTri, fill = Loai)) +
geom_col(position = "dodge") +
scale_fill_manual(values = c("vay_moi" = "blue", "tra_no_goc" = "gray"),
labels = c("Trả nợ gốc", "Vay mới")) +
labs(title = "Vay mới vs. Trả nợ gốc",
subtitle = "Liên tục vay nợ quy mô lớn",
x = "Năm", y = "Tỷ đồng", fill = "Hoạt động") +
scale_y_continuous(labels = scales::comma) +
scale_x_continuous(breaks = ta_clean1$year) +
theme_minimal() + theme(legend.position = "bottom")
# Đồ thị 15: Vay ròng (Vay mới - Trả nợ)
p15 <- ggplot(ta_clean1, aes(x = year, y = VayRong)) +
geom_col(aes(fill = VayRong > 0), show.legend = FALSE) +
geom_hline(yintercept = 10) +
scale_fill_manual(values = c("TRUE" = "blue", "FALSE" = "purple")) +
labs(title = "Vay ròng",
subtitle = "Xanh: Vay thêm ròng | Tím: Trả nợ ròng",
x = "Năm", y = "Tỷ đồng") +
scale_y_continuous(labels = scales::comma) +
scale_x_continuous(breaks = ta_clean1$year) +
theme_minimal()
# Đồ thị 16: Phân loại Chính sách Nợ
p16 <- ggplot(ta_clean1, aes(x = ChinhSachNo, fill = ChinhSachNo)) +
geom_bar(show.legend = FALSE) +
geom_text(stat='count', aes(label=after_stat(count)), vjust=1) +
labs(title = "Số năm theo Chính sách Nợ",
x = "Chính sách Nợ", y = "Số năm") +
theme_minimal()
# Kết hợp 3 đồ thị
(p14 / p15) + p16 + plot_annotation(title = "PHÂN TÍCH HOẠT ĐỘNG TÀI TRỢ (NỢ)")
Vay mới vs. Trả nợ gốc: Đồ thị 14 cho thấy quy mô vay và trả nợ của công
ty là rất lớn, lên đến hàng trăm nghìn tỷ. Công ty có vẻ đang thực hiện
chiến lược “đảo nợ” (rollover debt) - vay khoản mới để trả khoản cũ,
đồng thời vay thêm để mở rộng.
Vay ròng: Đồ thị 15 là kết quả thực.
Các năm màu tím (âm) như 2020, 2021: Công ty trả nợ ròng (trả nhiều hơn vay). Đây là những năm CFO tốt, công ty có tiền để giảm đòn bẩy.
Các năm màu xanh (dương) như 2024: Công ty vay ròng (vay nhiều hơn trả).
Chính sách Nợ: Đồ thị 16 tổng kết lại, công ty có 6 năm trả nợ ròng và 2 năm vay thêm ròng (và 2 năm cân bằng). Mặc dù có xu hướng trả nợ, nhưng khi cần vay thì công ty vay với quy mô rất lớn.
ta_visual <- ta_clean1 %>%
mutate(
year_factor = factor(year) )
# Đồ thị 17: Tỷ số ROA (Lợi nhuận/Tài sản)
p17 <- ggplot(ta_visual, aes(x = year_factor, y = ROA)) +
geom_line(aes(group = 1), color = "darkred", linewidth = 1) +
geom_point(color = "darkred", size = 2) +
labs(title = "Tỷ số sinh lời trên ROA",
x = "Năm", y = "ROA") +
scale_y_continuous(labels = scales::percent) +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1)
)
# Đồ thị 18: Tỷ số ROS (Lợi nhuận/Doanh thu - Giả định)
p18 <- ggplot(ta_visual, aes(x = year_factor, y = ROS)) + # Dùng year_factor
geom_line(aes(group = 1), color = "darkblue", linewidth = 1) +
geom_point(color = "darkblue", size = 2) +
labs(title = "Tỷ số sinh lời trên ROS",
x = "Năm", y = "ROS") +
scale_y_continuous(labels = scales::percent) +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1)
)
# Đồ thị 19: Tỷ số Thanh khoản Hiện hành (Giả định)
p19 <- ggplot(ta_visual, aes(x = year_factor, y = TySo_ThanhKhoanHienHanh))+
geom_line(aes(group = 1), color = "darkgreen", linewidth = 1) +
geom_point(color = "darkgreen", size = 2) +
geom_hline(yintercept = 1, linetype = "dashed", color = "red") +
labs(title = "Tỷ số thanh khoản",
subtitle = "Dưới 1 (màu đỏ) là rủi ro thanh khoản",
x = "Năm", y = "Tỷ số") +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1)
)
# Đồ thị 20: Tỷ số Nợ (Giả định)
p20 <- ggplot(ta_visual, aes(x = year_factor, y = TySo_No)) + # Dùng year_factor
geom_line(aes(group = 1), color = "purple", linewidth = 1) +
geom_point(color = "purple", size = 2) +
labs(title = "Tỷ số nợ",
x = "Năm", y = "Tỷ số") +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1)
)
# Kết hợp 4 đồ thị
(p17 + p18) / (p19 + p20) +
plot_annotation(title = "BẢNG ĐIỂU KHIỂN KẾT QUẢ TÀI CHÍNH")
Tỷ số Sinh lời trên Tài sản (ROA): Cho thấy hiệu quả sử dụng tài sản.
ROA biến động nhưng có xu hướng tăng mạnh về cuối (2023-2024), cho thấy
dù công ty đầu tư nhiều tài sản (CFI âm), nhưng lợi nhuận (LNST) tăng
còn nhanh hơn.
Tỷ số Sinh lời trên Doanh thu (ROS): Biên lợi nhuận ròng. Tỷ số này biến động mạnh, đặc biệt sụt giảm năm 2021 và 2023, cho thấy hiệu quả quản lý chi phí/giá bán không ổn định.
Tỷ số Thanh khoản: Đây là tỷ số cảnh báo. Khi nó rơi xuống dưới 1 (đường đỏ) vào các năm 2019, 2020 và đặc biệt là 2023 (gần như bằng 0), nó cho thấy tài sản ngắn hạn không đủ để trả các khoản nợ ngắn hạn. Điều này khớp hoàn hảo với khủng hoảng CFO âm năm 2023. Năm 2021 tỷ số này tăng vọt bất thường, cần xem xét lại dữ liệu năm đó.
Tỷ số Nợ: Cho thấy gánh nặng nợ. Tỷ số này tăng vọt vào năm 2020, cho thấy nợ tăng nhanh hơn lợi nhuận. Điều này cũng khớp với việc CFF dương (vay thêm ròng) trong những năm đó.