library(readr)
library(readxl)
library(tidyverse)
library(lubridate)
library(scales)
library(ggplot2)
library(dplyr)
library(knitr)
library(kableExtra)
library(DT)
library(janitor)
library(gt)
library(skimr)
library(patchwork)
library(showtext)
library(reshape2)
library(broom)
library(ggcorrplot)
library(gridExtra)
library(grid)
library(waterfalls)
options(knitr.kable.NA = "")
options(scipen = 999)kd %>%
slice(1:20) %>%
kable(format = "latex", booktabs = TRUE,
caption = "20 dòng đầu của bộ dữ liệu Marketing Campaign Performance Dataset") %>%
kable_styling(
latex_options = c("hold_position", "scale_down"),
position = "center" )cau_truc <- data.frame(
`Ten bien` = names(kd),
`Kieu du lieu` = sapply(kd, function(x) class(x)[1]),
`Gia tri dau` = sapply(kd, function(x) as.character(x[1])),
check.names = FALSE)
kable(cau_truc,
caption = "Cấu trúc dữ liệu",
row.names = FALSE,
col.names = c("Tên biến", "Kiểu dữ liệu", "Giá trị đầu tiên")) %>%
kable_styling(
latex_options = c("hold_position", "scale_down"))| Tên biến | Kiểu dữ liệu | Giá trị đầu tiên |
|---|---|---|
| Company | character | Innovate Industries |
| Campaign_Type | character | |
| Target_Audience | character | Men 18-24 |
| Duration | character | 30 days |
| Channel_Used | character | Google Ads |
| Conversion_Rate | numeric | 0.04 |
| Acquisition_Cost | character | $16,174.00 |
| ROI | numeric | 6.29 |
| Location | character | Chicago |
| Language | character | Spanish |
| Clicks | numeric | 506 |
| Impressions | numeric | 1922 |
| Engagement_Score | numeric | 6 |
| Customer_Segment | character | Health & Wellness |
| Date | character | 01/01/2021 |
[1] "company" "campaign_type" "target_audience" "duration"
[5] "channel_used" "conversion_rate" "acquisition_cost" "roi"
[9] "location" "language" "clicks" "impressions"
[13] "engagement_score" "customer_segment" "date"
[1] 200000 15
| Name | kd |
| Number of rows | 200000 |
| Number of columns | 15 |
| _______________________ | |
| Column type frequency: | |
| character | 10 |
| numeric | 5 |
| ________________________ | |
| Group variables | None |
Variable type: character
| skim_variable | n_missing | complete_rate | min | max | empty | n_unique | whitespace |
|---|---|---|---|---|---|---|---|
| company | 0 | 1 | 8 | 19 | 0 | 5 | 0 |
| campaign_type | 0 | 1 | 5 | 12 | 0 | 5 | 0 |
| target_audience | 0 | 1 | 8 | 11 | 0 | 5 | 0 |
| duration | 0 | 1 | 7 | 7 | 0 | 4 | 0 |
| channel_used | 0 | 1 | 5 | 10 | 0 | 6 | 0 |
| acquisition_cost | 0 | 1 | 9 | 10 | 0 | 15001 | 0 |
| location | 0 | 1 | 5 | 11 | 0 | 5 | 0 |
| language | 0 | 1 | 6 | 8 | 0 | 5 | 0 |
| customer_segment | 0 | 1 | 7 | 19 | 0 | 5 | 0 |
| date | 0 | 1 | 10 | 10 | 0 | 365 | 0 |
Variable type: numeric
| skim_variable | n_missing | complete_rate | mean | sd | p0 | p25 | p50 | p75 | p100 | hist |
|---|---|---|---|---|---|---|---|---|---|---|
| conversion_rate | 0 | 1 | 0.08 | 0.04 | 0.01 | 0.05 | 0.08 | 0.12 | 0.15 | ▆▇▇▇▆ |
| roi | 0 | 1 | 5.00 | 1.73 | 2.00 | 3.50 | 5.01 | 6.51 | 8.00 | ▇▇▇▇▇ |
| clicks | 0 | 1 | 549.77 | 260.02 | 100.00 | 325.00 | 550.00 | 775.00 | 1000.00 | ▇▇▇▇▇ |
| impressions | 0 | 1 | 5507.30 | 2596.86 | 1000.00 | 3266.00 | 5517.50 | 7753.00 | 10000.00 | ▇▇▇▇▇ |
| engagement_score | 0 | 1 | 5.49 | 2.87 | 1.00 | 3.00 | 5.00 | 8.00 | 10.00 | ▇▇▇▇▇ |
[1] 0
company campaign_type target_audience duration
0 0 0 0
channel_used conversion_rate acquisition_cost roi
0 0 0 0
location language clicks impressions
0 0 0 0
engagement_score customer_segment date
0 0 0
[1] 0
freq_company <- kd %>%
count(company, sort = TRUE)
kable(freq_company, caption = "Tần suất theo Company",
col.names = c("Công ty", "Số lượng"))| Công ty | Số lượng |
|---|---|
| TechCorp | 40237 |
| Alpha Innovations | 40051 |
| DataTech Solutions | 40012 |
| NexGen Systems | 39991 |
| Innovate Industries | 39709 |
freq_campaign_type <- kd %>%
count(campaign_type, sort = TRUE)
kable(freq_campaign_type, caption = "Tần suất theo loại chiến dịch",
col.names = c("Loại chiến dịch", "Số lượng chiến dịch"))| Loại chiến dịch | Số lượng chiến dịch |
|---|---|
| Influencer | 40169 |
| Search | 40157 |
| Display | 39987 |
| 39870 | |
| Social Media | 39817 |
freq_language <- kd %>%
count(language, sort = TRUE)
kable(freq_language, caption = "Tần suất theo ngôn ngữ quảng cáo",
col.names = c("Ngôn ngữ", "Số lượng"))| Ngôn ngữ | Số lượng |
|---|---|
| Mandarin | 40255 |
| Spanish | 40102 |
| German | 39983 |
| English | 39896 |
| French | 39764 |
freq_target_audience <- kd %>%
count(target_audience, sort = TRUE)
kable(freq_target_audience, caption = "Tần suất theo đối tượng nghiên cứu",
col.names = c("Đối tượng nghiên cứu", "Số lượng"))| Đối tượng nghiên cứu | Số lượng |
|---|---|
| Men 18-24 | 40258 |
| Men 25-34 | 40023 |
| All Ages | 40019 |
| Women 25-34 | 40013 |
| Women 35-44 | 39687 |
freq_location <- kd %>%
count(location, sort = TRUE)
kable(freq_location, caption = "Tần suất theo địa điểm triển khai quảng cáo",
col.names = c("Địa điểm", "Số lượng"))| Địa điểm | Số lượng |
|---|---|
| Miami | 40269 |
| New York | 40024 |
| Chicago | 40010 |
| Los Angeles | 39947 |
| Houston | 39750 |
freq_customer_segment <- kd %>%
count(customer_segment, sort = TRUE)
kable(freq_customer_segment, caption = "Tần suất theo phân khúc khách hàng",
col.names = c("Nhóm khách hàng", "Số lượng"))| Nhóm khách hàng | Số lượng |
|---|---|
| Foodies | 40208 |
| Tech Enthusiasts | 40151 |
| Outdoor Adventurers | 40011 |
| Health & Wellness | 39888 |
| Fashionistas | 39742 |
kd$date <- as.Date(kd$date, format = "%d/%m/%Y")
kd$acquisition_cost <- as.numeric(gsub("[\\$,]", "", kd$acquisition_cost))
kd$duration <- as.numeric(gsub(" days", "", kd$duration))
cau_truc_moi <- data.frame(
`Tên biến` = names(kd),
`Kiểu dữ liệu` = sapply(kd, function(x) class(x)[1]),
`Giá trị đầu` = sapply(kd, function(x) as.character(x[1])),
check.names = FALSE,
row.names = NULL)
kable(cau_truc_moi, caption = "Cấu trúc dữ liệu sau khi chuyển đổi kiểu dữ liệu",
col.names = c("Tên biến", "Kiểu dữ liệu", "Giá trị đầu tiên")) %>%
kable_styling(
latex_options = c("hold_position", "scale_down"))| Tên biến | Kiểu dữ liệu | Giá trị đầu tiên |
|---|---|---|
| company | character | Innovate Industries |
| campaign_type | character | |
| target_audience | character | Men 18-24 |
| duration | numeric | 30 |
| channel_used | character | Google Ads |
| conversion_rate | numeric | 0.04 |
| acquisition_cost | numeric | 16174 |
| roi | numeric | 6.29 |
| location | character | Chicago |
| language | character | Spanish |
| clicks | numeric | 506 |
| impressions | numeric | 1922 |
| engagement_score | numeric | 6 |
| customer_segment | character | Health & Wellness |
| date | Date | 2021-01-01 |
q <- quantile(kd$engagement_score, probs = c(0.25, 0.75))
kd <- kd %>% mutate(
engagement_level = cut(
engagement_score,
breaks = c(-Inf, q[1], q[2], Inf),
labels = c("Thấp", "Trung bình", "Cao"),
right = TRUE ))
kd %>%
select(engagement_score, engagement_level) %>%
distinct() %>%
arrange(engagement_score) %>%
kable(
caption = "Bảng: Mã hóa mức độ tương tác (engagement_level)",
col.names = c("Engagement Score", "Engagement Level"))| Engagement Score | Engagement Level |
|---|---|
| 1 | Thấp |
| 2 | Thấp |
| 3 | Thấp |
| 4 | Trung bình |
| 5 | Trung bình |
| 6 | Trung bình |
| 7 | Trung bình |
| 8 | Trung bình |
| 9 | Cao |
| 10 | Cao |
kd <- kd %>% mutate(
age_group = case_when(
grepl("18-24", target_audience) ~ "18-24",
grepl("25-34", target_audience) ~ "25-34",
grepl("35-44", target_audience) ~ "35-44",
TRUE ~ "All" ))
kd %>%
select(target_audience, age_group) %>%
distinct() %>%
arrange(age_group) %>%
kable(
caption = "Nhóm tuổi từ đối tượng nghiên cứu (target_audience)",
col.names = c("Target Audience", "Age Group"))| Target Audience | Age Group |
|---|---|
| Men 18-24 | 18-24 |
| Men 25-34 | 25-34 |
| Women 25-34 | 25-34 |
| Women 35-44 | 35-44 |
| All Ages | All |
kd <- kd %>% mutate(
duration_level = case_when(
duration == 15 ~ "Rất ngắn",
duration == 30 ~ "Ngắn",
duration == 45 ~ "Trung bình",
duration == 60 ~ "Dài",
TRUE ~ NA_character_ ))
kd %>%
select(duration, duration_level) %>%
distinct() %>%
arrange(duration) %>%
kable(
caption = "Cấp độ thời lượng chiến dịch (duration_level)",
col.names = c("Duration (days)", "Duration Level"))| Duration (days) | Duration Level |
|---|---|
| 15 | Rất ngắn |
| 30 | Ngắn |
| 45 | Trung bình |
| 60 | Dài |
q1 <- quantile(kd$clicks, probs = c(0.25, 0.75), na.rm = TRUE)
kd <- kd %>% mutate(
clicks_level = cut(
clicks,
breaks = c(-Inf, q1[1], q1[2], Inf),
labels = c("Thấp", "Trung bình", "Cao"),
right = TRUE ))
kd %>%
count(clicks_level) %>%
arrange(match(clicks_level, c("Thấp", "Trung bình", "Cao"))) %>%
distinct() %>%
kable(caption = "Cấp độ số lần nhấp (clicks) theo phân vị",
col.names = c("Clicks_level", "Số lượng quan sát"))| Clicks_level | Số lượng quan sát |
|---|---|
| Thấp | 50142 |
| Trung bình | 99987 |
| Cao | 49871 |
kd <- kd %>%
add_count(language, name = "Frequency") %>%
mutate(
Language_Level = case_when(
Frequency > quantile(Frequency, 0.75, na.rm = TRUE) ~ "Phổ biến cao",
Frequency > quantile(Frequency, 0.25, na.rm = TRUE) ~ "Phổ biến trung bình",
TRUE ~ "Ít phổ biến"))
kd %>%
count(Language_Level, name = "Số lượng") %>%
distinct() %>%
arrange(factor(Language_Level, levels = c(
"Ít phổ biến", "Phổ biến trung bình", "Phổ biến cao"))) %>%
kable(caption = "Mức độ phổ biến của ngôn ngữ quảng cáo theo phân vị tần suất",
col.names = c("Language_Level", "Số lượng"))| Language_Level | Số lượng |
|---|---|
| Ít phổ biến | 79660 |
| Phổ biến trung bình | 80085 |
| Phổ biến cao | 40255 |
\[CTR = \frac{clicks}{impressions}\]
kd <- kd %>%
mutate(CTR = ifelse(impressions > 0, clicks / impressions, NA))
kd %>%
select(clicks, impressions, CTR) %>%
head(10) %>%
arrange(CTR) %>%
kable(caption = "Tỷ lệ người xem quảng cáo khi đã nhấp chuột vào (CTR)",
col.names = c("Clicks", "Impressions", "CTR"))| Clicks | Impressions | CTR |
|---|---|---|
| 116 | 7523 | 0.0154194 |
| 100 | 1643 | 0.0608643 |
| 584 | 7698 | 0.0758639 |
| 624 | 7854 | 0.0794500 |
| 379 | 4201 | 0.0902166 |
| 817 | 8749 | 0.0933821 |
| 217 | 1820 | 0.1192308 |
| 642 | 3856 | 0.1664938 |
| 506 | 1922 | 0.2632674 |
| 861 | 1754 | 0.4908780 |
\[CPC = \frac{acquisition\_cost}{clicks}\]
kd <- kd %>%
mutate(CPC = ifelse(clicks > 0, acquisition_cost / clicks, NA))
kd %>%
select(acquisition_cost, clicks, CPC) %>%
head(10) %>%
arrange(CPC) %>%
kable(caption = "Chi phí trung bình cho mỗi clicks (CPC)",
col.names = c("Acquisition Cost", "Clicks", "CPC"))| Acquisition Cost | Clicks | CPC |
|---|---|---|
| 11067 | 817 | 13.54590 |
| 10200 | 584 | 17.46575 |
| 18066 | 861 | 20.98258 |
| 13280 | 624 | 21.28205 |
| 13766 | 642 | 21.44237 |
| 16174 | 506 | 31.96443 |
| 16452 | 379 | 43.40897 |
| 12724 | 217 | 58.63594 |
| 9716 | 100 | 97.16000 |
| 11566 | 116 | 99.70690 |
\[CPM = \frac{acquisition\_cost}{impressions} \times 1000\]
kd <- kd %>%
mutate(CPM = ifelse(impressions > 0,(acquisition_cost / impressions) * 1000, NA))
kd %>%
select(acquisition_cost, impressions, CPM) %>%
head(10) %>%
arrange(CPM) %>%
kable(caption = "Chi phí cho mỗi 1000 lần hiển thị quảng cáo (CPM)",
col.names = c("Acquisition Cost", "Impressions", "CPM"))| Acquisition Cost | Impressions | CPM |
|---|---|---|
| 11067 | 8749 | 1264.945 |
| 10200 | 7698 | 1325.019 |
| 11566 | 7523 | 1537.419 |
| 13280 | 7854 | 1690.858 |
| 13766 | 3856 | 3570.021 |
| 16452 | 4201 | 3916.210 |
| 9716 | 1643 | 5913.573 |
| 12724 | 1820 | 6991.209 |
| 16174 | 1922 | 8415.193 |
| 18066 | 1754 | 10299.886 |
\[Engagement\_Rate = \frac{engagement\_score}{clicks}\]
kd <- kd %>%
mutate(Engagement_Rate = ifelse(clicks > 0, engagement_score / clicks, NA))
kd %>%
select(engagement_score, clicks, Engagement_Rate) %>%
head(10) %>%
arrange(Engagement_Rate) %>%
kable(caption = "Mức độ tương tác trung bình trên mỗi click (Engagement Rate)",
col.names = c("Engagement Score", "Clicks", "Engagement Rate"))| Engagement Score | Clicks | Engagement Rate |
|---|---|---|
| 1 | 584 | 0.0017123 |
| 3 | 642 | 0.0046729 |
| 6 | 861 | 0.0069686 |
| 3 | 379 | 0.0079156 |
| 1 | 100 | 0.0100000 |
| 7 | 624 | 0.0112179 |
| 6 | 506 | 0.0118577 |
| 10 | 817 | 0.0122399 |
| 7 | 217 | 0.0322581 |
| 7 | 116 | 0.0603448 |
q2 <- quantile(kd$roi, probs = c(0.25, 0.75), na.rm = TRUE)
kd <- kd %>% mutate(
roi_level = cut(
roi,
breaks = c(-Inf, q2[1], q2[2], Inf),
labels = c("Thấp", "Trung bình", "Cao"),
right = TRUE ))
kd %>%
count(roi_level) %>%
arrange(factor(roi_level, levels = c("Thấp", "Trung bình", "Cao"))) %>%
kable(caption = "Phân loại mức hiệu quả đầu tư theo phân vị",
col.names = c("ROI_Level", "Số lượng quan sát"))| ROI_Level | Số lượng quan sát |
|---|---|
| Thấp | 50259 |
| Trung bình | 100047 |
| Cao | 49694 |
q3 <- quantile(kd$engagement_score, probs = c(0.25, 0.75), na.rm = TRUE)
kd <- kd %>% mutate(
ad_attractiveness = cut(
engagement_score,
breaks = c(-Inf, q3[1], q3[2], Inf),
labels = c("Kém hấp dẫn", "Hấp dẫn vừa phải", "Rất hấp dẫn"),
right = TRUE ))
kd %>%
count(ad_attractiveness) %>%
arrange(factor(ad_attractiveness,
levels = c("Kém hấp dẫn", "Hấp dẫn vừa phải", "Rất hấp dẫn"))) %>%
kable(caption = "Phân loại sức hấp dẫn của quảng cáo theo phân vị",
col.names = c("Ad Attractiveness", "Số lượng quan sát"))| Ad Attractiveness | Số lượng quan sát |
|---|---|
| Kém hấp dẫn | 60087 |
| Hấp dẫn vừa phải | 99923 |
| Rất hấp dẫn | 39990 |
theme_set(theme_minimal(base_family = "Times New Roman"))
font_add_google("Roboto", "roboto")
showtext_auto()
theme_custom <- function() {
theme_minimal(
base_size = 14,
base_family = "Times New Roman") +
theme(
plot.title = element_text(face = "bold", size = 16,
hjust = 0.5, color = "#000"),
strip.text = element_text(face = "bold", size = 10),
axis.title = element_text(size = 10, face = "bold"),
axis.text = element_text(size = 10),
legend.title = element_text(size = 12, face = "bold"),
legend.text = element_text(size = 10),
panel.grid.minor = element_blank(),
panel.grid.major.x = element_blank())}bang_tan_suat <- list(
"Engagement Level" = kd %>% count(engagement_level) %>%
mutate(Variable = "Mức độ tương tác", Category = engagement_level) %>%
select(Variable, Category, n) %>%
arrange(factor(Category, levels = c("Thấp", "Trung bình", "Cao"))),
"Age Group" = kd %>% count(age_group) %>%
mutate(Variable = "Nhóm tuổi", Category = age_group) %>%
select(Variable, Category, n) %>%
arrange(factor(Category, levels = c("18-24", "25-34", "35-44", "All"))),
"Duration Level" = kd %>% count(duration_level) %>%
mutate(Variable = "Thời lượng chiến dịch", Category = duration_level) %>%
select(Variable, Category, n) %>%
arrange(factor(Category, levels = c("Rất ngắn", "Ngắn", "Trung bình", "Dài"))),
"Clicks Level" = kd %>% count(clicks_level) %>%
mutate(Variable = "Số lần nhấp chuột", Category = clicks_level) %>%
select(Variable, Category, n) %>%
arrange(factor(Category, levels = c("Thấp", "Trung bình", "Cao"))),
"Language Level" = kd %>% count(Language_Level) %>%
mutate(Variable = "Mức độ phổ biến ngôn ngữ", Category = Language_Level) %>%
select(Variable, Category, n) %>%
arrange(factor(Category, levels = c("Ít phổ biến",
"Phổ biến trung bình", "Phổ biến cao"))),
"ROI Level" = kd %>% count(roi_level) %>%
mutate(Variable = "Mức hiệu quả đầu tư", Category = roi_level) %>%
select(Variable, Category, n) %>%
arrange(factor(Category, levels = c("Thấp", "Trung bình", "Cao"))),
"Ad Attractiveness" = kd %>% count(ad_attractiveness) %>%
mutate(Variable = "Sức hấp dẫn quảng cáo", Category = ad_attractiveness) %>%
select(Variable, Category, n) %>%
arrange(factor(Category, levels = c("Kém hấp dẫn",
"Hấp dẫn vừa phải", "Rất hấp dẫn"))))
combined_df <- bind_rows(bang_tan_suat) %>%
select(Variable, Category, n) %>%
group_by(Variable) %>%
mutate(Percentage = round(100 * n / sum(n), 2)) %>%
ungroup()
kableExtra::kable(combined_df, format = "latex",
caption = "Tần suất các biến đã được mã hóa",
col.names = c("Biến", "Mức phân loại", "Số lượng quan sát", "Tỷ lệ (%)")) %>%
kable_styling(
latex_options = c("hold_position", "scale_down"),
position = "center" )bieu_do_tan_suat <- list(
ggplot(kd, aes(x = engagement_level, fill = engagement_level)) +
geom_bar() +
geom_text(stat = "count", aes(label = ..count..), vjust = 1.5,
color = "black", size = 4) +
labs(title = "Mức độ tương tác", x = "Engagement Level", y = "Số lượng") +
theme_custom() +
theme(legend.position = "none"),
ggplot(kd, aes(x = age_group, fill = age_group)) +
geom_bar() +
geom_text(stat = "count", aes(label = ..count..), vjust = 1.5,
color = "black", size = 4) +
labs(title = "Nhóm tuổi", x = "Age Group", y = "Số lượng") +
theme_custom() +
theme(legend.position = "none"),
ggplot(kd, aes(x = duration_level, fill = duration_level)) +
geom_bar() +
geom_text(stat = "count", aes(label = ..count..), vjust = 1.5,
color = "black", size = 4) +
labs(title = "Cấp độ thời lượng chiến dịch",
x = "Duration Level", y = "Số lượng") +
theme_custom() +
theme(legend.position = "none",
axis.text.x = element_text(angle = 0, hjust = 0.5, size = 8)),
ggplot(kd, aes(x = clicks_level, fill = clicks_level)) +
geom_bar() +
geom_text(stat = "count", aes(label = ..count..), vjust = 1.5,
color = "black", size = 4) +
labs(title = "Cấp độ số lần nhấp chuột", x = "Clicks Level", y = "Số lượng") +
theme_custom() +
theme(legend.position = "none"))
(bieu_do_ket_hop <- wrap_plots(bieu_do_tan_suat, ncol = 2) +
plot_annotation(
title = "Biểu đồ tần suất các biến đã được mã hóa",
theme = theme(plot.title = element_text(size = 18, face = "bold",
hjust = 0.5, family = "Times New Roman") )))bieu_do_tan_suat1 <- list(
ggplot(kd, aes(x = Language_Level, fill = Language_Level)) +
geom_bar() +
geom_text(stat = "count", aes(label = ..count..), vjust = 1.5,
color = "black", size = 4) +
labs(title = "Mức độ phổ biến ngôn ngữ", x = "Language Level", y = "Số lượng") +
theme_custom() +
theme(legend.position = "none",
axis.text.x = element_text(angle = 0, hjust = 0.5, size = 6)),
ggplot(kd, aes(x = roi_level, fill = roi_level)) +
geom_bar() +
geom_text(stat = "count", aes(label = ..count..), vjust = 1.5,
color = "black", size = 4) +
labs(title = "Mức hiệu quả đầu tư", x = "ROI Level", y = "Số lượng") +
theme_custom() +
theme(legend.position = "none"),
ggplot(kd, aes(x = ad_attractiveness, fill = ad_attractiveness)) +
geom_bar()+
geom_text(stat = "count", aes(label = ..count..), vjust = 1.5,
color = "black", size = 4) +
labs(title = "Sức hấp dẫn quảng cáo", x = "Ad Attractiveness", y = "Số lượng") +
theme_custom() +
theme(legend.position = "none",
axis.text.x = element_text(angle = 0, hjust = 0.5, size = 6)))
(bieu_do_ket_hop1 <- wrap_plots(bieu_do_tan_suat1, ncol = 2) +
plot_annotation(
title = "Biểu đồ tần suất các biến đã được mã hóa (tiếp)",
theme = theme(plot.title = element_text(size = 18, face = "bold",
hjust = 0.5, family = "Times New Roman"))))kd_summary <- kd %>%
group_by(engagement_level) %>%
summarise(Mean_ROI = mean(roi, na.rm = TRUE), N = n()) %>%
arrange(desc(Mean_ROI))
kd_summary %>%
kable(
caption = "ROI trung bình theo mức độ tương tác",
col.names = c("Mức độ tương tác", "ROI trung bình", "Số lượng quan sát"))| Mức độ tương tác | ROI trung bình | Số lượng quan sát |
|---|---|---|
| Trung bình | 5.003452 | 99923 |
| Cao | 5.002360 | 39990 |
| Thấp | 5.000803 | 60087 |
ggplot(kd_summary, aes(x = reorder(engagement_level, -Mean_ROI),y = Mean_ROI,
color = engagement_level)) +
geom_segment(aes(x = reorder(engagement_level, -Mean_ROI),
xend = reorder(engagement_level,-Mean_ROI),y = 0, yend = Mean_ROI)) +
geom_point(size = 5) +
geom_text(aes(label = sprintf("%.4f", Mean_ROI)),vjust = -1,size = 4, color="black") +
labs(title = "ROI trung bình theo mức độ tương tác",
x = "Mức độ tương tác",
y = "ROI trung bình") +
theme_custom() +
theme(plot.title = element_text(face = "bold", size = 16, hjust = 0.5),
legend.position = "none") + scale_y_continuous(limits = c(0, 7))kd_age <- kd %>%
group_by(age_group) %>%
summarise(Mean_CPC = mean(CPC, na.rm = TRUE), N = n()) %>%
arrange(Mean_CPC)
kd_age %>%
kable(
caption = "CPC trung bình theo nhóm tuổi",
col.names = c("Nhóm tuổi", "CPC trung bình", "Số lượng quan sát"))| Nhóm tuổi | CPC trung bình | Số lượng quan sát |
|---|---|---|
| 25-34 | 31.90798 | 80036 |
| 35-44 | 31.97152 | 39687 |
| 18-24 | 32.05411 | 40258 |
| All | 32.20028 | 40019 |
ggplot(kd_age, aes(x = Mean_CPC, y = reorder(age_group, Mean_CPC), fill = age_group)) +
geom_col(width = 0.6) +
geom_text(aes(label = sprintf("%.4f", Mean_CPC, 2)),
hjust = 1.2, size = 5, color="#000") +
labs(title = "CPC trung bình theo nhóm tuổi", x = "CPC trung bình", y = "Nhóm tuổi") +
theme_custom() +
theme(plot.title = element_text(face = "bold", size = 16, hjust = 0.5),
legend.position = "none")kd_cd <- kd %>%
group_by(duration_level) %>%
summarise( Mean_CTR = mean(CTR, na.rm = TRUE),N = n()) %>%
arrange(factor(duration_level, levels = c("Rất ngắn", "Ngắn", "Trung bình", "Dài")))
kd_cd %>%
kable(
caption = "CTR trung bình theo cấp độ thời lượng chiến dịch",
col.names = c("Cấp độ thời lượng chiến dịch", "CTR trung bình", "Số lượng quan sát"))| Cấp độ thời lượng chiến dịch | CTR trung bình | Số lượng quan sát |
|---|---|---|
| Rất ngắn | 0.1394716 | 49779 |
| Ngắn | 0.1408740 | 50255 |
| Trung bình | 0.1403701 | 50100 |
| Dài | 0.1409012 | 49866 |
ggplot(kd_cd, aes(x = duration_level,
y = Mean_CTR,
size = Mean_CTR,
color = duration_level)) +
geom_point() +
geom_text(aes(label = sprintf("%.5f", Mean_CTR)),
vjust = -1.5, size = 5, color = "#000000") +
labs(title = "CTR trung bình theo mức độ thời lượng",
x = "Mức độ thời lượng",
y = "CTR trung bình", size = "Giá trị CTR", color = "Thời lượng") +
theme_custom() +
theme(plot.title = element_text(face = "bold", size = 16, hjust = 0.5)) +
scale_y_continuous(limits = c(0.1390, 0.1415))kd_la <- kd %>%
group_by(Language_Level) %>%
summarise(Mean_CPC = mean(CPC, na.rm = TRUE),N = n()) %>%
arrange(Mean_CPC)
kd_la %>%
kable(
caption = "CPC trung bình theo mức độ phổ biến ngôn ngữ",
col.names = c("Mức độ phổ biến ngôn ngữ", "CPC trung bình", "Số lượng quan sát"))| Mức độ phổ biến ngôn ngữ | CPC trung bình | Số lượng quan sát |
|---|---|---|
| Ít phổ biến | 31.86422 | 79660 |
| Phổ biến cao | 32.07894 | 40255 |
| Phổ biến trung bình | 32.11659 | 80085 |
ggplot(kd_la, aes(x = 1, y = Mean_CPC, fill = Language_Level)) +
geom_bar(stat = "identity", width = 1, color = "white") +
coord_polar("y", start = 0) + xlim(c(0, 1.5)) +
geom_text(aes(label = paste0(round(Mean_CPC / sum(Mean_CPC) * 100, 1), "%")),
position = position_stack(vjust = 0.5),
size = 5, color = "black") +
labs(
title = "Tỷ trọng CPC trung bình theo mức độ phổ biến ngôn ngữ",
fill = "Trình độ ngôn ngữ"
) +
theme_void(base_family = "Times New Roman") +
scale_fill_brewer(palette = "Set2") +
theme(
plot.title = element_text(face = "bold", size = 16, hjust = 0),
legend.title = element_text(size = 13, face = "bold"),
legend.text = element_text(size = 12))roi_channel <- kd %>%
filter(!is.na(roi_level) & !is.na(channel_used)) %>%
count(channel_used, roi_level) %>%
group_by(channel_used) %>%
mutate(percentage = n / sum(n)) %>%
ungroup()
roi_channel %>%
kable(
caption = "Phân phối mức ROI theo Kênh",
col.names = c("Kênh", "Mức ROI", "Số lượng", "Tỷ lệ"))| Kênh | Mức ROI | Số lượng | Tỷ lệ |
|---|---|---|---|
| Thấp | 8529 | 0.2538468 | |
| Trung bình | 16684 | 0.4965624 | |
| Cao | 8386 | 0.2495908 | |
| Thấp | 8226 | 0.2506475 | |
| Trung bình | 16314 | 0.4970901 | |
| Cao | 8279 | 0.2522624 | |
| Google Ads | Thấp | 8323 | 0.2489084 |
| Google Ads | Trung bình | 16829 | 0.5032897 |
| Google Ads | Cao | 8286 | 0.2478019 |
| Thấp | 8508 | 0.2547916 | |
| Trung bình | 16632 | 0.4980834 | |
| Cao | 8252 | 0.2471251 | |
| Website | Thấp | 8257 | 0.2475120 |
| Website | Trung bình | 16875 | 0.5058453 |
| Website | Cao | 8228 | 0.2466427 |
| YouTube | Thấp | 8416 | 0.2520364 |
| YouTube | Trung bình | 16713 | 0.5005091 |
| YouTube | Cao | 8263 | 0.2474545 |
(p_roi_channel <- ggplot(roi_channel,
aes(x = channel_used, y = percentage, fill = roi_level)) +
geom_col(position = "fill", width = 0.7) +
geom_text(aes(label = scales::percent(percentage, accuracy = 0.1)),
position = position_fill(vjust = 0.5), size = 3.5, color = "black") +
scale_y_continuous(labels = scales::percent) +
scale_fill_brewer(palette = "RdYlGn", direction = 1) +
labs(
title = "Tỷ lệ mức ROI theo Kênh sử dụng",
x = "Kênh",
y = "Tỷ lệ",
fill = "Mức ROI" ) +
coord_flip() +
theme_custom()) campaign_age<- kd %>%
filter(!is.na(age_group) & !is.na(campaign_type)) %>%
count(age_group, campaign_type) %>%
group_by(age_group) %>%
mutate(percentage = n / sum(n)) %>%
ungroup()
campaign_age %>%
kable(
caption = "Phân phối Loại chiến dịch theo Nhóm tuổi",
col.names = c("Nhóm tuổi", "Loại chiến dịch", "Số lượng", "Tỷ lệ"))| Nhóm tuổi | Loại chiến dịch | Số lượng | Tỷ lệ |
|---|---|---|---|
| 18-24 | Display | 8119 | 0.2016742 |
| 18-24 | 8012 | 0.1990163 | |
| 18-24 | Influencer | 8195 | 0.2035620 |
| 18-24 | Search | 7965 | 0.1978489 |
| 18-24 | Social Media | 7967 | 0.1978986 |
| 25-34 | Display | 15967 | 0.1994977 |
| 25-34 | 15948 | 0.1992603 | |
| 25-34 | Influencer | 15944 | 0.1992104 |
| 25-34 | Search | 16174 | 0.2020841 |
| 25-34 | Social Media | 16003 | 0.1999475 |
| 35-44 | Display | 7975 | 0.2009474 |
| 35-44 | 8013 | 0.2019049 | |
| 35-44 | Influencer | 7798 | 0.1964875 |
| 35-44 | Search | 7986 | 0.2012246 |
| 35-44 | Social Media | 7915 | 0.1994356 |
| All | Display | 7926 | 0.1980559 |
| All | 7897 | 0.1973313 | |
| All | Influencer | 8232 | 0.2057023 |
| All | Search | 8032 | 0.2007047 |
| All | Social Media | 7932 | 0.1982059 |
(p_camp_age <- ggplot(campaign_age,
aes(x = age_group, y = percentage, fill = campaign_type)) +
geom_col(position = "fill", width = 0.7) +
geom_text(aes(label = scales::percent(percentage, accuracy = 0.1)),
position = position_fill(vjust = 0.5),
size = 4, color = "black", fontface = "bold") +
scale_y_continuous(labels = scales::percent) +
scale_fill_brewer(palette = "Set2") +
labs(
title = "Phân phối Loại chiến dịch theo Nhóm tuổi",
x = "Nhóm tuổi",
y = "Tỷ lệ",
fill = "Loại chiến dịch" ) +
theme_custom())age_clicks_table <- table(kd$age_group, kd$clicks_level)
age_clicks_df <- as.data.frame(age_clicks_table) %>%
arrange(desc(Freq))
age_clicks_df %>%
kable(
caption = "Bảng chéo: Nhóm tuổi × Cấp độ số lần nhấp chuột",
col.names = c("Nhóm tuổi", "Cấp độ số lần nhấp chuột", "Số lượng quan sát"))| Nhóm tuổi | Cấp độ số lần nhấp chuột | Số lượng quan sát |
|---|---|---|
| 25-34 | Trung bình | 39894 |
| 18-24 | Trung bình | 20185 |
| All | Trung bình | 20136 |
| 25-34 | Thấp | 20109 |
| 25-34 | Cao | 20033 |
| 35-44 | Trung bình | 19772 |
| 18-24 | Thấp | 10090 |
| 18-24 | Cao | 9983 |
| All | Thấp | 9972 |
| 35-44 | Thấp | 9971 |
| 35-44 | Cao | 9944 |
| All | Cao | 9911 |
cor_matrix <- cor(kd[, c("engagement_score", "clicks")],
use = "complete.obs", method = "pearson")
as.data.frame(cor_matrix) %>%
kable(
caption = "Ma trận hệ số tương quan giữa Engagement Score và Clicks",
col.names = c("Engagement Score", "Clicks"))| Engagement Score | Clicks | |
|---|---|---|
| engagement_score | 1.0000000 | -0.0019081 |
| clicks | -0.0019081 | 1.0000000 |
cor_data <- melt(cor_matrix)
ggplot(cor_data, aes(x = Var1, y = Var2, fill = value)) +
geom_tile(color = "white") +
geom_text(aes(label = round(value, 2)), color = "black",
size = 5, fontface = "bold") +
scale_fill_gradient2(low = "#d73027", mid = "white", high = "#1a9850",
midpoint = 0, limit = c(-1, 1),
name = "Hệ số Tương quan") +
labs(title = " Ma trận hệ số tương quan giữa Engagement Score và Clicks",
x = "", y = "" ) +
theme_custom()1: Tính ma trận tương quan giữa Engagement Score và Clicks sử dụng phương pháp Pearson.
3: Chuyển đổi ma trận tương quan thành bảng dữ liệu để dễ dàng hiển thị.
4 - 6: Hiển thị bảng ma trận tương quan.
1: Chuyển đổi ma trận tương quan thành định dạng dài để vẽ biểu đồ nhiệt.
2: Tạo biểu đồ nhiệt thể hiện ma trận tương quan.
8: Thêm tiêu đề và nhãn trục cho biểu đồ.
11: Áp dụng chủ đề tùy chỉnh đã thiết lập trước đó.
\[\text{Các chỉ số: } \text{roi, CTR, CPC, CPM, acquisition\_cost, clicks, impressions}\]
numeric_metrics <- kd %>%
select(roi, CTR, CPC, CPM, acquisition_cost, clicks, impressions, engagement_score) %>%
filter_all(all_vars(!is.infinite(.)))
cor_matrix_metrics <- cor(numeric_metrics, use = "complete.obs", method = "pearson")
as.data.frame(cor_matrix_metrics) %>%
kable(format = "latex", booktabs = TRUE,
caption = "Ma trận hệ số tương quan các chỉ số Marketing",
col.names = c("ROI", "CTR", "CPC", "CPM",
"Acquisition Cost", "Clicks", "Impressions", "Engagement Score")) %>%
kable_styling(
latex_options = c("hold_position", "scale_down"),
position = "center" )(p_corr_metrics <- ggcorrplot(cor_matrix_metrics,
hc.order = TRUE,
type = "lower",
lab = TRUE,
lab_size = 3.5,
method = "square",
colors = c("#d73027", "white", "#1a9850"),
title = "Ma trận tương quan các chỉ số Marketing") +
theme(plot.title = element_text(face = "bold", size = 16,
hjust = 0.5, family="Times New Roman"),
axis.text.x = element_text(angle = 45, vjust = 1,
hjust = 1, family="Times New Roman"),
axis.text.y = element_text(family="Times New Roman")))roi_mul <- kd %>%
filter(!is.na(roi) & !is.na(channel_used) & !is.na(age_group)) %>%
group_by(channel_used, age_group) %>%
summarise( Mean_ROI = mean(roi, na.rm = TRUE),N = n()) %>%
ungroup()
roi_mul %>%
kable(
caption = "ROI trung bình theo Kênh và Nhóm tuổi",
col.names = c("Kênh", "Nhóm tuổi", "ROI Trung bình", "Số lượng"))| Kênh | Nhóm tuổi | ROI Trung bình | Số lượng |
|---|---|---|---|
| 18-24 | 4.987819 | 6772 | |
| 25-34 | 5.008481 | 13353 | |
| 35-44 | 5.014520 | 6719 | |
| All | 4.963529 | 6755 | |
| 18-24 | 4.959734 | 6727 | |
| 25-34 | 5.034363 | 12999 | |
| 35-44 | 5.033879 | 6476 | |
| All | 5.033015 | 6617 | |
| Google Ads | 18-24 | 5.009151 | 6658 |
| Google Ads | 25-34 | 4.998661 | 13450 |
| Google Ads | 35-44 | 4.987042 | 6656 |
| Google Ads | All | 5.022231 | 6674 |
| 18-24 | 4.958137 | 6763 | |
| 25-34 | 5.000456 | 13279 | |
| 35-44 | 4.985893 | 6679 | |
| All | 4.999123 | 6671 | |
| Website | 18-24 | 4.998221 | 6661 |
| Website | 25-34 | 5.018644 | 13493 |
| Website | 35-44 | 5.007805 | 6561 |
| Website | All | 5.027339 | 6645 |
| YouTube | 18-24 | 4.984590 | 6677 |
| YouTube | 25-34 | 4.994060 | 13462 |
| YouTube | 35-44 | 5.009632 | 6596 |
| YouTube | All | 4.986596 | 6657 |
Nhận xét tổng quan:
* Facebook và Website có ROI trung bình cao nhất cho nhóm 25–34 (khoảng
5,034 – 5,019), cho thấy đây là đối tượng tiềm năng để tập trung chiến
dịch.
* Sự khác biệt ROI giữa các nhóm tuổi không quá lớn, nhưng nhóm 25–34
vẫn nổi bật hơn, đặc biệt trên các kênh hiệu quả như Facebook và
Website.
* Nhóm 18–24 và nhóm All có ROI trung bình thấp hơn, có thể cần tối ưu
chiến lược hoặc nội dung quảng cáo cho các đối tượng này.
(p_roi_facet <- ggplot(roi_mul,
aes(x = reorder(channel_used, Mean_ROI), y = Mean_ROI, fill = channel_used)) +
geom_col() +
geom_text(aes(label = sprintf("%.4f", Mean_ROI)),
vjust = 1.5, size = 4, color="black") +
facet_wrap(~ age_group, ncol = 1) +
labs(
title = "ROI trung bình theo Kênh và Nhóm tuổi",
x = "Kênh",
y = "ROI trung bình") +
theme_custom() +
theme(
legend.position = "none",
axis.text.x = element_text(angle = 0, hjust = 0.5),
axis.text.y = element_text(angle = 0, hjust = 0.5, size = 8, fontface="bold" )))kbl_default1<- function(data, caption = NULL, col.names = NULL, align = NULL) {
num_cols <- names(data)[sapply(data, is.numeric) & !(names(data) %in%
c("Năm", "year"))]
data_fmt <- data %>%
mutate(across(all_of(num_cols),
~ format(., big.mark = ".", decimal.mark = ",",
scientific = FALSE)))
return(data_fmt) }
format_vn <- function(x, digits = 0) {
format(round(x, digits),
big.mark = ".",
decimal.mark = ",",
scientific = FALSE)}bc %>% kbl_default1() %>%
kable(format = "latex", booktabs = TRUE,
caption = "Bộ dữ liệu Báo cáo tài chính IMP") %>%
kable_styling(
latex_options = c("hold_position", "scale_down"),
position = "center")cau_truc1 <- data.frame(
`Tên biến` = names(bc),
`Kiểu dữ liệu` = sapply(bc, function(x) class(x)[1]),
`xuất giá trị đầu` = sapply(bc, function(x) if(is.numeric(x)) x[1]
else as.character(x[1])),
check.names = FALSE,
row.names = NULL)
cau_truc1 %>%
kbl_default1() %>% kable(
caption = "Cấu trúc dữ liệu của bộ Marketing Campaign Performance Dataset",
col.name= c("Tên biến", "Kiểu dữ liệu", "Giá trị đầu"),
align = "lrr")| Tên biến | Kiểu dữ liệu | Giá trị đầu |
|---|---|---|
| Năm | numeric | 2.015 |
| LoiNhuanSauThue | numeric | 92.275.349.999 |
| Tien_DauKy | numeric | 178.550.050.326 |
| Tien_CuoiKy | numeric | 87.841.659.460 |
| CFO_Tong | numeric | 81.130.888.888 |
| KhauHao | numeric | 38.402.557.093 |
| BienDong_PhaiThu | numeric | -41.333.661.601 |
| BienDong_TonKho | numeric | 50.382.333.195 |
| BienDong_PhaiTra | numeric | -35.669.331.173 |
| LaiVay_DaTra | numeric | -605.820.692 |
| Thue_DaNop | numeric | -26.094.252.845 |
| CFI_Tong | numeric | -204.828.797.781 |
| Chi_MuaTSCD | numeric | -116.451.196.931 |
| Chi_TienGui | numeric | -100.000.000.000 |
| Thu_TienGui | numeric | NA |
| CFF_Tong | numeric | 32.990.722.640 |
| VayMoi | numeric | 95.894.850.000 |
| TraNoGoc | numeric | -95.894.850.000 |
kich_thuoc1 <- data.frame(
Thông_tin = c("Số dòng (Quan sát)", "Số cột (Biến)"),
Kết_quả = c(nrow(bc), ncol(bc)) )
kich_thuoc1 %>%
kbl_default1() %>% kable(
caption = "Cấu trúc dữ liệu của bộ Marketing Campaign Performance Dataset",
col.name= c("Thông tin", "Kết quả"),
align = "lr")| Thông tin | Kết quả |
|---|---|
| Số dòng (Quan sát) | 10 |
| Số cột (Biến) | 18 |
bc1 <- bc %>% select(-Năm)
skimmed1 <- skim(bc1)
thong_ke_mota1 <- skimmed1 %>%
select(skim_variable, numeric.mean, numeric.p50, numeric.sd, numeric.p0, numeric.p100)
thong_ke_mota1 %>% kbl_default1() %>% kable(
caption = "Bảng Thống kê Mô tả (Đơn vị: VND)",
col.names = c("Biến", "Trung bình", "Trung vị", "Độ lệch chuẩn", "Min", "Max"),
align = "lrrrrr") %>%
kable_styling(latex_options = c("hold_position", "scale_down"),
position = "center")| Biến | Trung bình | Trung vị | Độ lệch chuẩn | Min | Max |
|---|---|---|---|---|---|
| LoiNhuanSauThue | 185.461.493.333 | 175.740.780.878 | 79.267.830.966 | 92.275.349.999 | 320.862.393.082 |
| Tien_DauKy | 138.003.577.443 | 106.328.850.442 | 63.705.340.836 | 75.035.614.726 | 271.272.865.376 |
| Tien_CuoiKy | 136.346.904.294 | 106.328.850.442 | 62.741.887.421 | 75.035.614.726 | 271.272.865.376 |
| CFO_Tong | 133.427.627.649 | 90.931.774.710 | 114.796.209.903 | -30.308.428.665 | 378.603.401.448 |
| KhauHao | 54.126.367.933 | 47.284.812.141 | 24.306.276.907 | 30.515.092.412 | 105.636.226.909 |
| BienDong_PhaiThu | -12.166.658.588 | -14.460.118.668 | 57.502.782.383 | -83.306.984.898 | 115.759.490.658 |
| BienDong_TonKho | -41.154.397.712 | -34.622.213.581 | 89.038.343.861 | -260.749.238.157 | 52.398.387.880 |
| BienDong_PhaiTra | -7.535.274.795 | -8.277.667.477 | 29.924.095.334 | -49.525.833.086 | 39.579.670.960 |
| LaiVay_DaTra | -3.046.559.562 | -3.598.954.722 | 2.272.372.959 | -6.699.943.903 | -55.154.439 |
| Thue_DaNop | -45.519.649.979 | -41.597.605.868 | 20.095.203.893 | -83.992.016.063 | -22.380.008.319 |
| CFI_Tong | -130.736.762.123 | -123.911.128.404 | 137.798.621.319 | -443.246.932.809 | 69.894.262.492 |
| Chi_MuaTSCD | -130.057.173.899 | -101.628.608.786 | 78.923.882.881 | -274.456.614.870 | -52.856.687.303 |
| Chi_TienGui | -198.920.800.808 | -176.494.739.041 | 162.819.741.002 | -451.171.580.000 | -12.000.000.000 |
| Thu_TienGui | 204.128.349.936 | 195.897.929.613 | 146.900.902.612 | 26.297.761.332 | 491.300.000.000 |
| CFF_Tong | -4.797.122.112 | -33.304.800.015 | 168.195.912.399 | -271.718.144.243 | 352.371.798.300 |
| VayMoi | 142.392.327.092 | 160.076.187.844 | 202.072.945.620 | -315.649.453.686 | 387.993.511.872 |
| TraNoGoc | -183.894.915.875 | -181.308.771.504 | 92.990.583.989 | -351.293.662.887 | -49.387.359.000 |
du_lieu_bi_thieu1 <- bc %>% summarise_all(~ sum(is.na(.))) %>%
pivot_longer(everything(), names_to = "Tên biến", values_to = "Số giá trị bị thiếu")
du_lieu_bi_thieu1 %>% kbl_default1() %>%
kable(caption = "Kiểm tra dữ liệu bị thiếu",
col.names = c("Tên biến", "Số giá trị bị thiếu"), align = "lr")| Tên biến | Số giá trị bị thiếu |
|---|---|
| Năm | 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 |
trung_lap1 <- bc %>%
duplicated() %>% sum()
trung_lap_df <- data.frame('Số bản dòng bị trùng lặp' = trung_lap1)
trung_lap_df %>%
kbl_default1() %>%
kable(caption = "Kiểm tra dữ liệu trùng lặp",
col.names = c("Số dòng bị trùng lặp"), align = "c")| Số dòng bị trùng lặp |
|---|
| 0 |
bc %>%
select(Năm, LoiNhuanSauThue) %>%
arrange(desc(LoiNhuanSauThue)) %>%
head(3) %>%
kbl_default1() %>%
kable(
caption = "Top 3 năm có giá trị lợi nhuận sau thuế cao nhất",
col.names = c("Năm", "Lợi nhuận sau thuế (VND)"), align = "lr")| Năm | Lợi nhuận sau thuế (VND) |
|---|---|
| 2024 | 320.862.393.082 |
| 2023 | 299.556.005.542 |
| 2022 | 223.540.317.602 |
bc %>%
select(Năm, CFO_Tong) %>%
arrange(desc(CFO_Tong)) %>%
head(3) %>%
kbl_default1() %>%
kable(
caption = "Top 3 năm có dòng tiền từ hoạt động kinh doanh cao nhất",
col.names = c("Năm", "Dòng tiền từ hoạt động kinh doanh (VND)"), align = "lr")| Năm | Dòng tiền từ hoạt động kinh doanh (VND) |
|---|---|
| 2022 | 378.603.401.448 |
| 2021 | 234.881.036.040 |
| 2024 | 216.267.565.018 |
bc %>%
select(Năm, BienDong_TonKho) %>%
arrange(BienDong_TonKho) %>%
head(3) %>% kbl_default1() %>%
kable(
caption = "Top 3 năm có biến động hàng tồn kho thấp nhất",
col.names = c("Năm", "Biến động hàng tồn kho (VND)"), align = "lr")| Năm | Biến động hàng tồn kho (VND) |
|---|---|
| 2023 | -260.749.238.157 |
| 2020 | -75.247.048.473 |
| 2021 | -66.128.977.456 |
bctc <- bc %>%
mutate(across(where(is.numeric),
~ifelse(is.na(.), median(., na.rm = TRUE), .)))
du_lieu_bi_thieu2 <- bctc %>% summarise_all(~ sum(is.na(.))) %>%
pivot_longer(everything(), names_to = "Tên biến", values_to = "Số giá trị bị thiếu")
du_lieu_bi_thieu2 %>%kbl_default1() %>%
kable(caption = "Kiểm tra dữ liệu bị thiếu sau khi xử lý",
l.names = c("Tên biến", "Số giá trị bị thiếu"), align = "lr")| Tên biến | Số giá trị bị thiếu |
|---|---|
| Năm | 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 | 0 |
| CFF_Tong | 0 |
| VayMoi | 0 |
| TraNoGoc | 0 |
q4 <- quantile(bctc$LoiNhuanSauThue, probs = c(0.25, 0.75), na.rm = TRUE)
bctc <- bctc %>% mutate(
Nhom_loi_nhuan = cut(
LoiNhuanSauThue,
breaks = c(-Inf, q4[1], q4[2], Inf),
labels = c("Thấp", "Trung bình", "Cao"),
right = TRUE ))
bctc %>%
select(Năm, LoiNhuanSauThue, Nhom_loi_nhuan) %>%
arrange(factor(Nhom_loi_nhuan, levels = c("Thấp", "Trung bình", "Cao"))) %>%
kbl_default1() %>%
kable(caption = "Phân loại lợi nhuận sau thuế theo phân vị",
col.names = c("Năm", "Lợi Nhuận Sau Thuế", "Nhóm lợi nhuận"), align = "lrl")| Năm | Lợi Nhuận Sau Thuế | Nhóm lợi nhuận |
|---|---|---|
| 2015 | 92.275.349.999 | Thấp |
| 2016 | 101.159.344.647 | Thấp |
| 2017 | 117.360.040.786 | Thấp |
| 2018 | 138.683.041.628 | Trung bình |
| 2019 | 162.386.686.793 | Trung bình |
| 2020 | 209.696.878.289 | Trung bình |
| 2021 | 189.094.874.963 | Trung bình |
| 2022 | 223.540.317.602 | Cao |
| 2023 | 299.556.005.542 | Cao |
| 2024 | 320.862.393.082 | Cao |
q5 <- quantile(bctc$CFO_Tong, probs = c(0.25, 0.75), na.rm = TRUE)
bctc <- bctc %>% mutate(
Nhom_CFO = cut(
CFO_Tong,
breaks = c(-Inf, q5[1], q5[2], Inf),
labels = c("Thấp", "Trung bình", "Cao"),
right = TRUE ))
bctc %>%
select(Năm, CFO_Tong, Nhom_CFO) %>%
arrange(Năm) %>% kbl_default1() %>%
kable(caption = "Phân loại dòng tiền từ hoạt động kinh doanh theo phân vị",
col.names = c("Năm" ,"Dòng tiền từ hoạt động kinh doanh", "Nhóm CFO"),
align = "lrl")| Năm | Dòng tiền từ hoạt động kinh doanh | Nhóm CFO |
|---|---|---|
| 2015 | 81.130.888.888 | Trung bình |
| 2016 | 84.650.650.055 | Trung bình |
| 2017 | 97.212.899.364 | Trung bình |
| 2018 | 132.094.454.149 | Trung bình |
| 2019 | 66.590.387.415 | Thấp |
| 2020 | 73.153.422.780 | Thấp |
| 2021 | 234.881.036.040 | Cao |
| 2022 | 378.603.401.448 | Cao |
| 2023 | -30.308.428.665 | Thấp |
| 2024 | 216.267.565.018 | Cao |
q6 <- quantile(bctc$KhauHao, probs = c(0.25, 0.75), na.rm = TRUE)
bctc <- bctc %>% mutate(
Nhom_KhauHao = cut(
KhauHao,
breaks = c(-Inf, q6[1], q6[2], Inf),
labels = c("Thấp", "Trung bình", "Cao"),
right = TRUE ))
bctc %>%
select(Năm, KhauHao, Nhom_KhauHao) %>%
arrange(Năm) %>%
kbl_default1() %>%
kable(caption = "Phân loại biên độ khấu hao theo phân vị",
col.names = c("Năm" ,"Khấu hao" , "Nhóm Khấu Hao"), align = "lrl")| Năm | Khấu hao | Nhóm Khấu Hao |
|---|---|---|
| 2015 | 38.402.557.093 | Trung bình |
| 2016 | 37.320.990.534 | Thấp |
| 2017 | 31.379.088.060 | Thấp |
| 2018 | 30.515.092.412 | Thấp |
| 2019 | 41.208.658.249 | Trung bình |
| 2020 | 53.360.966.033 | Trung bình |
| 2021 | 60.412.122.442 | Cao |
| 2022 | 60.385.696.030 | Trung bình |
| 2023 | 82.642.281.566 | Cao |
| 2024 | 105.636.226.909 | Cao |
q7 <- quantile(bctc$Thue_DaNop, probs = c(0.25, 0.75), na.rm = TRUE)
bctc <- bctc %>% mutate(
Nhom_ThueDaNop = cut(
Thue_DaNop,
breaks = c(-Inf, q7[1], q7[2], Inf),
labels = c("Cao", "Trung bình", "Thấp"),
right = TRUE ))
bctc %>%
select(Năm, Thue_DaNop, Nhom_ThueDaNop) %>%
arrange(Năm) %>%
kbl_default1() %>%
kable(caption = "Phân loại Thuế đã nộp theo phân vị",
col.names = c("Năm" ,"Thuế đã nộp", "Nhóm Thuế Đã Nộp"), align = "lrl")| Năm | Thuế đã nộp | Nhóm Thuế Đã Nộp |
|---|---|---|
| 2015 | -26.094.252.845 | Thấp |
| 2016 | -22.380.008.319 | Thấp |
| 2017 | -31.711.798.648 | Thấp |
| 2018 | -32.083.024.291 | Trung bình |
| 2019 | -42.339.105.925 | Trung bình |
| 2020 | -40.856.105.810 | Trung bình |
| 2021 | -45.310.346.424 | Trung bình |
| 2022 | -59.623.516.944 | Cao |
| 2023 | -83.992.016.063 | Cao |
| 2024 | -70.806.324.518 | Cao |
\[ \text{Tổng điểm} = \text{Điểm lợi nhuận} + \text{Điểm CFO} + \text{Điểm Khấu hao} + \text{Điểm Thuế} \]
bctc <- bctc %>%
mutate(
LoiNhuan_diem = recode(Nhom_loi_nhuan, "Thấp" = 1, "Trung bình" = 2, "Cao" = 3),
CFO_diem = recode(Nhom_CFO, "Thấp" = 1, "Trung bình" = 2, "Cao" = 3),
KhauHao_diem = recode(Nhom_KhauHao, "Thấp" = 1, "Trung bình" = 2, "Cao" = 3),
Thue_diem = recode(Nhom_ThueDaNop, "Thấp" = 1, "Trung bình" = 2, "Cao" = 3),
TongDiem_HieuQua = LoiNhuan_diem + CFO_diem + KhauHao_diem + Thue_diem)
bctc %>%
select(Năm, TongDiem_HieuQua) %>% arrange(Năm) %>%
kbl_default1() %>%
kable(caption = "Tổng điểm hiệu quả hoạt động theo Năm",
col.names = c("Năm", "Tổng điểm hiệu quả"), align = "rl")| Năm | Tổng điểm hiệu quả |
|---|---|
| 2015 | 6 |
| 2016 | 5 |
| 2017 | 5 |
| 2018 | 7 |
| 2019 | 7 |
| 2020 | 7 |
| 2021 | 10 |
| 2022 | 11 |
| 2023 | 10 |
| 2024 | 12 |
bctc <- bctc %>%
mutate(
Nhom_HieuQua = case_when(
TongDiem_HieuQua <= 5 ~ "Thấp",
TongDiem_HieuQua <= 8 ~ "Trung bình",
TRUE ~ "Cao"))
bctc %>%
select(Năm, TongDiem_HieuQua, Nhom_HieuQua) %>%
arrange(Năm) %>%
kbl_default1() %>%
kable(caption = "Phân loại nhóm hiệu quả hoạt động theo tổng điểm",
col.names = c("Năm" ,"Tổng điểm hiệu quả", "Nhóm Hiệu Quả"), align = "lrl") %>%
kable_styling(latex_options = c("hold_position", "scale_down"),
position = "center")| Năm | Tổng điểm hiệu quả | Nhóm Hiệu Quả |
|---|---|---|
| 2015 | 6 | Trung bình |
| 2016 | 5 | Thấp |
| 2017 | 5 | Thấp |
| 2018 | 7 | Trung bình |
| 2019 | 7 | Trung bình |
| 2020 | 7 | Trung bình |
| 2021 | 10 | Cao |
| 2022 | 11 | Cao |
| 2023 | 10 | Cao |
| 2024 | 12 | Cao |
bctc %>%
select(Năm, Nhom_loi_nhuan, Nhom_CFO, Nhom_KhauHao,
Nhom_ThueDaNop, TongDiem_HieuQua, Nhom_HieuQua) %>% arrange(Năm) %>%
kbl_default1() %>%
kable( format = "latex", booktabs = TRUE,
caption = "Tổng hợp các chỉ số hiệu quả hoạt động kinh doanh đã được mã hóa theo Năm",
col.names = c("Năm", "Nhóm Lợi nhuận", "Nhóm CFO", "Nhóm Khấu hao",
"Nhóm Thuế đã nộp", "Tổng điểm hiệu quả", "Nhóm Hiệu quả"),
align = "lllllrl") %>%
kable_styling(latex_options = c("hold_position", "scale_down"),
position = "center")bctc <- bctc %>%
mutate(
QOE = ifelse(LoiNhuanSauThue != 0, CFO_Tong / LoiNhuanSauThue, NA))
bctc %>%
select(Năm, CFO_Tong, LoiNhuanSauThue, QOE) %>%
arrange(Năm) %>%
kbl_default1() %>%
kable(caption = "Chất lượng thu nhập (QOE)",
col.names = c("Năm", "Dòng tiền từ hoạt động kinh doanh (CFO Tổng)",
"thuế", "QOE"), align = "lrrr")| Năm | Dòng tiền từ hoạt động kinh doanh (CFO Tổng) | thuế | QOE |
|---|---|---|---|
| 2015 | 81.130.888.888 | 92.275.349.999 | 0,8792260 |
| 2016 | 84.650.650.055 | 101.159.344.647 | 0,8368050 |
| 2017 | 97.212.899.364 | 117.360.040.786 | 0,8283305 |
| 2018 | 132.094.454.149 | 138.683.041.628 | 0,9524918 |
| 2019 | 66.590.387.415 | 162.386.686.793 | 0,4100729 |
| 2020 | 73.153.422.780 | 209.696.878.289 | 0,3488532 |
| 2021 | 234.881.036.040 | 189.094.874.963 | 1,2421333 |
| 2022 | 378.603.401.448 | 223.540.317.602 | 1,6936694 |
| 2023 | -30.308.428.665 | 299.556.005.542 | -0,1011778 |
| 2024 | 216.267.565.018 | 320.862.393.082 | 0,6740197 |
bctc <- bctc %>%
mutate(QOE_Nhom = case_when(
QOE >= 1 ~ "Chất lượng cao",
QOE < 1 & QOE >= 0.7 ~ "Chất lượng trung bình",
TRUE ~ "Chất lượng thấp"))
bctc %>%
select(Năm, QOE, QOE_Nhom) %>%
arrange(Năm) %>%
kbl_default1() %>%
kable(caption = "Phân loại chất lượng lợi nhuận",
col.names = c("Năm" ,"QOE", "Kết quả"), align = "rrl")| Năm | QOE | Kết quả |
|---|---|---|
| 2015 | 0,8792260 | Chất lượng trung bình |
| 2016 | 0,8368050 | Chất lượng trung bình |
| 2017 | 0,8283305 | Chất lượng trung bình |
| 2018 | 0,9524918 | Chất lượng trung bình |
| 2019 | 0,4100729 | Chất lượng thấp |
| 2020 | 0,3488532 | Chất lượng thấp |
| 2021 | 1,2421333 | Chất lượng cao |
| 2022 | 1,6936694 | Chất lượng cao |
| 2023 | -0,1011778 | Chất lượng thấp |
| 2024 | 0,6740197 | Chất lượng thấp |
bctc <- bctc %>%
mutate( FCF = CFO_Tong - (- Chi_MuaTSCD))
bctc %>%
select(Năm, CFO_Tong, Chi_MuaTSCD, FCF) %>%
arrange(Năm) %>%
kbl_default1() %>%
kable(caption = "Dòng tiền tự do (FCF)",
col.names = c("Năm", "Dòng tiền từ hoạt động kinh doanh (CFO Tổng)",
"Chi Mua TSCD", "FCF"), align = "rrrr")| Năm | Dòng tiền từ hoạt động kinh doanh (CFO Tổng) | Chi Mua TSCD | FCF |
|---|---|---|---|
| 2015 | 81.130.888.888 | -116.451.196.931 | -35.320.308.043 |
| 2016 | 84.650.650.055 | -103.904.028.053 | -19.253.377.998 |
| 2017 | 97.212.899.364 | -274.456.614.870 | -177.243.715.506 |
| 2018 | 132.094.454.149 | -272.440.024.143 | -140.345.569.994 |
| 2019 | 66.590.387.415 | -131.124.961.007 | -64.534.573.592 |
| 2020 | 73.153.422.780 | -89.684.662.322 | -16.531.239.542 |
| 2021 | 234.881.036.040 | -52.856.687.303 | 182.024.348.737 |
| 2022 | 378.603.401.448 | -99.353.189.519 | 279.250.211.929 |
| 2023 | -30.308.428.665 | -63.529.641.231 | -93.838.069.896 |
| 2024 | 216.267.565.018 | -96.770.733.614 | 119.496.831.404 |
bctc <- bctc %>%
mutate(FCF_Nhom = case_when(
FCF > 0 ~ "Dòng tiền dương",
FCF <= 0 ~ "Dòng tiền âm"))
bctc %>%
select(Năm, FCF, FCF_Nhom) %>%
arrange(Năm) %>%
kbl_default1() %>%
kable(caption = "Phân loại dòng tiền tự do theo FCF",
col.names = c("Năm" ,"FCF", "Kết quả"), align = "rrl")| Năm | FCF | Kết quả |
|---|---|---|
| 2015 | -35.320.308.043 | Dòng tiền âm |
| 2016 | -19.253.377.998 | Dòng tiền âm |
| 2017 | -177.243.715.506 | Dòng tiền âm |
| 2018 | -140.345.569.994 | Dòng tiền âm |
| 2019 | -64.534.573.592 | Dòng tiền âm |
| 2020 | -16.531.239.542 | Dòng tiền âm |
| 2021 | 182.024.348.737 | Dòng tiền dương |
| 2022 | 279.250.211.929 | Dòng tiền dương |
| 2023 | -93.838.069.896 | Dòng tiền âm |
| 2024 | 119.496.831.404 | Dòng tiền dương |
bctc <- bctc %>%
mutate(Delta_NWC = BienDong_PhaiThu + BienDong_TonKho - BienDong_PhaiTra)
bctc %>%
select(Năm, BienDong_PhaiThu, BienDong_TonKho, BienDong_PhaiTra, Delta_NWC) %>%
arrange(Năm) %>%
kbl_default1() %>%
kable(caption = "Vốn lưu động thuần (Net Working Capital - NWC)",
col.names = c("Năm", "Biến Động Phải thu", "Biến Động Tồn kho",
"Biến Động Phải trả", "ΔNWC"), align = "rrrrr")| Năm | Biến Động Phải thu | Biến Động Tồn kho | Biến Động Phải trả | ΔNWC |
|---|---|---|---|---|
| 2015 | -41.333.661.601 | 50.382.333.195 | -35.669.331.173 | 44.718.002.767 |
| 2016 | -8.928.274.802 | 10.749.182.912 | -25.111.605.021 | 26.932.513.131 |
| 2017 | -1.437.631.837 | -47.523.201.453 | 23.575.925.481 | -72.536.758.771 |
| 2018 | 22.334.105.781 | -43.797.978.420 | -13.724.008.827 | -7.739.863.812 |
| 2019 | -64.061.938.449 | -25.446.448.742 | 6.749.916.226 | -96.258.303.417 |
| 2020 | -60.835.559.336 | -75.247.048.473 | -49.525.833.086 | -86.556.774.723 |
| 2021 | 115.759.490.658 | -66.128.977.456 | -2.831.326.127 | 52.461.839.329 |
| 2022 | 20.135.831.138 | 52.398.387.880 | 39.579.670.960 | 32.954.548.058 |
| 2023 | -19.991.962.534 | -260.749.238.157 | -38.673.957.017 | -242.067.243.674 |
| 2024 | -83.306.984.898 | -6.180.988.401 | 20.277.800.636 | -109.765.773.935 |
bctc <- bctc %>%
mutate(NWC_Nhom = case_when(
Delta_NWC > 0 ~ "Kẹt vốn",
Delta_NWC <= 0 ~ "Được chiếm dụng vốn"))
bctc %>%
select(Năm, Delta_NWC, NWC_Nhom) %>%
arrange(Năm) %>% kbl_default1() %>%
kable(caption = "Phân loại vốn lưu động thuần theo ΔNWC",
col.names = c("Năm" ,"ΔNWC", "Kết quả"), align = "rrl")| Năm | ΔNWC | Kết quả |
|---|---|---|
| 2015 | 44.718.002.767 | Kẹt vốn |
| 2016 | 26.932.513.131 | Kẹt vốn |
| 2017 | -72.536.758.771 | Được chiếm dụng vốn |
| 2018 | -7.739.863.812 | Được chiếm dụng vốn |
| 2019 | -96.258.303.417 | Được chiếm dụng vốn |
| 2020 | -86.556.774.723 | Được chiếm dụng vốn |
| 2021 | 52.461.839.329 | Kẹt vốn |
| 2022 | 32.954.548.058 | Kẹt vốn |
| 2023 | -242.067.243.674 | Được chiếm dụng vốn |
| 2024 | -109.765.773.935 | Được chiếm dụng vốn |
plots_hist <- list(
ggplot(bctc, aes(x = LoiNhuanSauThue / 1e9 , fill = ..count..)) +
geom_histogram(bins = 10, color = "white") +
scale_fill_gradient(low = "#caf0f8", high = "#0077b6") +
labs(title = "Phân phối Lợi nhuận sau thuế", x = "Lợi nhuận sau thuế (tỷ đồng) ",
y = "Tần suất") +
scale_x_continuous(labels = format_vn) +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", hjust = 0.5, size = 12),
axis.title = element_text(size = 12)),
ggplot(bctc, aes(x = CFO_Tong / 1e9 , fill = ..count..)) +
geom_histogram(bins = 10, color = "white") +
scale_fill_gradient(low = "#ade8f4", high = "#023e8a") +
labs(title = "Phân phối Dòng tiền hoạt động (CFO)", x = "CFO Tổng (tỷ đồng) ",
y = "Tần suất") +
scale_x_continuous(labels = format_vn) +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", hjust = 0.5, size = 12),
axis.title = element_text(size = 12)))
grid.arrange(
grobs = plots_hist,ncol = 1,
top = textGrob(
"Phân phối các chỉ số hiệu quả hoạt động kinh doanh",
gp = grid::gpar(fontsize = 16, fontface = "bold")))plots_hist1 <- list( ggplot(bctc, aes(x = KhauHao / 1e9 , fill = ..count..)) +
geom_histogram(bins = 10, color = "white") +
scale_fill_gradient(low = "#90e0ef", high = "#0077b6") +
labs(title = "Phân phối Khấu hao", x = "Khấu hao (tỷ đồng)", y = "Tần suất") +
scale_x_continuous(labels = format_vn) +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", hjust = 0.5, size = 14),
axis.title = element_text(size = 12)),
ggplot(bctc, aes(x = FCF / 1e9 , fill = ..count..)) +
geom_histogram(bins = 10, color = "white") +
scale_fill_gradient(low = "#48cae4", high = "#03045e") +
labs(title = "Phân phối Dòng tiền tự do (FCF)", x = "FCF (tỷ đồng) ",
y = "Tần suất") +
scale_x_continuous(labels = format_vn) +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", hjust = 0.5, size = 14),
axis.title = element_text(size = 12)))
grid.arrange(grobs = plots_hist1, ncol = 1,
top = textGrob(
"Phân phối các chỉ số hiệu quả hoạt động kinh doanh (tiếp)",
gp = gpar(fontsize = 16, fontface = "bold")))QOE_nam <- bctc %>%
group_by(Năm) %>%
summarise(QOE_trungbinh = mean(QOE, na.rm = TRUE)) %>%
mutate(QOE_trungbinh = round(QOE_trungbinh * 100, 2))
QOE_nam %>% arrange(Năm) %>%
kbl_default1() %>%
kable(caption = "Tỷ lệ chất lượng thu nhập (QOE) trung bình theo Năm",
col.names = c("Năm", "QOE trung bình (%)"), align = "rr")| Năm | QOE trung bình (%) |
|---|---|
| 2015 | 87,92 |
| 2016 | 83,68 |
| 2017 | 82,83 |
| 2018 | 95,25 |
| 2019 | 41,01 |
| 2020 | 34,89 |
| 2021 | 124,21 |
| 2022 | 169,37 |
| 2023 | -10,12 |
| 2024 | 67,40 |
QOE_nam %>%
ggplot(aes(x = Năm, y = QOE_trungbinh)) +
geom_line(color = "red", size = 1.2) +
geom_point(color = "#CC0000", size = 3) +
geom_area(fill = "pink", alpha = 0.5) +
geom_text(
aes(label = format_vn(QOE_trungbinh, 2)), vjust = -0.8, size = 4, color = "black",
fontface = "bold") +
geom_hline(yintercept = 0, linetype = "dashed", color = "#CC0000") +
scale_y_continuous(limits = c(min(0, QOE_nam$QOE_trungbinh),
max(QOE_nam$QOE_trungbinh) * 1.1)) +
scale_x_continuous(breaks = breaks_pretty(n = 8)) +
labs(title = "XU HƯỚNG CHẤT LƯỢNG THU NHẬP THEO NĂM",
x = "Năm",
y = "QOE trung bình (%)") +
theme_minimal() +
theme(plot.title = element_text(
face = "bold",
hjust = 0.5,
size = 16,
color = "#2C3E50"),
axis.title = element_text(size = 13),
axis.text = element_text(size = 11))FCF_nam <- bctc %>%
group_by(Năm) %>%
summarise(FCF_trungbinh = mean(FCF, na.rm = TRUE)) %>%
mutate(FCF_trungbinh = round(FCF_trungbinh))
FCF_nam %>% arrange(Năm) %>%
kbl_default1() %>%
kable(caption = "Dòng tiền tự do (FCF) trung bình theo Năm",
col.names = c("Năm", "FCF trung bình (VND)"), align = "rr")| Năm | FCF trung bình (VND) |
|---|---|
| 2015 | -35.320.308.043 |
| 2016 | -19.253.377.998 |
| 2017 | -177.243.715.506 |
| 2018 | -140.345.569.994 |
| 2019 | -64.534.573.592 |
| 2020 | -16.531.239.542 |
| 2021 | 182.024.348.737 |
| 2022 | 279.250.211.929 |
| 2023 | -93.838.069.896 |
| 2024 | 119.496.831.404 |
FCF_nam %>%
ggplot(aes(x = Năm, y = FCF_trungbinh / 1e9 )) +
geom_area(fill = "lightgreen", alpha = 0.5) +
geom_hline(yintercept = 0, linetype = "dashed", color = "red", size = 0.8) +
geom_line(color = "darkgreen", size = 1.2) +
geom_point(color = "#003300", size = 3) +
geom_text(aes(
label = paste0(round(FCF_trungbinh / 1e9, 2), " tỷ"),
y = FCF_trungbinh / 1e9,),
vjust = ifelse(FCF_nam$FCF_trungbinh >= 0, -1, 2),
size = 4,
color = "#000",
fontface = "bold") +
scale_x_continuous(breaks = unique(FCF_nam$Năm)) +
scale_y_continuous(labels = scales::comma,
limits = c(-250, 300)) +
labs(
title = "XU HƯỚNG DÒNG TIỀN TỰ DO THEO NĂM",
x = "Năm",
y = "FCF trung bình (tỷ đồng)") +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", hjust = 0.5, size = 16, color = "#2C3E50"),
axis.title = element_text(size = 13),
axis.text = element_text(size = 11))QF <- bctc %>%
select(QOE, FCF) %>%
skim() %>%
select(skim_variable, numeric.mean, numeric.sd, numeric.p0, numeric.p100)
QF %>%
kbl_default1() %>%
kable(caption = "Thống kê mô tả của hai biến QOE và FCF",
col.names = c("Biến", "Trung bình", "Độ lệch chuẩn", "Min", "Max"),
align = "lrrrr")| Biến | Trung bình | Độ lệch chuẩn | Min | Max |
|---|---|---|---|---|
| QOE | 0,7764424 | 0,4948439 | -0,1011778 | 1,693669 |
| FCF | 3.370.453.749,9000001 | 145.775.110.047,9837646 | -177.243.715.506,0000000 | 279.250.211.929,000000 |
cor_matrix <- bctc %>%
select(QOE, FCF) %>%
cor(use = "complete.obs")
cor_matrix_df <- as.data.frame(as.table(cor_matrix))
cor_matrix_df %>%
kbl_default1() %>%
kable(caption = "Ma trận tương quan giữa QOE và FCF",
col.names = c("Biến 1", "Biến 2", "Hệ số tương quan"),align = "llr")| Biến 1 | Biến 2 | Hệ số tương quan |
|---|---|---|
| QOE | QOE | 1,0000000 |
| FCF | QOE | 0,6207924 |
| QOE | FCF | 0,6207924 |
| FCF | FCF | 1,0000000 |
ggplot(cor_matrix_df, aes(x = Var1, y = Var2, fill = Freq)) +
geom_tile(color = "white") +
geom_text(aes(label = scales::comma(Freq, big.mark = ".", decimal.mark = ",", accuracy = 0.0001))) +
scale_fill_gradient2(low = "blue", mid = "white", high = "orange", midpoint = 0,
limits = c(-1, 1), name = "Hệ số tương quan") +
labs(title = "Heatmap ma trận tương quan giữa QOE và FCF",
x = NULL, y = NULL) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 0, hjust = 1))bctc %>%
ggplot(aes(x = QOE, y = FCF / 1e9)) +
geom_point(color = "#ff7f0e", size = 3, alpha = 0.7) +
geom_smooth(method = "lm", color = "#1f77b4", se = TRUE, linewidth = 1.2) +
labs(
title = "MỐI QUAN HỆ GIỮA CHẤT LƯỢNG THU NHẬP (QOE) VÀ DÒNG TIỀN TỰ DO (FCF)",
subtitle = "Đường màu xanh biểu diễn xu hướng tuyến tính giữa hai biến",
x = "Chất lượng thu nhập (QOE)",
y = "Dòng tiền tự do (FCF) (tỷ đồng)") +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", hjust = 0.5, size = 12, color = "#2C3E50"),
plot.subtitle = element_text(hjust = 0.5, size = 10, color = "gray40"),
axis.title = element_text(size = 13),
axis.text = element_text(size = 11) )LN_CFO <- bctc %>%
select(LoiNhuanSauThue, CFO_Tong) %>%
skim() %>%
select(skim_variable, numeric.mean, numeric.sd, numeric.p0, numeric.p100)
LN_CFO %>%
kbl_default1() %>%
kable(caption = "Thống kê mô tả của hai biến Lợi nhuận sau thuế và
Dòng tiền từ hoạt động kinh doanh",
col.names = c("Biến", "Trung bình", "Độ lệch chuẩn", "Min", "Max"),
align = "lrrrr")| Biến | Trung bình | Độ lệch chuẩn | Min | Max |
|---|---|---|---|---|
| LoiNhuanSauThue | 185.461.493.333 | 79.267.830.966 | 92.275.349.999 | 320.862.393.082 |
| CFO_Tong | 133.427.627.649 | 114.796.209.903 | -30.308.428.665 | 378.603.401.448 |
cor_matrix2 <- bctc %>%
select(LoiNhuanSauThue, CFO_Tong) %>%
cor(use = "complete.obs")
cor_matrix2_df <- as.data.frame(as.table(cor_matrix2))
cor_matrix2_df %>%
kbl_default1() %>%
kable(
caption = "Ma trận tương quan giữa Lợi nhuận sau thuế và
Dòng tiền từ hoạt động kinh doanh",
col.names = c("Biến 1", "Biến 2", "Hệ số tương quan"), align = "lrr")| Biến 1 | Biến 2 | Hệ số tương quan |
|---|---|---|
| LoiNhuanSauThue | LoiNhuanSauThue | 1,0000000 |
| CFO_Tong | LoiNhuanSauThue | 0,1689358 |
| LoiNhuanSauThue | CFO_Tong | 0,1689358 |
| CFO_Tong | CFO_Tong | 1,0000000 |
ggplot(cor_matrix2_df, aes(x = Var1, y = Var2, fill = Freq)) +
geom_tile(color = "white") +
geom_text(aes(label = scales::comma(Freq, big.mark = ".", decimal.mark = ",", accuracy = 0.0001))) +
scale_fill_gradient2(low = "#CFCFCF", mid = "#B9D3EE", high = "#8DEEEE", midpoint = 0,
limits = c(-1, 1), name = "Hệ số tương quan") +
labs(title = "Ma trận tương quan giữa LoiNhuanSauThue và CFO Tong",
x = NULL, y = NULL) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 0, hjust = 1))bctc %>%
ggplot(aes(x = LoiNhuanSauThue /1e9 , y = CFO_Tong /1e9)) +
geom_point(color = "#ff7f0e", size = 3, alpha = 0.7) +
geom_smooth(method = "lm", color = "#1f77b4", se = TRUE, linewidth = 1.2) +
scale_x_continuous(labels = format_vn) +
scale_y_continuous(labels = format_vn) +
labs(
title = "MỐI QUAN HỆ GIỮA LỢI NHUẬN SAU THUẾ VÀ DÒNG TIỀN TỪ HOẠT ĐỘNG KINH DOANH",
subtitle = "Đường màu xanh biểu diễn xu hướng tuyến tính giữa hai biến",
x = "Lợi nhuận sau thuế (Tỷ đồng )",
y = "Dòng tiền từ hoạt động kinh doanh (CFO Tổng) (Tỷ đồng)") +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", hjust = 0.5, size = 8, color = "#2C3E50"),
plot.subtitle = element_text(hjust = 0.5, size = 10, color = "gray40"),
axis.title = element_text(size = 13),
axis.text = element_text(size = 11))CFO_CFI_CFF <- bctc %>%
select(CFO_Tong, CFI_Tong, CFF_Tong) %>%
skim() %>%
select(skim_variable, numeric.mean, numeric.sd, numeric.p0, numeric.p100)
CFO_CFI_CFF %>%
kbl_default1() %>%
kable(
caption = "Thống kê mô tả của ba biến CFO Tổng, CFI Tổng, CFF Tổng",
col.names = c("Biến", "Trung bình", "Độ lệch chuẩn", "Min", "Max"),
align = "lrrrr")| Biến | Trung bình | Độ lệch chuẩn | Min | Max |
|---|---|---|---|---|
| CFO_Tong | 133.427.627.649 | 114.796.209.903 | -30.308.428.665 | 378.603.401.448 |
| CFI_Tong | -130.736.762.123 | 137.798.621.319 | -443.246.932.809 | 69.894.262.492 |
| CFF_Tong | -7.647.889.903 | 158.832.664.745 | -271.718.144.243 | 352.371.798.300 |
cor_matrix3 <- bctc %>%
select(CFO_Tong, CFI_Tong, CFF_Tong) %>%
cor(use = "complete.obs")
cor_matrix3_df <- as.data.frame(as.table(cor_matrix3)) %>%
rename(Var1 = Var1, Var2 = Var2, Freq = Freq) %>%
mutate(Freq = round(Freq, 4))
cor_matrix3_df %>%
kbl_default1() %>%
kable(
caption = "Ma trận tương quan giữa CFO Tổng, CFI Tổng, CFF Tổng",
col.names = c("Biến 1", "Biến 2", "Hệ số tương quan"),
allign = "lrrr")| Biến 1 | Biến 2 | Hệ số tương quan |
|---|---|---|
| CFO_Tong | CFO_Tong | 1,0000 |
| CFI_Tong | CFO_Tong | -0,2491 |
| CFF_Tong | CFO_Tong | -0,3623 |
| CFO_Tong | CFI_Tong | -0,2491 |
| CFI_Tong | CFI_Tong | 1,0000 |
| CFF_Tong | CFI_Tong | -0,6370 |
| CFO_Tong | CFF_Tong | -0,3623 |
| CFI_Tong | CFF_Tong | -0,6370 |
| CFF_Tong | CFF_Tong | 1,0000 |
ggplot(cor_matrix3_df, aes(x = Var2, y = Var1, fill = Freq)) +
geom_tile(color = "white") +
geom_text(aes(label = scales::comma(Freq, big.mark = ".", decimal.mark = ",", accuracy = 0.0001))) +
scale_fill_gradient2(low = "blue", mid = "white", high = "red", midpoint = 0,
limits = c(-1, 1), name = "Hệ số tương quan") +
labs(title = "Ma trận tương quan giữa CFO Tong, CFI Tong, CFF Tong",
x = NULL, y = NULL) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 0, hjust = 0.5))df_sum <- bctc %>%
select(Năm, CFO_Tong, CFI_Tong, CFF_Tong) %>%
mutate(NetCash = CFO_Tong + CFI_Tong + CFF_Tong)
waterfall_df <- bctc %>%
summarise(
CFO_Tong = sum(CFO_Tong, na.rm = TRUE),
CFI_Tong = sum(CFI_Tong, na.rm = TRUE),
CFF_Tong = sum(CFF_Tong, na.rm = TRUE)
) %>%
pivot_longer(cols = everything(), names_to = "label", values_to = "value") %>%
mutate(value = value / 1e9) %>%
mutate(value_label = sprintf("%.2f", value))
waterfall_df$value <- as.numeric(waterfall_df$value)
net_cash_flow_value <- sum(waterfall_df$value)
total_label_text <- sprintf("%.2f", net_cash_flow_value)
waterfall(waterfall_df,
calc_total = TRUE,
total_axis_text = "Net Cash Flow" ,
rect_text_labels = waterfall_df$value_label,
total_rect_text = total_label_text ) +
scale_y_continuous(labels = format_vn) +
labs(
title = "BIỂU DIỄN DÒNG TIỀN TỪ HOẠT ĐỘNG KINH DOANH, ĐẦU TƯ VÀ TÀI CHÍNH",
x = "Loại Dòng Tiền",
y = "Giá Trị (Tỷ đồng)",) +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", hjust = 0.5, size = 12, color = "#2C3E50"),
axis.title = element_text(size = 13),
axis.text = element_text(size = 11) )cor_matrix4 <- bctc %>%
select(LoiNhuanSauThue, CFO_Tong, FCF) %>%
cor(use = "complete.obs")
cor_matrix4_df <- as.data.frame(as.table(cor_matrix4))
cor_matrix4_df %>%
kbl_default1() %>%
kable(
caption = "Ma trận tương quan giữa Lợi nhuận sau thuế, CFO Tổng, và FCF",
col.names = c("Biến 1", "Biến 2", "Hệ số tương quan"), align = "llr")| Biến 1 | Biến 2 | Hệ số tương quan |
|---|---|---|
| LoiNhuanSauThue | LoiNhuanSauThue | 1,0000000 |
| CFO_Tong | LoiNhuanSauThue | 0,1689358 |
| FCF | LoiNhuanSauThue | 0,3981548 |
| LoiNhuanSauThue | CFO_Tong | 0,1689358 |
| CFO_Tong | CFO_Tong | 1,0000000 |
| FCF | CFO_Tong | 0,8425615 |
| LoiNhuanSauThue | FCF | 0,3981548 |
| CFO_Tong | FCF | 0,8425615 |
| FCF | FCF | 1,0000000 |
ggplot(cor_matrix4_df, aes(x = Var1, y = Var2, fill = Freq)) +
geom_tile(color = "white") +
geom_text(
aes(label = scales::comma(Freq, big.mark = ".", decimal.mark = ",", accuracy = 0.0001)),
color = "black",
size = 5) +
scale_fill_gradient2(low = "blue", mid = "white", high = "orange", midpoint = 0,
limits = c(-1, 1), name = "Hệ số tương quan") +
labs(title = "Ma trận tương quan giữa LoiNhuanSauThue, CFO Tong, FCF",
x = NULL, y = NULL) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 0, hjust = 1))bctc %>%
mutate(
LNST_ty = LoiNhuanSauThue / 1e9,
CFO_ty = CFO_Tong / 1e9,
FCF_ty = FCF / 1e9 ) %>%
ggplot(aes(x = LNST_ty, y = CFO_ty, color = FCF_ty)) +
geom_point(size = 3, alpha = 0.7) +
geom_smooth(method = "lm", color = "#1f77b4", se = TRUE, linewidth = 1.2) +
scale_x_continuous(labels = label_comma(), n.breaks = 8) +
scale_y_continuous(labels = label_comma(), n.breaks = 10) +
scale_color_continuous(labels = label_comma()) +
labs(
title = "MỐI QUAN HỆ GIỮA LỢI NHUẬN SAU THUẾ, CFO (tỷ VND), FCF (tỷ VND)",
subtitle = "Đường màu xanh biểu diễn xu hướng tuyến tính giữa hai biến",
x = "Lợi nhuận sau thuế (tỷ VND)",
y = "Dòng tiền từ hoạt động kinh doanh (CFO) (tỷ VND)",
color = "Dòng tiền tự do (FCF) (tỷ VND)") +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", hjust = 0.5, size = 12, color = "#2C3E50"),
plot.subtitle = element_text(hjust = 0.5, size = 10, color = "gray40"),
axis.title = element_text(size = 13),
axis.text = element_text(size = 11),
legend.position = "bottom",
legend.direction = "horizontal" )NWC_nam <- bctc %>%
group_by(Năm) %>%
summarise(Delta_NWC_trungbinh = mean(Delta_NWC, na.rm = TRUE)) %>%
mutate(Delta_NWC_trungbinh = round(Delta_NWC_trungbinh))
NWC_nam %>% arrange(Năm) %>%
kbl_default1() %>%
kable(
caption = "Biến động vốn lưu động (ΔNWC) trung bình theo Năm",
col.names = c("Năm", "ΔNWC trung bình (VND)"), align = "rr")| Năm | ΔNWC trung bình (VND) |
|---|---|
| 2015 | 44.718.002.767 |
| 2016 | 26.932.513.131 |
| 2017 | -72.536.758.771 |
| 2018 | -7.739.863.812 |
| 2019 | -96.258.303.417 |
| 2020 | -86.556.774.723 |
| 2021 | 52.461.839.329 |
| 2022 | 32.954.548.058 |
| 2023 | -242.067.243.674 |
| 2024 | -109.765.773.935 |
NWC_nam %>%
ggplot(aes(x = Năm, y = Delta_NWC_trungbinh / 1e9)) +
geom_line(color = "orange", size = 1.2) +
geom_point(color = "#CC3300", size = 3) +
geom_segment(aes(x = Năm,
xend = Năm,
y = Delta_NWC_trungbinh / 1e9,
yend = (Delta_NWC_trungbinh + max(NWC_nam$Delta_NWC_trungbinh) * 0.09) / 1e9),
color = "#CC3300", linewidth = 0.5) +
geom_text(aes(
label = format_vn(Delta_NWC_trungbinh / 1e9, 2),
y = (Delta_NWC_trungbinh + max(NWC_nam$Delta_NWC_trungbinh) * 0.2 ) / 1e9 ),
size = 4,
color = "red",
fontface = "bold") +
scale_x_continuous(breaks = unique(NWC_nam$Năm)) +
labs(
title = "XU HƯỚNG BIẾN ĐỘNG VỐN LƯU ĐỘNG (ΔNWC) THEO NĂM",
x = "Năm",
y = "ΔNWC trung bình (tỷ đồng)" ) +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", hjust = 0.5, size = 16, color = "#2C3E50"),
axis.title = element_text(size = 13),
axis.text = element_text(size = 11) )