Chương 1: Trình bày về bộ dữ liệu về hiệu suất và năng suất của nhân viên

I. GIỚI THIỆU VỀ BỘ DỮ LIỆU

1.1. Đọc dữ liệu

library(readxl)
## Warning: package 'readxl' was built under R version 4.5.1
Data <- read_excel("D:/NNLT/Data.xlsx")

Câu lệnh này giúp nhập toàn bộ bộ dữ liệu nhân sự (thông tin như lương, tuổi, giới tính, phòng ban, điểm hài lòng, v.v.) vào R để bắt đầu phân tích.

1.2. Xem qua dữ liệu

head(Data)
## # A tibble: 6 × 20
##   Employee_ID Department       Gender   Age Job_Title Hire_Date Years_At_Company
##         <dbl> <chr>            <chr>  <dbl> <chr>     <chr>                <dbl>
## 1           1 IT               Male      55 Speciali… 2022-01-…                2
## 2           2 Finance          Male      29 Developer 2024-04-…                0
## 3           3 Finance          Male      55 Speciali… 2015-10-…                8
## 4           4 Customer Support Female    48 Analyst   2016-10-…                7
## 5           5 Engineering      Female    36 Analyst   2021-07-…                3
## 6           6 IT               Male      43 Manager   2016-08-…                8
## # ℹ 13 more variables: Education_Level <chr>, Performance_Score <dbl>,
## #   Monthly_Salary <chr>, Work_Hours_Per_Week <dbl>, Projects_Handled <dbl>,
## #   Overtime_Hours <dbl>, Sick_Days <dbl>, Remote_Work_Frequency <dbl>,
## #   Team_Size <dbl>, Training_Hours <dbl>, Promotions <dbl>,
## #   Employee_Satisfaction_Score <chr>, Resigned <lgl>

Lệnh head(Data) giúp nhanh chóng kiểm tra dữ liệu nhập có đúng hay chưa, đồng thời hình dung cấu trúc tổng quan của bộ dữ liệu nhân viên trước khi bắt đầu các bước xử lý tiếp theo.

1.3. Kiểm tra kích thước dữ liệu

dim(Data)
## [1] 100000     20

Dữ liệu thô có 100000 quan sát và 20 biến.

1.4. Kiểm tra tên biến

names(Data)
##  [1] "Employee_ID"                 "Department"                 
##  [3] "Gender"                      "Age"                        
##  [5] "Job_Title"                   "Hire_Date"                  
##  [7] "Years_At_Company"            "Education_Level"            
##  [9] "Performance_Score"           "Monthly_Salary"             
## [11] "Work_Hours_Per_Week"         "Projects_Handled"           
## [13] "Overtime_Hours"              "Sick_Days"                  
## [15] "Remote_Work_Frequency"       "Team_Size"                  
## [17] "Training_Hours"              "Promotions"                 
## [19] "Employee_Satisfaction_Score" "Resigned"

Lệnh names(Data) giúp xác định rõ các biến có trong bộ dữ liệu nhân sự, là bước quan trọng để hiểu cấu trúc dữ liệu và định hướng các phân tích tiếp theo.

1.5. Giải thích ý nghĩa các biến trong bộ dữ liệu

variable_meaning <- data.frame(
  Variable = c(
    "Employee_ID",
    "Department",
    "Gender",
    "Age",
    "Job_Title",
    "Hire_Date",
    "Years_At_Company",
    "Education_Level",
    "Performance_Score",
    "Monthly_Salary",
    "Work_Hours_Per_Week",
    "Projects_Handled",
    "Overtime_Hours",
    "Sick_Days",
    "Remote_Work_Frequency",
    "Team_Size",
    "Training_Hours",
    "Promotions",
    "Employee_Satisfaction_Score",
    "Resigned"
  ),
  
  Meaning = c(
    "Mã định danh duy nhất của mỗi nhân viên",
    "Phòng ban mà nhân viên đang làm việc (như IT, HR, Sales,...)",
    "Giới tính của nhân viên (Nam/Nữ)",
    "Tuổi của nhân viên (tính bằng năm)",
    "Chức danh công việc hiện tại của nhân viên",
    "Ngày bắt đầu làm việc tại công ty",
    "Số năm nhân viên đã làm việc tại công ty",
    "Trình độ học vấn cao nhất của nhân viên (Cao đẳng, Đại học, Sau đại học,...)",
    "Điểm đánh giá hiệu suất làm việc (từ 1 đến 5)",
    "Mức lương hàng tháng của nhân viên",
    "Số giờ làm việc trung bình mỗi tuần của nhân viên",
    "Số dự án mà nhân viên đã hoặc đang phụ trách",
    "Số giờ làm thêm (overtime) trung bình mỗi tháng",
    "Số ngày nghỉ ốm của nhân viên trong năm",
    "Tần suất làm việc từ xa",
    "Quy mô nhóm hoặc đội mà nhân viên tham gia",
    "Tổng số giờ tham gia các khóa đào tạo",
    "Số lần được thăng chức của nhân viên",
    "Mức độ hài lòng của nhân viên (từ 0 đến 5)",
    "Trạng thái nghỉ việc của nhân viên (TRUE = đã nghỉ, FALSE = còn làm)"
  ),
  
  stringsAsFactors = FALSE
)

# Hiển thị bảng 
library(knitr)
kable(variable_meaning, booktabs = TRUE, caption = "Giải thích ý nghĩa các biến trong bộ dữ liệu nhân sự")
Giải thích ý nghĩa các biến trong bộ dữ liệu nhân sự
Variable Meaning
Employee_ID Mã định danh duy nhất của mỗi nhân viên
Department Phòng ban mà nhân viên đang làm việc (như IT, HR, Sales,…)
Gender Giới tính của nhân viên (Nam/Nữ)
Age Tuổi của nhân viên (tính bằng năm)
Job_Title Chức danh công việc hiện tại của nhân viên
Hire_Date Ngày bắt đầu làm việc tại công ty
Years_At_Company Số năm nhân viên đã làm việc tại công ty
Education_Level Trình độ học vấn cao nhất của nhân viên (Cao đẳng, Đại học, Sau đại học,…)
Performance_Score Điểm đánh giá hiệu suất làm việc (từ 1 đến 5)
Monthly_Salary Mức lương hàng tháng của nhân viên
Work_Hours_Per_Week Số giờ làm việc trung bình mỗi tuần của nhân viên
Projects_Handled Số dự án mà nhân viên đã hoặc đang phụ trách
Overtime_Hours Số giờ làm thêm (overtime) trung bình mỗi tháng
Sick_Days Số ngày nghỉ ốm của nhân viên trong năm
Remote_Work_Frequency Tần suất làm việc từ xa
Team_Size Quy mô nhóm hoặc đội mà nhân viên tham gia
Training_Hours Tổng số giờ tham gia các khóa đào tạo
Promotions Số lần được thăng chức của nhân viên
Employee_Satisfaction_Score Mức độ hài lòng của nhân viên (từ 0 đến 5)
Resigned Trạng thái nghỉ việc của nhân viên (TRUE = đã nghỉ, FALSE = còn làm)

Đoạn mã này giúp hệ thống hóa toàn bộ thông tin về các biến trong bộ dữ liệu nhân sự.

1.6. Xem kiểu dữ liệu của từng cột

str(Data)
## tibble [100,000 × 20] (S3: tbl_df/tbl/data.frame)
##  $ Employee_ID                : num [1:100000] 1 2 3 4 5 6 7 8 9 10 ...
##  $ Department                 : chr [1:100000] "IT" "Finance" "Finance" "Customer Support" ...
##  $ Gender                     : chr [1:100000] "Male" "Male" "Male" "Female" ...
##  $ Age                        : num [1:100000] 55 29 55 48 36 43 37 55 55 45 ...
##  $ Job_Title                  : chr [1:100000] "Specialist" "Developer" "Specialist" "Analyst" ...
##  $ Hire_Date                  : chr [1:100000] "2022-01-19 08:03:05.556036" "2024-04-18 08:03:05.556036" "2015-10-26 08:03:05.556036" "2016-10-22 08:03:05.556036" ...
##  $ Years_At_Company           : num [1:100000] 2 0 8 7 3 8 1 9 1 7 ...
##  $ Education_Level            : chr [1:100000] "High School" "High School" "High School" "Bachelor" ...
##  $ Performance_Score          : num [1:100000] 5 5 3 2 2 3 5 2 2 1 ...
##  $ Monthly_Salary             : chr [1:100000] "6750.0" "7500.0" "5850.0" "4800.0" ...
##  $ Work_Hours_Per_Week        : num [1:100000] 33 34 37 52 38 46 55 42 51 41 ...
##  $ Projects_Handled           : num [1:100000] 32 34 27 10 11 31 20 46 23 33 ...
##  $ Overtime_Hours             : num [1:100000] 22 13 6 28 29 8 29 7 21 2 ...
##  $ Sick_Days                  : num [1:100000] 2 14 3 12 13 0 2 8 14 6 ...
##  $ Remote_Work_Frequency      : num [1:100000] 0 100 50 100 100 100 0 100 0 75 ...
##  $ Team_Size                  : num [1:100000] 14 12 10 10 15 15 16 7 1 4 ...
##  $ Training_Hours             : num [1:100000] 66 61 1 0 9 95 27 64 0 53 ...
##  $ Promotions                 : num [1:100000] 0 2 0 1 1 0 0 0 1 2 ...
##  $ Employee_Satisfaction_Score: chr [1:100000] "2.63" "1.72" "3.17" "1.86" ...
##  $ Resigned                   : logi [1:100000] FALSE FALSE FALSE FALSE FALSE FALSE ...

Lệnh str(Data) cho ta cái nhìn tổng quan về cấu trúc và kiểu dữ liệu của bộ nhân sự.

1.7. Kiểm tra dữ liệu bị thiếu

colSums(is.na(Data))
##                 Employee_ID                  Department 
##                           0                           0 
##                      Gender                         Age 
##                           0                           0 
##                   Job_Title                   Hire_Date 
##                           0                           0 
##            Years_At_Company             Education_Level 
##                           0                           0 
##           Performance_Score              Monthly_Salary 
##                           0                           0 
##         Work_Hours_Per_Week            Projects_Handled 
##                           0                           0 
##              Overtime_Hours                   Sick_Days 
##                           0                           0 
##       Remote_Work_Frequency                   Team_Size 
##                           0                           0 
##              Training_Hours                  Promotions 
##                           0                           0 
## Employee_Satisfaction_Score                    Resigned 
##                           0                           0

Lệnh colSums(is.na(Data)) giúp bạn phát hiện dữ liệu bị thiếu trong từng biến.

1.8. Kiểm tra dữ liệu trùng lặp

sum(duplicated(Data))
## [1] 0

Lệnh sum(duplicated(Data)) cho biết có bao nhiêu quan sát bị trùng lặp trong dữ liệu. Kết quả = 0 → bộ dữ liệu nhân sự sạch, không trùng lặp.

1.9.Thống kê tổng quan nhanh

summary(Data)
##   Employee_ID      Department           Gender               Age       
##  Min.   :     1   Length:100000      Length:100000      Min.   :22.00  
##  1st Qu.: 25001   Class :character   Class :character   1st Qu.:31.00  
##  Median : 50001   Mode  :character   Mode  :character   Median :41.00  
##  Mean   : 50001                                         Mean   :41.03  
##  3rd Qu.: 75000                                         3rd Qu.:51.00  
##  Max.   :100000                                         Max.   :60.00  
##   Job_Title          Hire_Date         Years_At_Company Education_Level   
##  Length:100000      Length:100000      Min.   : 0.000   Length:100000     
##  Class :character   Class :character   1st Qu.: 2.000   Class :character  
##  Mode  :character   Mode  :character   Median : 4.000   Mode  :character  
##                                        Mean   : 4.476                     
##                                        3rd Qu.: 7.000                     
##                                        Max.   :10.000                     
##  Performance_Score Monthly_Salary     Work_Hours_Per_Week Projects_Handled
##  Min.   :1.000     Length:100000      Min.   :30.00       Min.   : 0.00   
##  1st Qu.:2.000     Class :character   1st Qu.:37.00       1st Qu.:12.00   
##  Median :3.000     Mode  :character   Median :45.00       Median :24.00   
##  Mean   :2.995                        Mean   :44.96       Mean   :24.43   
##  3rd Qu.:4.000                        3rd Qu.:53.00       3rd Qu.:37.00   
##  Max.   :5.000                        Max.   :60.00       Max.   :49.00   
##  Overtime_Hours    Sick_Days      Remote_Work_Frequency   Team_Size    
##  Min.   : 0.00   Min.   : 0.000   Min.   :  0.00        Min.   : 1.00  
##  1st Qu.: 7.00   1st Qu.: 3.000   1st Qu.: 25.00        1st Qu.: 5.00  
##  Median :15.00   Median : 7.000   Median : 50.00        Median :10.00  
##  Mean   :14.51   Mean   : 7.009   Mean   : 50.09        Mean   :10.01  
##  3rd Qu.:22.00   3rd Qu.:11.000   3rd Qu.: 75.00        3rd Qu.:15.00  
##  Max.   :29.00   Max.   :14.000   Max.   :100.00        Max.   :19.00  
##  Training_Hours    Promotions     Employee_Satisfaction_Score  Resigned      
##  Min.   : 0.00   Min.   :0.0000   Length:100000               Mode :logical  
##  1st Qu.:25.00   1st Qu.:0.0000   Class :character            FALSE:89990    
##  Median :49.00   Median :1.0000   Mode  :character            TRUE :10010    
##  Mean   :49.51   Mean   :0.9997                                              
##  3rd Qu.:75.00   3rd Qu.:2.0000                                              
##  Max.   :99.00   Max.   :2.0000

Lệnh summary(Data) giúp hiểu rõ cấu trúc và đặc điểm chung của toàn bộ bộ dữ liệu nhân sự. Biến Age Kết quả: Min = 22, Median = 41, Mean = 41.03, Max = 60 cho thấy Biến số (numeric), giá trị trung bình và trung vị gần bằng nhau → phân bố tuổi khá đều, không bị lệch nhiều.Đa phần nhân viên trong công ty nằm ở độ tuổi trung niên (30–50 tuổi), là nhóm có kinh nghiệm và ổn định nghề nghiệp. Ít nhân viên ở độ tuổi rất trẻ (<25) hoặc gần nghỉ hưu (>60).

1.10. Thống kê mô tả từng biến

library(dplyr)
library(psych)
## Warning: package 'psych' was built under R version 4.5.1
library(moments)

# --- XÁC ĐỊNH DANH SÁCH BIẾN SỐ ---
num_vars <- names(Data)[sapply(Data, is.numeric)]

# --- HÀM THỐNG KÊ MÔ TẢ CHO 1 BIẾN ---
describe_one_var <- function(x) {
  x_no_na <- na.omit(x)
  data.frame(
    Min = min(x_no_na),
    Max = max(x_no_na),
    Mean = mean(x_no_na),
    Median = median(x_no_na),
    SD = sd(x_no_na),
    Variance = var(x_no_na),
    Skewness = skewness(x_no_na),
    Kurtosis = kurtosis(x_no_na)
  )
}
# --- TẠO DANH SÁCH BẢNG THỐNG KÊ CHO TỪNG BIẾN ---
desc_list <- lapply(num_vars, function(var) {
  stats <- describe_one_var(Data[[var]])
  list(Variable = var, Summary = stats)
})

# --- IN RA MỖI BẢNG RIÊNG ---
for (item in desc_list) {
  cat("\n====================================\n")
  cat("Biến:", item$Variable, "\n")
  print(item$Summary)
}
## 
## ====================================
## Biến: Employee_ID 
##   Min   Max    Mean  Median       SD  Variance Skewness Kurtosis
## 1   1 1e+05 50000.5 50000.5 28867.66 833341667        0      1.8
## 
## ====================================
## Biến: Age 
##   Min Max     Mean Median       SD Variance     Skewness Kurtosis
## 1  22  60 41.02941     41 11.24412 126.4302 -0.006169566 1.796472
## 
## ====================================
## Biến: Years_At_Company 
##   Min Max    Mean Median       SD Variance   Skewness Kurtosis
## 1   0  10 4.47607      4 2.869336  8.23309 0.01121056 1.778282
## 
## ====================================
## Biến: Performance_Score 
##   Min Max    Mean Median       SD Variance    Skewness Kurtosis
## 1   1   5 2.99543      3 1.414726 2.001449 0.004008424 1.699362
## 
## ====================================
## Biến: Work_Hours_Per_Week 
##   Min Max     Mean Median       SD Variance    Skewness Kurtosis
## 1  30  60 44.95695     45 8.942003 79.95942 0.009620887 1.795712
## 
## ====================================
## Biến: Projects_Handled 
##   Min Max     Mean Median       SD Variance    Skewness Kurtosis
## 1   0  49 24.43117     24 14.46958 209.3689 0.009681863 1.791757
## 
## ====================================
## Biến: Overtime_Hours 
##   Min Max     Mean Median       SD Variance     Skewness Kurtosis
## 1   0  29 14.51493     15 8.664026 75.06535 -0.001166502 1.796839
## 
## ====================================
## Biến: Sick_Days 
##   Min Max    Mean Median       SD Variance     Skewness Kurtosis
## 1   0  14 7.00855      7 4.331591 18.76268 -0.003320354 1.783845
## 
## ====================================
## Biến: Remote_Work_Frequency 
##   Min Max    Mean Median       SD Variance     Skewness Kurtosis
## 1   0 100 50.0905     50 35.35116 1249.704 -0.001900944 1.697277
## 
## ====================================
## Biến: Team_Size 
##   Min Max     Mean Median       SD Variance      Skewness Kurtosis
## 1   1  19 10.01356     10 5.495405 30.19948 -0.0005922356 1.788459
## 
## ====================================
## Biến: Training_Hours 
##   Min Max     Mean Median       SD Variance      Skewness Kurtosis
## 1   0  99 49.50606     49 28.89038 834.6542 -0.0006484809 1.800442
## 
## ====================================
## Biến: Promotions 
##   Min Max    Mean Median        SD  Variance     Skewness Kurtosis
## 1   0   2 0.99972      1 0.8158717 0.6656466 0.0005139954 1.502314

Sau khi thực hiện thống kê mô tả cho các biến định lượng trong bộ dữ liệu nhân sự, ta thu được các chỉ tiêu như giá trị trung bình, độ lệch chuẩn, độ lệch và độ nhọn. Kết quả cho thấy phần lớn các biến như tuổi, số năm làm việc, điểm hiệu suất, số giờ làm việc mỗi tuần có phân bố tương đối cân đối quanh giá trị trung bình (Skewness ≈ 0), chứng tỏ dữ liệu có độ ổn định cao. Một số biến như lương và giờ làm thêm có Skewness dương, cho thấy có một nhóm nhỏ nhân viên có giá trị cao hơn trung bình đáng kể — thường là nhóm có hiệu suất hoặc vị trí cao hơn.

1.11. Phân loại biến theo kiểu dữ liệu

#Chuyển đổi 2 biến từ character → numeric
Data$Monthly_Salary <- as.numeric(Data$Monthly_Salary)
Data$Employee_Satisfaction_Score <- as.numeric(Data$Employee_Satisfaction_Score)
str(Data$Monthly_Salary)
##  num [1:100000] 6750 7500 5850 4800 4800 7800 5250 7200 4200 6050 ...
str(Data$Employee_Satisfaction_Score)
##  num [1:100000] 2.63 1.72 3.17 1.86 1.25 2.77 4.46 2.09 1.44 2.93 ...
# Chuyển đổi biến thành dạng date
Data$Hire_Date <- as.Date(Data$Hire_Date)
# Đếm số biến định lượng
num_vars <- sapply(Data, is.numeric)
sum(num_vars)
## [1] 14
# Đếm số biến định tính
cat_vars <- sapply(Data, function(x) is.character(x) | is.factor(x))
sum(cat_vars)
## [1] 4
# Đếm số biến thời gian
date_vars <- sapply(Data, function(x) inherits(x, "Date") | inherits(x, "POSIXct"))
sum(date_vars)
## [1] 1
# Liệt kê tên biến theo loại
names(Data)[num_vars]    # Định lượng
##  [1] "Employee_ID"                 "Age"                        
##  [3] "Years_At_Company"            "Performance_Score"          
##  [5] "Monthly_Salary"              "Work_Hours_Per_Week"        
##  [7] "Projects_Handled"            "Overtime_Hours"             
##  [9] "Sick_Days"                   "Remote_Work_Frequency"      
## [11] "Team_Size"                   "Training_Hours"             
## [13] "Promotions"                  "Employee_Satisfaction_Score"
names(Data)[cat_vars]    # Định tính
## [1] "Department"      "Gender"          "Job_Title"       "Education_Level"
names(Data)[date_vars]   # Kiểu thời gian
## [1] "Hire_Date"

Sau khi thực hiện phân loại kiểu dữ liệu, ta xác định được: Các biến định lượng gồm các thông tin có thể đo lường bằng số như: tuổi, lương, số năm làm việc, điểm hiệu suất, số giờ làm việc mỗi tuần,… Các biến định tính gồm các thông tin dạng phân loại như: giới tính, phòng ban, trình độ học vấn, chức danh công việc,… Biến thời gian gồm Hire_Date – ngày bắt đầu làm việc. Việc phân loại này giúp lựa chọn phương pháp xử lý và biểu đồ phù hợp cho từng biến, đảm bảo phân tích đúng bản chất dữ liệu nhân sự.

1.12. Tạo bảng tóm tắt nhóm

library(dplyr)
Data %>%
  group_by(Department) %>%
  summarise(
    Mean_Salary = mean(Monthly_Salary),
    Mean_Performance = mean(Performance_Score)
  )
## # A tibble: 9 × 3
##   Department       Mean_Salary Mean_Performance
##   <chr>                  <dbl>            <dbl>
## 1 Customer Support       6404.             3.00
## 2 Engineering            6417.             3.02
## 3 Finance                6399.             2.98
## 4 HR                     6400.             3.00
## 5 IT                     6415.             3   
## 6 Legal                  6391.             2.98
## 7 Marketing              6378.             2.98
## 8 Operations             6412.             3.01
## 9 Sales                  6413.             2.99

Lệnh group_by(Department) nhóm dữ liệu theo từng phòng ban. Hàm summarise() sau đó tính giá trị trung bình (mean) của hai biến định lượng là Monthly_Salary (lương trung bình) và Performance_Score (điểm hiệu suất trung bình) trong từng nhóm. Kết quả hiển thị dạng bảng tóm tắt (tibble), gồm 3 cột: Department: tên phòng ban. Mean_Salary: lương trung bình của nhân viên trong phòng ban đó. Mean_Performance: điểm hiệu suất trung bình của phòng ban. Bảng này cho thấy mức lương trung bình và hiệu suất làm việc trung bình của từng phòng ban trong công ty. Ví dụ: phòng Engineering có Mean_Salary và Mean_Performance cao hơn một chút, cho thấy nhân viên ở đây được trả lương tốt và có năng suất cao hơn mức trung bình. Ngược lại, các phòng như Marketing hay Finance có giá trị thấp hơn một chút, có thể phản ánh tính chất công việc hoặc chính sách đãi ngộ khác nhau giữa các bộ phận.

II. XỬ LÝ DỮ LIỆU THÔ VÀ MÃ HÓA DỮ LIỆU

2.1. Chuyển kiểu dữ liệu

Data$Department <- as.factor(Data$Department)
Data$Gender <- as.factor(Data$Gender)

Trong quá trình xử lý dữ liệu, hai biến Department (phòng ban) và Gender (giới tính) ban đầu có kiểu dữ liệu character. Để đảm bảo việc phân tích nhóm và trực quan hóa dữ liệu được chính xác, hai biến này được chuyển đổi sang kiểu factor bằng hàm as.factor() trong R. Biến Department thể hiện phòng ban làm việc của nhân viên (như IT, HR, Sales, Finance,…), là cơ sở để so sánh các chỉ tiêu như lương, hiệu suất giữa các phòng ban. Biến Gender biểu thị giới tính nhân viên (Nam/Nữ), hỗ trợ phân tích sự khác biệt về lương, mức độ hài lòng giữa hai giới.

2.2. Chuẩn hóa chữ viết trong các biến text

library(stringr)
Data$Job_Title <- stringr::str_to_title(Data$Job_Title)
Data$Department <- stringr::str_replace_all(Data$Department, "Dept\\.|Department", "")

Việc chuẩn hóa này đảm bảo các giá trị trong biến Department và Job_Title được đồng nhất, từ đó tránh trùng lặp khi phân tích, giúp cho các thống kê về mức lương, hiệu suất hoặc sự hài lòng theo chức danh/phòng ban trở nên chính xác và đáng tin cậy hơn.

2.3. Phát hiện ngoại lai

library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.5.1
## 
## Attaching package: 'ggplot2'
## The following objects are masked from 'package:psych':
## 
##     %+%, alpha
# Chọn một vài biến định lượng chính để kiểm tra
numeric_vars <- c("Monthly_Salary", "Work_Hours_Per_Week", "Projects_Handled",
                  "Overtime_Hours", "Training_Hours")

# Vẽ biểu đồ boxplot cho từng biến
for (var in numeric_vars) {
  p <- ggplot(Data, aes_string(y = var)) +
    geom_boxplot(fill = "steelblue", outlier.color = "red", outlier.size = 2) +
    labs(title = paste("Phát hiện giá trị ngoại lai -", var),
         y = var) +
    theme_minimal()
  print(p)
}
## Warning: `aes_string()` was deprecated in ggplot2 3.0.0.
## ℹ Please use tidy evaluation idioms with `aes()`.
## ℹ See also `vignette("ggplot2-in-packages")` for more information.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

Hàm geom_boxplot() trong ggplot2 giúp trực quan hóa phân bố dữ liệu và xác định giá trị ngoại lai (outlier) thông qua các điểm màu đỏ nằm ngoài khoảng tứ phân vị (IQR). aes_string(y = var) cho phép lặp tự động qua nhiều biến, tiết kiệm thời gian và tăng tính linh hoạt. Các điểm outlier.color = “red” biểu thị những giá trị nằm ngoài phạm vi thông thường của biến. Việc phát hiện ngoại lai giúp xác định các trường hợp bất thường trong dữ liệu nhân sự, ví dụ: Mức lương cao đột biến có thể là nhân viên cấp quản lý hoặc lỗi nhập liệu. Giờ làm thêm (Overtime_Hours) quá cao có thể phản ánh áp lực công việc hoặc phân bổ nguồn lực chưa hợp lý. Số giờ đào tạo quá lớn có thể là chương trình huấn luyện đặc biệt hoặc lỗi ghi nhận dữ liệu. Bước này giúp đảm bảo độ tin cậy và tính hợp lý của dữ liệu đầu vào

2.5. Lọc ra các giá trị ngoại lai cụ thể

for (var in numeric_vars) {
  Q1 <- quantile(Data[[var]], 0.25, na.rm = TRUE)
  Q3 <- quantile(Data[[var]], 0.75, na.rm = TRUE)
  IQR_value <- Q3 - Q1
  
  outliers <- Data %>%
    filter(Data[[var]] > (Q3 + 1.5 * IQR_value) | Data[[var]] < (Q1 - 1.5 * IQR_value))
  
  cat("Biến:", var, "- Số lượng giá trị ngoại lai:", nrow(outliers), "\n")
}
## Biến: Monthly_Salary - Số lượng giá trị ngoại lai: 0 
## Biến: Work_Hours_Per_Week - Số lượng giá trị ngoại lai: 0 
## Biến: Projects_Handled - Số lượng giá trị ngoại lai: 0 
## Biến: Overtime_Hours - Số lượng giá trị ngoại lai: 0 
## Biến: Training_Hours - Số lượng giá trị ngoại lai: 0

Mục đích: Trong quá trình phân tích dữ liệu, việc phát hiện các giá trị ngoại lai (outliers) giúp đảm bảo độ tin cậy của các phép thống kê và mô hình dự đoán. Các giá trị bất thường có thể làm sai lệch kết quả hoặc phản ánh các trường hợp đặc biệt (ví dụ: nhân viên có lương quá cao, làm việc quá giờ,…). Mỗi biến được kiểm tra dựa trên khoảng tứ phân vị (IQR): Giá trị nằm ngoài khoảng [Q1 - 1.5×IQR, Q3 + 1.5×IQR] được xem là ngoại lai. Kết quả cho thấy tất cả 5 biến định lượng chính đều không có giá trị nằm ngoài khoảng này. Điều đó chứng tỏ dữ liệu sạch, ổn định, không có điểm bất thường trong các biến về lương, giờ làm việc, dự án, làm thêm, hay đào tạo. Các biến phản ánh hiệu suất và điều kiện làm việc của nhân viên có sự phân bố hợp lý — ví dụ: Không có nhân viên nào có mức lương hay giờ làm vượt trội bất thường. Số lượng dự án, giờ đào tạo và làm thêm đều nằm trong giới hạn bình thường. Điều này giúp đảm bảo rằng khi phân tích hiệu suất làm việc, mức độ hài lòng, hoặc dự đoán nghỉ việc, kết quả sẽ không bị ảnh hưởng bởi giá trị cực đoan. Bộ dữ liệu nhân sự được xây dựng khá hoàn chỉnh, không tồn tại giá trị ngoại lai đáng kể. Do đó, không cần thực hiện bước loại bỏ hoặc xử lý ngoại lai, có thể chuyển sang bước tiếp theo (chuẩn hóa và mã hóa dữ liệu).

2.4. Mã hóa biến định tính

Data$Gender_Code <- ifelse(Data$Gender == "Male", 1, ifelse(Data$Gender == "Female", 0, 2))

2.5. Tạo biến mới

Data$Income_per_Hour <- Data$Monthly_Salary / (4 * Data$Work_Hours_Per_Week)
Data$Tenure_Years <- as.numeric(difftime(Sys.Date(), Data$Hire_Date, units = "days")) / 365

2.6. Chuẩn hóa thang đo

Data$Monthly_Salary_Scaled <- scale(Data$Monthly_Salary)

2.7. Gộp nhóm độ tuổi

Data$Age_Group <- cut(Data$Age, breaks=c(20,30,40,50,60), labels=c("20-30","31-40","41-50","51-60"))

2.8. Kiểm tra giá trị bất hợp lí ở biến Age

summary(Data$Age)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   22.00   31.00   41.00   41.03   51.00   60.00
Data %>% filter(Age < 18 | Age > 65)
## # A tibble: 0 × 25
## # ℹ 25 variables: Employee_ID <dbl>, Department <chr>, Gender <fct>, Age <dbl>,
## #   Job_Title <chr>, Hire_Date <date>, Years_At_Company <dbl>,
## #   Education_Level <chr>, Performance_Score <dbl>, Monthly_Salary <dbl>,
## #   Work_Hours_Per_Week <dbl>, Projects_Handled <dbl>, Overtime_Hours <dbl>,
## #   Sick_Days <dbl>, Remote_Work_Frequency <dbl>, Team_Size <dbl>,
## #   Training_Hours <dbl>, Promotions <dbl>, Employee_Satisfaction_Score <dbl>,
## #   Resigned <lgl>, Gender_Code <dbl>, Income_per_Hour <dbl>, …

2.9. Kiểm tra sự tương quan

library(corrplot)
## Warning: package 'corrplot' was built under R version 4.5.1
## corrplot 0.95 loaded
corr_data <- Data %>% 
  select(Monthly_Salary, Performance_Score, Age, Years_At_Company, Training_Hours)
corrplot(cor(corr_data), method = "circle")

### 2.10. Mã hóa thứ bậc cho trình độ học vấn

Data$Education_Level <- factor(Data$Education_Level,
                               levels = c("High School", "Bachelor", "Master", "PhD"),
                               ordered = TRUE)
Data$Education_Code <- as.numeric(Data$Education_Level)

2.11. Chuẩn hóa phân phối dữ liệu lệch (log transformation)

Data$Salary_log <- log(Data$Monthly_Salary)

2.12. Gán nhãn mới cho biến logic (Resigned)

Data$Resigned_Label <- ifelse(Data$Resigned == TRUE, "Đã nghỉ việc", "Còn làm việc")

2.13. Phân loại hiệu suất làm việc

Data$Performance_Level <- cut(Data$Performance_Score,
                              breaks = c(0,2,3.5,5),
                              labels = c("Thấp", "Trung bình", "Cao"))

2.14. Phát hiện giá trị bất thường theo z-score

z_salary <- scale(Data$Monthly_Salary)
Data$outlier_flag <- ifelse(abs(z_salary) > 3, 1, 0)
table(Data$outlier_flag)
## 
##      0 
## 100000

2.15. Chuẩn hóa định dạng số thập phân

Data$Monthly_Salary <- round(Data$Monthly_Salary, 0)
Data$Performance_Score <- round(Data$Performance_Score, 1)

III. THỐNG KÊ CƠ BẢN

install.packages("skimr")
## Installing package into 'C:/Users/Admin/AppData/Local/R/win-library/4.5'
## (as 'lib' is unspecified)
## package 'skimr' successfully unpacked and MD5 sums checked
## 
## The downloaded binary packages are in
##  C:\Users\Admin\AppData\Local\Temp\RtmpKYkmzk\downloaded_packages
install.packages("corrplot")
## Warning: package 'corrplot' is in use and will not be installed
library(dplyr)
library(ggplot2)
library(psych)
library(skimr)
## Warning: package 'skimr' was built under R version 4.5.1
library(corrplot)

3.1. Thống kê các biến định lượng

describe(Data)
## Warning in FUN(newX[, i], ...): no non-missing arguments to min; returning Inf
## Warning in FUN(newX[, i], ...): no non-missing arguments to min; returning Inf
## Warning in FUN(newX[, i], ...): no non-missing arguments to max; returning -Inf
## Warning in FUN(newX[, i], ...): no non-missing arguments to max; returning -Inf
##                             vars     n     mean       sd   median  trimmed
## Employee_ID                    1 1e+05 50000.50 28867.66 50000.50 50000.50
## Department*                    2 1e+05     5.01     2.58     5.00     5.01
## Gender*                        3 1e+05     1.56     0.57     2.00     1.52
## Age                            4 1e+05    41.03    11.24    41.00    41.04
## Job_Title*                     5 1e+05     4.01     2.00     4.00     4.01
## Hire_Date                      6 1e+05      NaN       NA       NA      NaN
## Years_At_Company               7 1e+05     4.48     2.87     4.00     4.47
## Education_Level*               8 1e+05     1.95     0.81     2.00     1.87
## Performance_Score              9 1e+05     3.00     1.41     3.00     2.99
## Monthly_Salary                10 1e+05  6403.21  1372.51  6500.00  6385.86
## Work_Hours_Per_Week           11 1e+05    44.96     8.94    45.00    44.95
## Projects_Handled              12 1e+05    24.43    14.47    24.00    24.41
## Overtime_Hours                13 1e+05    14.51     8.66    15.00    14.52
## Sick_Days                     14 1e+05     7.01     4.33     7.00     7.01
## Remote_Work_Frequency         15 1e+05    50.09    35.35    50.00    50.11
## Team_Size                     16 1e+05    10.01     5.50    10.00    10.01
## Training_Hours                17 1e+05    49.51    28.89    49.00    49.51
## Promotions                    18 1e+05     1.00     0.82     1.00     1.00
## Employee_Satisfaction_Score   19 1e+05     3.00     1.15     3.00     3.00
## Resigned                      20 1e+05      NaN       NA       NA      NaN
## Gender_Code                   21 1e+05     0.56     0.57     1.00     0.52
## Income_per_Hour               22 1e+05    37.13    11.25    35.55    36.30
## Tenure_Years                  23 1e+05     6.12     2.88     6.10     6.12
## Monthly_Salary_Scaled         24 1e+05     0.00     1.00     0.07    -0.01
## Age_Group*                    25 1e+05     2.54     1.11     3.00     2.55
## Education_Code                26 1e+05     1.95     0.81     2.00     1.87
## Salary_log                    27 1e+05     8.74     0.22     8.78     8.75
## Resigned_Label*               28 1e+05     1.10     0.30     1.00     1.00
## Performance_Level*            29 1e+05     2.00     0.89     2.00     2.00
## outlier_flag                  30 1e+05     0.00     0.00     0.00     0.00
##                                  mad     min       max    range  skew kurtosis
## Employee_ID                 37065.00    1.00 100000.00 99999.00  0.00    -1.20
## Department*                     2.97    1.00      9.00     8.00 -0.01    -1.23
## Gender*                         1.48    1.00      3.00     2.00  0.41    -0.78
## Age                            14.83   22.00     60.00    38.00 -0.01    -1.20
## Job_Title*                      2.97    1.00      7.00     6.00 -0.01    -1.25
## Hire_Date                         NA     Inf      -Inf     -Inf    NA       NA
## Years_At_Company                2.97    0.00     10.00    10.00  0.01    -1.22
## Education_Level*                0.00    1.00      4.00     3.00  0.67     0.13
## Performance_Score               1.48    1.00      5.00     4.00  0.00    -1.30
## Monthly_Salary               1630.86 3850.00   9000.00  5150.00  0.10    -0.88
## Work_Hours_Per_Week            11.86   30.00     60.00    30.00  0.01    -1.20
## Projects_Handled               19.27    0.00     49.00    49.00  0.01    -1.21
## Overtime_Hours                 11.86    0.00     29.00    29.00  0.00    -1.20
## Sick_Days                       5.93    0.00     14.00    14.00  0.00    -1.22
## Remote_Work_Frequency          37.06    0.00    100.00   100.00  0.00    -1.30
## Team_Size                       7.41    1.00     19.00    18.00  0.00    -1.21
## Training_Hours                 37.06    0.00     99.00    99.00  0.00    -1.20
## Promotions                      1.48    0.00      2.00     2.00  0.00    -1.50
## Employee_Satisfaction_Score     1.47    1.00      5.00     4.00  0.00    -1.19
## Resigned                          NA     Inf      -Inf     -Inf    NA       NA
## Gender_Code                     1.48    0.00      2.00     2.00  0.41    -0.78
## Income_per_Hour                11.00   16.04     75.00    58.96  0.66     0.10
## Tenure_Years                    3.70    1.15     11.15    10.00  0.01    -1.20
## Monthly_Salary_Scaled           1.19   -1.86      1.89     3.75  0.10    -0.88
## Age_Group*                      1.48    1.00      4.00     3.00 -0.04    -1.33
## Education_Code                  0.00    1.00      4.00     3.00  0.67     0.13
## Salary_log                      0.25    8.26      9.10     0.85 -0.27    -0.76
## Resigned_Label*                 0.00    1.00      2.00     1.00  2.66     5.10
## Performance_Level*              1.48    1.00      3.00     2.00  0.01    -1.75
## outlier_flag                    0.00    0.00      0.00     0.00   NaN      NaN
##                                se
## Employee_ID                 91.29
## Department*                  0.01
## Gender*                      0.00
## Age                          0.04
## Job_Title*                   0.01
## Hire_Date                      NA
## Years_At_Company             0.01
## Education_Level*             0.00
## Performance_Score            0.00
## Monthly_Salary               4.34
## Work_Hours_Per_Week          0.03
## Projects_Handled             0.05
## Overtime_Hours               0.03
## Sick_Days                    0.01
## Remote_Work_Frequency        0.11
## Team_Size                    0.02
## Training_Hours               0.09
## Promotions                   0.00
## Employee_Satisfaction_Score  0.00
## Resigned                       NA
## Gender_Code                  0.00
## Income_per_Hour              0.04
## Tenure_Years                 0.01
## Monthly_Salary_Scaled        0.00
## Age_Group*                   0.00
## Education_Code               0.00
## Salary_log                   0.00
## Resigned_Label*              0.00
## Performance_Level*           0.00
## outlier_flag                 0.00

3.2. Thống kê mô tả nâng cao cho toàn bộ dữ liệu

skim(Data)
Data summary
Name Data
Number of rows 100000
Number of columns 30
_______________________
Column type frequency:
character 3
Date 1
factor 4
logical 1
numeric 21
________________________
Group variables None

Variable type: character

skim_variable n_missing complete_rate min max empty n_unique whitespace
Department 0 1 2 16 0 9 0
Job_Title 0 1 7 10 0 7 0
Resigned_Label 0 1 12 12 0 2 0

Variable type: Date

skim_variable n_missing complete_rate min max median n_unique
Hire_Date 0 1 2014-09-07 2024-09-03 2019-09-21 3650

Variable type: factor

skim_variable n_missing complete_rate ordered n_unique top_counts
Gender 0 1 FALSE 3 Mal: 48031, Fem: 48001, Oth: 3968
Education_Level 0 1 TRUE 4 Bac: 50041, Hig: 30004, Mas: 14904, PhD: 5051
Age_Group 0 1 FALSE 4 41-: 25721, 51-: 25713, 31-: 25535, 20-: 23031
Performance_Level 0 1 FALSE 3 Thấ: 40133, Cao: 39868, Tru: 19999

Variable type: logical

skim_variable n_missing complete_rate mean count
Resigned 0 1 0.1 FAL: 89990, TRU: 10010

Variable type: numeric

skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
Employee_ID 0 1 50000.50 28867.66 1.00 25000.75 50000.50 75000.25 100000.00 ▇▇▇▇▇
Age 0 1 41.03 11.24 22.00 31.00 41.00 51.00 60.00 ▇▇▇▇▇
Years_At_Company 0 1 4.48 2.87 0.00 2.00 4.00 7.00 10.00 ▇▅▅▅▂
Performance_Score 0 1 3.00 1.41 1.00 2.00 3.00 4.00 5.00 ▇▇▇▇▇
Monthly_Salary 0 1 6403.21 1372.51 3850.00 5250.00 6500.00 7500.00 9000.00 ▅▇▇▇▅
Work_Hours_Per_Week 0 1 44.96 8.94 30.00 37.00 45.00 53.00 60.00 ▇▇▇▇▇
Projects_Handled 0 1 24.43 14.47 0.00 12.00 24.00 37.00 49.00 ▇▇▇▇▇
Overtime_Hours 0 1 14.51 8.66 0.00 7.00 15.00 22.00 29.00 ▇▇▇▇▇
Sick_Days 0 1 7.01 4.33 0.00 3.00 7.00 11.00 14.00 ▇▇▇▇▇
Remote_Work_Frequency 0 1 50.09 35.35 0.00 25.00 50.00 75.00 100.00 ▇▇▇▇▇
Team_Size 0 1 10.01 5.50 1.00 5.00 10.00 15.00 19.00 ▇▇▆▇▇
Training_Hours 0 1 49.51 28.89 0.00 25.00 49.00 75.00 99.00 ▇▇▇▇▇
Promotions 0 1 1.00 0.82 0.00 0.00 1.00 2.00 2.00 ▇▁▇▁▇
Employee_Satisfaction_Score 0 1 3.00 1.15 1.00 2.01 3.00 3.99 5.00 ▇▇▇▇▇
Gender_Code 0 1 0.56 0.57 0.00 0.00 1.00 1.00 2.00 ▇▁▇▁▁
Income_per_Hour 0 1 37.13 11.25 16.04 28.68 35.55 43.88 75.00 ▅▇▅▂▁
Tenure_Years 0 1 6.12 2.88 1.15 3.62 6.10 8.61 11.15 ▇▇▇▇▇
Monthly_Salary_Scaled 0 1 0.00 1.00 -1.86 -0.84 0.07 0.80 1.89 ▅▇▇▇▅
Education_Code 0 1 1.95 0.81 1.00 1.00 2.00 2.00 4.00 ▅▇▁▂▁
Salary_log 0 1 8.74 0.22 8.26 8.57 8.78 8.92 9.10 ▃▅▆▇▆
outlier_flag 0 1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 ▁▁▇▁▁

3.3. Tính trung bình, min, max cho các biến định lượng

Data %>%
  summarise(across(where(is.numeric),
                   list(mean = mean, min = min, max = max), na.rm = TRUE))
## Warning: There was 1 warning in `summarise()`.
## ℹ In argument: `across(...)`.
## Caused by warning:
## ! The `...` argument of `across()` is deprecated as of dplyr 1.1.0.
## Supply arguments directly to `.fns` through an anonymous function instead.
## 
##   # Previously
##   across(a:b, mean, na.rm = TRUE)
## 
##   # Now
##   across(a:b, \(x) mean(x, na.rm = TRUE))
## # A tibble: 1 × 63
##   Employee_ID_mean Employee_ID_min Employee_ID_max Age_mean Age_min Age_max
##              <dbl>           <dbl>           <dbl>    <dbl>   <dbl>   <dbl>
## 1           50000.               1          100000     41.0      22      60
## # ℹ 57 more variables: Years_At_Company_mean <dbl>, Years_At_Company_min <dbl>,
## #   Years_At_Company_max <dbl>, Performance_Score_mean <dbl>,
## #   Performance_Score_min <dbl>, Performance_Score_max <dbl>,
## #   Monthly_Salary_mean <dbl>, Monthly_Salary_min <dbl>,
## #   Monthly_Salary_max <dbl>, Work_Hours_Per_Week_mean <dbl>,
## #   Work_Hours_Per_Week_min <dbl>, Work_Hours_Per_Week_max <dbl>,
## #   Projects_Handled_mean <dbl>, Projects_Handled_min <dbl>, …

3.4. Đếm số nhân viên theo phòng ban

Data %>%
  count(Department, name = "SoLuong") %>%
  arrange(desc(SoLuong))
## # A tibble: 9 × 2
##   Department       SoLuong
##   <chr>              <int>
## 1 Marketing          11216
## 2 Finance            11200
## 3 Operations         11181
## 4 IT                 11131
## 5 Sales              11122
## 6 Legal              11118
## 7 Customer Support   11116
## 8 HR                 10960
## 9 Engineering        10956

3.5. Tính tỷ lệ phần trăm giới tính

Data %>%
  count(Gender) %>%
  mutate(Percent = round(n / sum(n) * 100, 2))
## # A tibble: 3 × 3
##   Gender     n Percent
##   <fct>  <int>   <dbl>
## 1 Female 48001   48   
## 2 Male   48031   48.0 
## 3 Other   3968    3.97

3.6. Lương trung bình theo nhóm tuổi và giới tính**

Data <- Data %>%
  mutate(
    Nhom_Tuoi = case_when(
      Age < 30 ~ "Dưới 30",
      Age >= 30 & Age < 40 ~ "30-39",
      Age >= 40 & Age < 50 ~ "40-49",
      Age >= 50 ~ "Từ 50 trở lên"
    )
  )
Data %>%
  group_by(Nhom_Tuoi, Gender) %>%
  summarise(LuongTB = mean(Monthly_Salary, na.rm = TRUE)) %>%
  arrange(Nhom_Tuoi)
## `summarise()` has grouped output by 'Nhom_Tuoi'. You can override using the
## `.groups` argument.
## # A tibble: 12 × 3
## # Groups:   Nhom_Tuoi [4]
##    Nhom_Tuoi     Gender LuongTB
##    <chr>         <fct>    <dbl>
##  1 30-39         Female   6400.
##  2 30-39         Male     6399.
##  3 30-39         Other    6414.
##  4 40-49         Female   6414.
##  5 40-49         Male     6394.
##  6 40-49         Other    6427.
##  7 Dưới 30       Female   6403.
##  8 Dưới 30       Male     6398.
##  9 Dưới 30       Other    6392.
## 10 Từ 50 trở lên Female   6403.
## 11 Từ 50 trở lên Male     6410.
## 12 Từ 50 trở lên Other    6421.

3.7. Phân nhóm nhân viên theo độ tuổi

Data <- Data %>%
  mutate(Nhom_Tuoi = case_when(
    Age < 25 ~ "Dưới 25",
    Age >= 25 & Age < 35 ~ "25–34",
    Age >= 35 & Age < 45 ~ "35–44",
    Age >= 45 ~ "Trên 45"
  ))

table(Data$Nhom_Tuoi)
## 
##   25–34   35–44 Dưới 25 Trên 45 
##   25607   25597    7608   41188

3.8. Xếp hạng phòng ban theo lương trung bình

Data %>%
   group_by(Department) %>%
  summarise(LuongTB = mean(Monthly_Salary, na.rm = TRUE)) %>%
  mutate(XepHang = rank(-LuongTB))
## # A tibble: 9 × 3
##   Department       LuongTB XepHang
##   <chr>              <dbl>   <dbl>
## 1 Customer Support   6404.       5
## 2 Engineering        6417.       1
## 3 Finance            6399.       7
## 4 HR                 6400.       6
## 5 IT                 6415.       2
## 6 Legal              6391.       8
## 7 Marketing          6378.       9
## 8 Operations         6412.       4
## 9 Sales              6413.       3

3.9. Phân phối lương theo nhóm trình độ

Data %>%
  group_by(Education_Level) %>%
  summarise(
    Min = min(Monthly_Salary, na.rm = TRUE),
    Q1 = quantile(Monthly_Salary, 0.25, na.rm = TRUE),
    Median = median(Monthly_Salary, na.rm = TRUE),
    Q3 = quantile(Monthly_Salary, 0.75, na.rm = TRUE),
    Max = max(Monthly_Salary, na.rm = TRUE)
  )
## # A tibble: 4 × 6
##   Education_Level   Min    Q1 Median    Q3   Max
##   <ord>           <dbl> <dbl>  <dbl> <dbl> <dbl>
## 1 High School      3850  5250   6500  7500  9000
## 2 Bachelor         3850  5250   6500  7500  9000
## 3 Master           3850  5250   6500  7500  9000
## 4 PhD              3850  5400   6500  7500  9000

3.10. Ma trận tương quan giữa các biến định lượng

num_vars <- Data %>% select(where(is.numeric))
cor_matrix <- cor(num_vars, use = "complete.obs")
## Warning in cor(num_vars, use = "complete.obs"): the standard deviation is zero
cor_matrix
##                               Employee_ID           Age Years_At_Company
## Employee_ID                  1.0000000000  4.010169e-03    -7.175044e-03
## Age                          0.0040101693  1.000000e+00     7.807067e-05
## Years_At_Company            -0.0071750437  7.807067e-05     1.000000e+00
## Performance_Score           -0.0020774164  1.597668e-03     1.597730e-03
## Monthly_Salary              -0.0020502697  2.756751e-03    -6.446329e-04
## Work_Hours_Per_Week         -0.0009682099 -3.049750e-03     2.577616e-03
## Projects_Handled            -0.0007055068 -1.726106e-03     2.962663e-03
## Overtime_Hours              -0.0052544207  1.875477e-03     1.964914e-03
## Sick_Days                    0.0007453207  6.981262e-03    -4.371378e-03
## Remote_Work_Frequency       -0.0003470926 -4.671609e-03    -2.443322e-03
## Team_Size                    0.0020271653 -3.411191e-03     3.249903e-03
## Training_Hours              -0.0029659719  2.044696e-03     2.696411e-03
## Promotions                  -0.0007783032 -2.887805e-03    -2.736752e-03
## Employee_Satisfaction_Score -0.0015949690 -1.242389e-04    -3.180180e-03
## Gender_Code                  0.0009785420 -7.307428e-04    -3.676997e-03
## Income_per_Hour             -0.0006911393  3.882076e-03    -1.511366e-03
## Tenure_Years                -0.0069117415  3.607415e-04     9.949547e-01
## Monthly_Salary_Scaled       -0.0020502697  2.756751e-03    -6.446329e-04
## Education_Code              -0.0018789701  3.824126e-03    -9.113552e-04
## Salary_log                  -0.0017915120  2.933448e-03    -9.981241e-04
## outlier_flag                           NA            NA               NA
##                             Performance_Score Monthly_Salary
## Employee_ID                     -0.0020774164  -0.0020502697
## Age                              0.0015976678   0.0027567514
## Years_At_Company                 0.0015977303  -0.0006446329
## Performance_Score                1.0000000000   0.5100348076
## Monthly_Salary                   0.5100348076   1.0000000000
## Work_Hours_Per_Week             -0.0056272519  -0.0023471937
## Projects_Handled                 0.0006404622  -0.0019249034
## Overtime_Hours                  -0.0013116293  -0.0030286716
## Sick_Days                        0.0029943235   0.0036103835
## Remote_Work_Frequency            0.0017328664  -0.0004640546
## Team_Size                       -0.0051744134   0.0029715225
## Training_Hours                   0.0023579401  -0.0010876011
## Promotions                      -0.0035012983  -0.0019402037
## Employee_Satisfaction_Score      0.0016962790   0.0010827334
## Gender_Code                      0.0033283897  -0.0005024205
## Income_per_Hour                  0.3652205329   0.7095713299
## Tenure_Years                     0.0013313701  -0.0011698334
## Monthly_Salary_Scaled            0.5100348076   1.0000000000
## Education_Code                   0.0018269621   0.0055555788
## Salary_log                       0.4984682532   0.9931557833
## outlier_flag                               NA             NA
##                             Work_Hours_Per_Week Projects_Handled Overtime_Hours
## Employee_ID                       -0.0009682099    -0.0007055068   -0.005254421
## Age                               -0.0030497497    -0.0017261058    0.001875477
## Years_At_Company                   0.0025776162     0.0029626628    0.001964914
## Performance_Score                 -0.0056272519     0.0006404622   -0.001311629
## Monthly_Salary                    -0.0023471937    -0.0019249034   -0.003028672
## Work_Hours_Per_Week                1.0000000000    -0.0041829031    0.005787021
## Projects_Handled                  -0.0041829031     1.0000000000    0.004106915
## Overtime_Hours                     0.0057870213     0.0041069149    1.000000000
## Sick_Days                         -0.0008383590    -0.0049951817    0.004254812
## Remote_Work_Frequency             -0.0046182275     0.0004843081   -0.004349288
## Team_Size                          0.0007902768     0.0038130125    0.002174617
## Training_Hours                     0.0012871484     0.0022111028    0.002939398
## Promotions                         0.0002382231    -0.0023438196   -0.002537371
## Employee_Satisfaction_Score        0.0005299660     0.0061258039    0.001052243
## Gender_Code                        0.0030297598     0.0020483138   -0.003142553
## Income_per_Hour                   -0.6788761210     0.0011201122   -0.005860099
## Tenure_Years                       0.0033883197     0.0024509233    0.001749499
## Monthly_Salary_Scaled             -0.0023471937    -0.0019249034   -0.003028672
## Education_Code                    -0.0018123271    -0.0015197491    0.007493310
## Salary_log                        -0.0019864042    -0.0022188744   -0.002688654
## outlier_flag                                 NA               NA             NA
##                                 Sick_Days Remote_Work_Frequency     Team_Size
## Employee_ID                  0.0007453207         -0.0003470926  0.0020271653
## Age                          0.0069812624         -0.0046716085 -0.0034111911
## Years_At_Company            -0.0043713776         -0.0024433223  0.0032499029
## Performance_Score            0.0029943235          0.0017328664 -0.0051744134
## Monthly_Salary               0.0036103835         -0.0004640546  0.0029715225
## Work_Hours_Per_Week         -0.0008383590         -0.0046182275  0.0007902768
## Projects_Handled            -0.0049951817          0.0004843081  0.0038130125
## Overtime_Hours               0.0042548124         -0.0043492880  0.0021746169
## Sick_Days                    1.0000000000          0.0004782113  0.0001493077
## Remote_Work_Frequency        0.0004782113          1.0000000000 -0.0006677778
## Team_Size                    0.0001493077         -0.0006677778  1.0000000000
## Training_Hours               0.0003468368          0.0052273677  0.0027358291
## Promotions                  -0.0030440420         -0.0005365374  0.0006476629
## Employee_Satisfaction_Score -0.0008929077         -0.0014080411  0.0009435061
## Gender_Code                  0.0019069739          0.0014421629 -0.0035767307
## Income_per_Hour              0.0030818680          0.0029304538  0.0015846071
## Tenure_Years                -0.0044099108         -0.0026209039  0.0034104045
## Monthly_Salary_Scaled        0.0036103835         -0.0004640546  0.0029715225
## Education_Code              -0.0026007225          0.0023716776  0.0011924871
## Salary_log                   0.0033390196         -0.0004589593  0.0031194449
## outlier_flag                           NA                    NA            NA
##                             Training_Hours    Promotions
## Employee_ID                  -0.0029659719 -0.0007783032
## Age                           0.0020446964 -0.0028878052
## Years_At_Company              0.0026964107 -0.0027367522
## Performance_Score             0.0023579401 -0.0035012983
## Monthly_Salary               -0.0010876011 -0.0019402037
## Work_Hours_Per_Week           0.0012871484  0.0002382231
## Projects_Handled              0.0022111028 -0.0023438196
## Overtime_Hours                0.0029393975 -0.0025373710
## Sick_Days                     0.0003468368 -0.0030440420
## Remote_Work_Frequency         0.0052273677 -0.0005365374
## Team_Size                     0.0027358291  0.0006476629
## Training_Hours                1.0000000000  0.0009325892
## Promotions                    0.0009325892  1.0000000000
## Employee_Satisfaction_Score  -0.0014892218  0.0002268193
## Gender_Code                  -0.0045291464  0.0016893454
## Income_per_Hour              -0.0023492786 -0.0015630480
## Tenure_Years                  0.0028224575 -0.0027728045
## Monthly_Salary_Scaled        -0.0010876011 -0.0019402037
## Education_Code               -0.0008259264  0.0007700870
## Salary_log                   -0.0013740890 -0.0017717160
## outlier_flag                            NA            NA
##                             Employee_Satisfaction_Score   Gender_Code
## Employee_ID                               -1.594969e-03  0.0009785420
## Age                                       -1.242389e-04 -0.0007307428
## Years_At_Company                          -3.180180e-03 -0.0036769971
## Performance_Score                          1.696279e-03  0.0033283897
## Monthly_Salary                             1.082733e-03 -0.0005024205
## Work_Hours_Per_Week                        5.299660e-04  0.0030297598
## Projects_Handled                           6.125804e-03  0.0020483138
## Overtime_Hours                             1.052243e-03 -0.0031425532
## Sick_Days                                 -8.929077e-04  0.0019069739
## Remote_Work_Frequency                     -1.408041e-03  0.0014421629
## Team_Size                                  9.435061e-04 -0.0035767307
## Training_Hours                            -1.489222e-03 -0.0045291464
## Promotions                                 2.268193e-04  0.0016893454
## Employee_Satisfaction_Score                1.000000e+00 -0.0047025556
## Gender_Code                               -4.702556e-03  1.0000000000
## Income_per_Hour                            9.901409e-06 -0.0021507012
## Tenure_Years                              -3.000590e-03 -0.0034907672
## Monthly_Salary_Scaled                      1.082733e-03 -0.0005024205
## Education_Code                            -3.167152e-03 -0.0025618943
## Salary_log                                 1.237863e-03 -0.0008487764
## outlier_flag                                         NA            NA
##                             Income_per_Hour  Tenure_Years Monthly_Salary_Scaled
## Employee_ID                   -6.911393e-04 -0.0069117415         -0.0020502697
## Age                            3.882076e-03  0.0003607415          0.0027567514
## Years_At_Company              -1.511366e-03  0.9949547064         -0.0006446329
## Performance_Score              3.652205e-01  0.0013313701          0.5100348076
## Monthly_Salary                 7.095713e-01 -0.0011698334          1.0000000000
## Work_Hours_Per_Week           -6.788761e-01  0.0033883197         -0.0023471937
## Projects_Handled               1.120112e-03  0.0024509233         -0.0019249034
## Overtime_Hours                -5.860099e-03  0.0017494988         -0.0030286716
## Sick_Days                      3.081868e-03 -0.0044099108          0.0036103835
## Remote_Work_Frequency          2.930454e-03 -0.0026209039         -0.0004640546
## Team_Size                      1.584607e-03  0.0034104045          0.0029715225
## Training_Hours                -2.349279e-03  0.0028224575         -0.0010876011
## Promotions                    -1.563048e-03 -0.0027728045         -0.0019402037
## Employee_Satisfaction_Score    9.901409e-06 -0.0030005904          0.0010827334
## Gender_Code                   -2.150701e-03 -0.0034907672         -0.0005024205
## Income_per_Hour                1.000000e+00 -0.0025908506          0.7095713299
## Tenure_Years                  -2.590851e-03  1.0000000000         -0.0011698334
## Monthly_Salary_Scaled          7.095713e-01 -0.0011698334          1.0000000000
## Education_Code                 4.468437e-03 -0.0007234356          0.0055555788
## Salary_log                     7.044228e-01 -0.0015312002          0.9931557833
## outlier_flag                             NA            NA                    NA
##                             Education_Code    Salary_log outlier_flag
## Employee_ID                  -0.0018789701 -0.0017915120           NA
## Age                           0.0038241263  0.0029334479           NA
## Years_At_Company             -0.0009113552 -0.0009981241           NA
## Performance_Score             0.0018269621  0.4984682532           NA
## Monthly_Salary                0.0055555788  0.9931557833           NA
## Work_Hours_Per_Week          -0.0018123271 -0.0019864042           NA
## Projects_Handled             -0.0015197491 -0.0022188744           NA
## Overtime_Hours                0.0074933096 -0.0026886542           NA
## Sick_Days                    -0.0026007225  0.0033390196           NA
## Remote_Work_Frequency         0.0023716776 -0.0004589593           NA
## Team_Size                     0.0011924871  0.0031194449           NA
## Training_Hours               -0.0008259264 -0.0013740890           NA
## Promotions                    0.0007700870 -0.0017717160           NA
## Employee_Satisfaction_Score  -0.0031671522  0.0012378629           NA
## Gender_Code                  -0.0025618943 -0.0008487764           NA
## Income_per_Hour               0.0044684368  0.7044228497           NA
## Tenure_Years                 -0.0007234356 -0.0015312002           NA
## Monthly_Salary_Scaled         0.0055555788  0.9931557833           NA
## Education_Code                1.0000000000  0.0058748496           NA
## Salary_log                    0.0058748496  1.0000000000           NA
## outlier_flag                            NA            NA            1

3.11. Tỷ lệ nghỉ việc tổng thể

Data %>%
   summarise(TyLeNghiViec = mean(Resigned) * 100)
## # A tibble: 1 × 1
##   TyLeNghiViec
##          <dbl>
## 1         10.0

3.12. Tính hệ số biến thiên (Coefficient of Variation) cho lương

Data %>%
  mutate(CV_Luong = sd(Monthly_Salary, na.rm = TRUE) / mean(Monthly_Salary, na.rm = TRUE) * 100)
## # A tibble: 100,000 × 32
##    Employee_ID Department     Gender   Age Job_Title Hire_Date  Years_At_Company
##          <dbl> <chr>          <fct>  <dbl> <chr>     <date>                <dbl>
##  1           1 IT             Male      55 Speciali… 2022-01-19                2
##  2           2 Finance        Male      29 Developer 2024-04-18                0
##  3           3 Finance        Male      55 Speciali… 2015-10-26                8
##  4           4 Customer Supp… Female    48 Analyst   2016-10-22                7
##  5           5 Engineering    Female    36 Analyst   2021-07-23                3
##  6           6 IT             Male      43 Manager   2016-08-14                8
##  7           7 IT             Male      37 Technici… 2023-08-28                1
##  8           8 Engineering    Female    55 Engineer  2014-10-27                9
##  9           9 Marketing      Female    55 Technici… 2023-06-29                1
## 10          10 Engineering    Female    45 Consulta… 2016-12-23                7
## # ℹ 99,990 more rows
## # ℹ 25 more variables: Education_Level <ord>, Performance_Score <dbl>,
## #   Monthly_Salary <dbl>, Work_Hours_Per_Week <dbl>, Projects_Handled <dbl>,
## #   Overtime_Hours <dbl>, Sick_Days <dbl>, Remote_Work_Frequency <dbl>,
## #   Team_Size <dbl>, Training_Hours <dbl>, Promotions <dbl>,
## #   Employee_Satisfaction_Score <dbl>, Resigned <lgl>, Gender_Code <dbl>,
## #   Income_per_Hour <dbl>, Tenure_Years <dbl>, …

3.13. So sánh trung bình điểm hài lòng giữa nhóm nghỉ và ở lại

Data %>%
  group_by(Resigned) %>%
  summarise(DiemHaiLongTB = mean(Employee_Satisfaction_Score, na.rm = TRUE))
## # A tibble: 2 × 2
##   Resigned DiemHaiLongTB
##   <lgl>            <dbl>
## 1 FALSE             3.00
## 2 TRUE              2.99

3.14. Trung bình lương và tuổi theo học vấn

Data %>%
  group_by(Education_Level) %>%
  summarise(
    LuongTB = mean(Monthly_Salary, na.rm = TRUE),
    TuoiTB = mean(Age, na.rm = TRUE)
  )
## # A tibble: 4 × 3
##   Education_Level LuongTB TuoiTB
##   <ord>             <dbl>  <dbl>
## 1 High School       6399.   41.0
## 2 Bachelor          6398.   41.0
## 3 Master            6417.   41.0
## 4 PhD               6432.   41.3

3.15. Phân tích chéo giữa giới tính và học vấn

table(Data$Gender, Data$Education_Level)
##         
##          High School Bachelor Master   PhD
##   Female       14299    24138   7127  2437
##   Male         14516    23902   7195  2418
##   Other         1189     2001    582   196

3.16. Hệ số tương quan giữa lương và điểm hài lòng

cor(Data$Monthly_Salary, Data$Employee_Satisfaction_Score)
## [1] 0.001082733

3.17. Trung bình số dự án theo chức vụ

Data %>%
  group_by(Job_Title) %>%
  summarise(DuAnTB = mean(Projects_Handled, na.rm = TRUE))
## # A tibble: 7 × 2
##   Job_Title  DuAnTB
##   <chr>       <dbl>
## 1 Analyst      24.4
## 2 Consultant   24.4
## 3 Developer    24.4
## 4 Engineer     24.5
## 5 Manager      24.3
## 6 Specialist   24.5
## 7 Technician   24.5

3.18. Phân tổ các biến theo giới tính và nhóm tuổi

# Tạo biến nhóm tuổi (phân tổ theo khoảng)
Data <- Data %>%
  mutate(Nhom_tuoi = cut(Age,
                         breaks = c(20, 30, 40, 50, 60),
                         labels = c("20-29", "30-39", "40-49", "50-59"),
                         right = FALSE))  # khoảng trái đóng, phải mở

# Phân tổ theo giới tính và nhóm tuổi
bang_phan_to <- Data %>%
  group_by(Gender, Nhom_tuoi) %>%
  summarise(
    So_luong = n(),
    Luong_TB = mean(as.numeric(Monthly_Salary), na.rm = TRUE),
    Diem_HL_TB = mean(as.numeric(Employee_Satisfaction_Score), na.rm = TRUE)
  ) %>%
  arrange(Gender, Nhom_tuoi)
## `summarise()` has grouped output by 'Gender'. You can override using the
## `.groups` argument.
# In kết quả ra màn hình
print(bang_phan_to)
## # A tibble: 15 × 5
## # Groups:   Gender [3]
##    Gender Nhom_tuoi So_luong Luong_TB Diem_HL_TB
##    <fct>  <fct>        <int>    <dbl>      <dbl>
##  1 Female 20-29         9722    6403.       3.00
##  2 Female 30-39        12403    6400.       3.01
##  3 Female 40-49        12333    6414.       3.00
##  4 Female 50-59        12331    6400.       3.00
##  5 Female <NA>          1212    6434.       3.06
##  6 Male   20-29         9946    6398.       2.99
##  7 Male   30-39        12056    6399.       3.00
##  8 Male   40-49        12357    6394.       2.99
##  9 Male   50-59        12462    6404.       2.99
## 10 Male   <NA>          1210    6469.       3.03
## 11 Other  20-29          824    6392.       2.94
## 12 Other  30-39         1006    6414.       3.00
## 13 Other  40-49         1020    6427.       3.00
## 14 Other  50-59         1005    6423.       3.00
## 15 Other  <NA>           113    6405.       3.10

3.19. So sánh lương trung bình và độ lệch chuẩn giữa các phòng ban

Data %>%
  group_by(Department) %>%
  summarise(
    LuongTB = mean(Monthly_Salary, na.rm = TRUE),
    DoLechChuan = sd(Monthly_Salary, na.rm = TRUE)
  ) %>%
  arrange(desc(LuongTB))
## # A tibble: 9 × 3
##   Department       LuongTB DoLechChuan
##   <chr>              <dbl>       <dbl>
## 1 Engineering        6417.       1365.
## 2 IT                 6415.       1378.
## 3 Sales              6413.       1365.
## 4 Operations         6412.       1380.
## 5 Customer Support   6404.       1372.
## 6 HR                 6400.       1369.
## 7 Finance            6399.       1364.
## 8 Legal              6391.       1376.
## 9 Marketing          6378.       1383.

3.20. Phan to chuc danh nha phat trien, trinh do thac si, diem hieu suat duoi 2, so ngay om tren 5

# Lọc dữ liệu theo tiêu chí học vấn, hiệu suất và số ngày ốm
df_filtered2 <- Data %>%
  filter(
    Job_Title == "Developer",
    Education_Level == "Master",
    Performance_Score < 2,
    Sick_Days > 5
  )

print(df_filtered2)
## # A tibble: 252 × 32
##    Employee_ID Department Gender   Age Job_Title Hire_Date  Years_At_Company
##          <dbl> <chr>      <fct>  <dbl> <chr>     <date>                <dbl>
##  1         338 Operations Female    55 Developer 2017-02-07                7
##  2         670 Legal      Male      47 Developer 2019-04-29                5
##  3         811 Sales      Female    24 Developer 2018-06-20                6
##  4         986 IT         Female    56 Developer 2020-07-31                4
##  5        1774 Finance    Male      45 Developer 2022-03-27                2
##  6        2191 Legal      Female    39 Developer 2016-05-06                8
##  7        2437 IT         Female    36 Developer 2014-12-23                9
##  8        2783 Finance    Female    43 Developer 2016-03-28                8
##  9        2847 Legal      Other     53 Developer 2017-09-13                6
## 10        3119 HR         Female    58 Developer 2015-09-17                8
## # ℹ 242 more rows
## # ℹ 25 more variables: Education_Level <ord>, Performance_Score <dbl>,
## #   Monthly_Salary <dbl>, Work_Hours_Per_Week <dbl>, Projects_Handled <dbl>,
## #   Overtime_Hours <dbl>, Sick_Days <dbl>, Remote_Work_Frequency <dbl>,
## #   Team_Size <dbl>, Training_Hours <dbl>, Promotions <dbl>,
## #   Employee_Satisfaction_Score <dbl>, Resigned <lgl>, Gender_Code <dbl>,
## #   Income_per_Hour <dbl>, Tenure_Years <dbl>, …

IV. TRỰC QUAN HÓA DỮ LIỆU

Biểu đồ 1-Cột: Số lượng nhân viên theo phòng ban

library(dplyr)
library(ggplot2)

data_bar <- Data %>%
  group_by(Department) %>%
  summarise(n = n())

ggplot(data_bar, aes(x = Department, y = n, fill = Department)) +
  geom_col() +
  geom_text(aes(label = n), vjust = -0.3, color = "black", size = 4) +
  labs(title = "Số lượng nhân viên theo phòng ban",
       x = "Phòng ban", y = "Số lượng nhân viên") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 30, hjust = 1))

### Biểu đồ 2-Cột nhóm (Gender+Department)

data_group <- Data %>%
  group_by(Department, Gender) %>%
  summarise(n = n())
## `summarise()` has grouped output by 'Department'. You can override using the
## `.groups` argument.
ggplot(data_group, aes(x = Department, y = n, fill = Gender)) +
  geom_col(position = "dodge") +
  geom_text(aes(label = n), position = position_dodge(0.9), vjust = -0.3) +
  labs(title = "Số lượng nhân viên theo phòng ban và giới tính",
       x = "Phòng ban", y = "Số lượng") +
  theme_classic()

### Biểu đồ 3 - Boxplot: Phân bố lương theo phòng ban

ggplot(Data, aes(x = Department, y = Monthly_Salary, fill = Department)) +
  geom_boxplot() +
  labs(title = "Phân bố lương theo phòng ban",
       x = "Phòng ban", y = "Mức lương") +
  theme_minimal() +
  coord_flip()

### Biểu đồ 4 - Scatter plot: Mối quan hệ giữa tuổi và lương

ggplot(Data, aes(x = Age, y = Monthly_Salary, color = Gender)) +
  geom_point(alpha = 0.6) +
  geom_smooth(method = "lm", se = FALSE, color = "black") +
  labs(title = "Mối quan hệ giữa tuổi và lương",
       x = "Tuổi", y = "Lương trung bình") +
  theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'

### Biểu đồ 5 - Density plot: Phân bố điểm hài lòng theo giới tính

ggplot(Data, aes(x = Employee_Satisfaction_Score, fill = Gender)) +
  geom_density(alpha = 0.5) +
  labs(title = "Phân bố điểm hài lòng theo giới tính",
       x = "Điểm hài lòng", y = "Mật độ") +
  theme_light()

### Biểu đồ 6 - Histogram: Phân bố tuổi nhân viên

ggplot(Data, aes(x = Age)) +
  geom_histogram(fill = "skyblue", color = "black", bins = 20) +
  labs(title = "Phân bố độ tuổi nhân viên",
       x = "Tuổi", y = "Số lượng") +
  theme_minimal()

### Biểu đồ 7 - Pie chart: Trình độ học vấn

data_pie <- Data %>%
  group_by(Education_Level) %>%
  summarise(n = n())

ggplot(data_pie, aes(x = "", y = n, fill = Education_Level)) +
  geom_col(width = 1) +
  coord_polar(theta = "y") +
  geom_text(aes(label = paste0(round(n/sum(n)*100, 1), "%")),
            position = position_stack(vjust = 0.5)) +
  labs(title = "Tỷ lệ trình độ học vấn của nhân viên") +
  theme_void()

### Biểu đồ 8 - Line chart: Lương trung bình theo thâm niên

data_line <- Data %>%
  group_by(Years_At_Company) %>%
  summarise(LuongTB = mean(Monthly_Salary, na.rm = TRUE))

ggplot(data_line, aes(x = Years_At_Company, y = LuongTB)) +
  geom_line(color = "blue", linewidth = 1.2) +
  geom_point(size = 2, color = "red") +
  labs(title = "Lương trung bình theo thâm niên làm việc",
       x = "Số năm làm việc", y = "Lương trung bình") +
  theme_minimal()

### Biểu đồ 9 - Facet: Chia biểu đồ theo giới tính

ggplot(Data, aes(x = Department, y = Monthly_Salary, fill = Department)) +
  geom_boxplot() +
  facet_wrap(~Gender) +
  labs(title = "Phân bố lương theo phòng ban và giới tính") +
  theme_minimal()

### Biểu đồ 10 - Heatmap: Trung bình điểm hài lòng theo phòng ban và giới tính

data_heat <- Data %>%
  group_by(Department, Gender) %>%
  summarise(SatMean = mean(Employee_Satisfaction_Score, na.rm = TRUE))
## `summarise()` has grouped output by 'Department'. You can override using the
## `.groups` argument.
ggplot(data_heat, aes(x = Department, y = Gender, fill = SatMean)) +
  geom_tile() +
  geom_text(aes(label = round(SatMean, 2)), color = "white") +
  labs(title = "Điểm hài lòng trung bình theo phòng ban & giới tính",
       x = "Phòng ban", y = "Giới tính") +
  theme_minimal()

### Biểu đồ 11 - Violin Plot: Lương theo trình độ học vấn

ggplot(Data, aes(x = Education_Level, y = Monthly_Salary, fill = Education_Level)) +
  geom_violin(trim = FALSE, alpha = 0.7) +
  geom_boxplot(width = 0.1, fill = "white", outlier.color = "red") +
  labs(title = "Phân bố lương theo trình độ học vấn",
       x = "Trình độ học vấn", y = "Mức lương") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 20, hjust = 1))

### Biểu đồ 12 - Bar chart có Facet theo giới tính

Data %>%
  group_by(Gender, Department) %>%
  summarise(n = n()) %>%
  ggplot(aes(x = Department, y = n, fill = Department)) +
  geom_col() +
  geom_text(aes(label = n), vjust = -0.3) +
  facet_wrap(~Gender) +
  labs(title = "Số lượng nhân viên theo phòng ban và giới tính",
       x = "Phòng ban", y = "Số lượng") +
  theme_classic()
## `summarise()` has grouped output by 'Gender'. You can override using the
## `.groups` argument.

### Biểu đồ 13 - Scatter Plot có Regression Line

ggplot(Data, aes(x = Projects_Handled, y = Performance_Score, color = Department)) +
  geom_point(alpha = 0.6) +
  geom_smooth(method = "lm", se = FALSE, color = "black") +
  labs(title = "Mối quan hệ giữa số dự án và điểm hiệu suất làm việc",
       x = "Số dự án phụ trách", y = "Điểm hiệu suất") +
  theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'

### Biểu đồ 14 - Histogram với đường Density Overlay

ggplot(Data, aes(x = Work_Hours_Per_Week)) +
  geom_histogram(aes(y = ..density..), bins = 20, fill = "lightblue", color = "black") +
  geom_density(color = "red", linewidth = 1) +
  labs(title = "Phân bố số giờ làm việc mỗi tuần",
       x = "Số giờ làm việc", y = "Mật độ") +
  theme_light()
## Warning: The dot-dot notation (`..density..`) was deprecated in ggplot2 3.4.0.
## ℹ Please use `after_stat(density)` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

### Biểu đồ 15 - Stacked Bar: Tỷ lệ nhân viên gắn bó theo trình độ học vấn

Data %>%
  group_by(Education_Level, Stay = ifelse(Resigned == 0, "Còn làm", "Nghỉ việc")) %>%
  summarise(SL = n()) %>%
  ggplot(aes(x = Education_Level, y = SL, fill = Stay)) +
  geom_col(position = "fill") +
  geom_text(aes(label = paste0(round(100 * SL / sum(SL), 1), "%")),
            position = position_fill(vjust = 0.5), color = "white", size = 3) +
  scale_y_continuous(labels = scales::percent) +
  labs(title = "Tỷ lệ nhân viên còn làm & nghỉ việc theo trình độ học vấn",
       x = "Trình độ học vấn", y = "Tỷ lệ (%)") +
  theme_minimal()
## `summarise()` has grouped output by 'Education_Level'. You can override using
## the `.groups` argument.

install.packages(“ggridges”) library(ggridges) ### Biểu đồ 16 - Ridgeline Plot: Phân bố hiệu suất theo phòng ban

ggplot(Data, aes(x = Performance_Score, y = Department, fill = Department)) +
  geom_density_ridges(alpha = 0.7) +
  labs(title = "Phân bố điểm hiệu suất theo phòng ban",
       x = "Điểm hiệu suất", y = "Phòng ban") +
  theme_minimal() +
  theme(legend.position = "none")
## Picking joint bandwidth of 0.198

### Biểu đồ 17 - Heatmap Lương trung bình theo Giới tính & Trình độ

Data %>%
  group_by(Gender, Education_Level) %>%
  summarise(LuongTB = mean(Monthly_Salary, na.rm = TRUE)) %>%
  ggplot(aes(x = Education_Level, y = Gender, fill = LuongTB)) +
  geom_tile() +
  geom_text(aes(label = round(LuongTB, 1)), color = "white") +
  scale_fill_gradient(low = "skyblue", high = "darkblue") +
  labs(title = "Lương trung bình theo giới tính và trình độ học vấn",
       x = "Trình độ học vấn", y = "Giới tính") +
  theme_minimal()
## `summarise()` has grouped output by 'Gender'. You can override using the
## `.groups` argument.

### Biểu đồ 18 – Line Chart: Điểm hài lòng trung bình theo năm thâm niên

Data %>%
  group_by(Years_At_Company) %>%
  summarise(SatMean = mean(Employee_Satisfaction_Score, na.rm = TRUE)) %>%
  ggplot(aes(x = Years_At_Company, y = SatMean)) +
  geom_line(color = "darkgreen", linewidth = 1.2) +
  geom_point(size = 3, color = "red") +
  geom_text(aes(label = round(SatMean, 2)), vjust = -0.6) +
  labs(title = "Mức độ hài lòng trung bình theo thâm niên",
       x = "Số năm làm việc", y = "Điểm hài lòng TB") +
  theme_minimal()

### Biểu đồ 19 – Bar Chart nâng cao: Tỷ lệ nghỉ việc theo phòng ban

Data %>%
  group_by(Department) %>%
  summarise(TyLeNghi = mean(Resigned) * 100) %>%
  ggplot(aes(x = reorder(Department, -TyLeNghi), y = TyLeNghi, fill = Department)) +
  geom_col() +
  geom_text(aes(label = paste0(round(TyLeNghi, 1), "%")), vjust = -0.3) +
  labs(title = "Tỷ lệ nghỉ việc theo phòng ban",
       x = "Phòng ban", y = "Tỷ lệ nghỉ việc (%)") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 30, hjust = 1))

### Biểu đồ 20 – Facet Grid: Lương theo Giới tính & Phòng ban

ggplot(Data, aes(x = Gender, y = Monthly_Salary, fill = Gender)) +
  geom_boxplot(alpha = 0.7) +
  facet_wrap(~Department) +
  labs(title = "So sánh lương giữa các giới tính theo từng phòng ban",
       x = "Giới tính", y = "Mức lương") +
  theme_light() +
  theme(axis.text.x = element_text(angle = 20, hjust = 1))

### Biểu đồ 21 - Correlation Plot: Biểu đồ tương quan

install.packages("GGally") 
## Installing package into 'C:/Users/Admin/AppData/Local/R/win-library/4.5'
## (as 'lib' is unspecified)
## package 'GGally' successfully unpacked and MD5 sums checked
## 
## The downloaded binary packages are in
##  C:\Users\Admin\AppData\Local\Temp\RtmpKYkmzk\downloaded_packages
library(GGally)
## Warning: package 'GGally' was built under R version 4.5.1
Data %>%
  select(Age, Monthly_Salary, Years_At_Company, Performance_Score, Employee_Satisfaction_Score) %>%
  ggpairs(title = "Biểu đồ ma trận tương quan giữa các biến định lượng")

# CHƯƠNG 2: PHÂN TÍCH DỮ LIỆU MÃ CHỨNG KHOÁN DBC

Mục tiêu: Trong tiểu luận này, mục tiêu chính là phân tích cấu trúc và biến động nguồn vốn của Công ty CP Tập đoàn Dabaco Việt Nam thông qua dữ liệu từ bảng cân đối kế toán trong giai đoạn nghiên cứu từ năm 2015 - 2024. Cụ thể, bài tiểu luận tập trung vào hai nhóm chỉ tiêu chính của Nguồn Vốn, bao gồm: Nợ phải trả và Vốn chủ sở hữu.

I. GIỚI THIỆU BỘ DỮ LIỆU

1. Đọc dữ liệu

# Đọc dữ liệu
install.packages("janitor")
## Installing package into 'C:/Users/Admin/AppData/Local/R/win-library/4.5'
## (as 'lib' is unspecified)
## package 'janitor' successfully unpacked and MD5 sums checked
## 
## The downloaded binary packages are in
##  C:\Users\Admin\AppData\Local\Temp\RtmpKYkmzk\downloaded_packages
library(janitor)
## Warning: package 'janitor' was built under R version 4.5.1
## 
## Attaching package: 'janitor'
## The following objects are masked from 'package:stats':
## 
##     chisq.test, fisher.test
library(readxl)
dataDBC <- read_excel("D:/NNLT/DBC/dataDBC.xlsx", sheet = "Sheet1")
df <- read_excel("D:/NNLT/DBC/dataDBC.xlsx", sheet = "Sheet1")
head(df)
## # A tibble: 6 × 18
##    Date `NỢ PHẢI TRẢ` `Nợ ngắn hạn` `Phải trả người bán ngắn hạn`
##   <dbl>         <dbl>         <dbl>                         <dbl>
## 1  2024 7355476127696 6420694102809                  762647490938
## 2  2023 8345469400426 7141605465752                  795600820770
## 3  2022 8332876258119 7213028754790                 2129218054781
## 4  2021 6176631172021 5171698802616                 1392462971688
## 5  2020 5894311104553 4254585526684                 1012195989287
## 6  2019 6565967444140 4819677610567                  911471772009
## # ℹ 14 more variables: `Người mua trả tiền trước ngắn hạn` <dbl>,
## #   `Thuế và các khoản phải nộp Nhà nước` <dbl>,
## #   `Phải trả người lao động` <dbl>, `Chi phí phải trả ngắn hạn` <dbl>,
## #   `Phải trả ngắn hạn khác` <dbl>, `Vay và nợ thuê tài chính ngắn hạn` <dbl>,
## #   `Quỹ khen thưởng, phúc lợi` <dbl>, `Nợ dài hạn` <dbl>,
## #   `VỐN CHỦ SỞ HỮU` <dbl>, `Vốn góp của chủ sở hữu` <dbl>,
## #   `Thặng dư vốn cổ phần` <dbl>, `Quỹ đầu tư phát triển` <dbl>, …

Lệnh read_excel() đọc dữ liệu từ “Sheet1”. Sử dụng lệnh head() hiển thị 6 dòng đầu để xác định có đọc đúng và dữ liệu có bị lệch dòng, lệch cột hay không.

2. Số dòng và số cột

dim(dataDBC)
## [1] 10 18

Lệnh dim() dùng để xác định kích thước của bảng dữ liệu. Kết quả cho thấy: 10 18 nghĩa là bảng dataDBC có 10 hàng (quan sát) và 18 cột (biến). Đây là bước kiểm tra cơ bản, đảm bảo dữ liệu đã được đọc đúng và có đủ số lượng biến cần phân tích.

3. Tên các biến

names(dataDBC)
##  [1] "Date"                                "NỢ PHẢI TRẢ"                        
##  [3] "Nợ ngắn hạn"                         "Phải trả người bán ngắn hạn"        
##  [5] "Người mua trả tiền trước ngắn hạn"   "Thuế và các khoản phải nộp Nhà nước"
##  [7] "Phải trả người lao động"             "Chi phí phải trả ngắn hạn"          
##  [9] "Phải trả ngắn hạn khác"              "Vay và nợ thuê tài chính ngắn hạn"  
## [11] "Quỹ khen thưởng, phúc lợi"           "Nợ dài hạn"                         
## [13] "VỐN CHỦ SỞ HỮU"                      "Vốn góp của chủ sở hữu"             
## [15] "Thặng dư vốn cổ phần"                "Quỹ đầu tư phát triển"              
## [17] "Lợi nhuận sau thuế chưa phân phối"   "TỔNG CỘNG NGUỒN VỐN"
dataDBC <- clean_names(dataDBC)

Hàm names() giúp người dùng kiểm tra nhanh toàn bộ cấu trúc tên biến trong bảng dữ liệu. Kết quả dữ liệu cho thấy gồm 18 biến mô tả cấu trúc nguồn vốn của doanh nghiệp. Vì trong R, tên biến (variable names) phải tuân thủ quy tắc cú pháp: Không có dấu tiếng Việt (ă, â, ê, ô, ơ, đ, …), Không có khoảng trắng, dấu chấm câu, ký tự đặc biệt (-, /, ,, (, ), v.v.), Không bắt đầu bằng số, nên sẽ xử lý bằng cách loại bỏ dấu và khoảng trắng có trong biến để trong quá trình gọi biến trong code không bị lỗi.

4. Xác định phạm vi thời gian

nam_bat_dau <- min(dataDBC$date, na.rm = TRUE)
nam_ket_thuc <- max(dataDBC$date, na.rm = TRUE)
cat("Phạm vi thời gian của bộ dữ liệu từ năm", nam_bat_dau, "đến năm", nam_ket_thuc, "\n")
## Phạm vi thời gian của bộ dữ liệu từ năm 2015 đến năm 2024

Bộ dữ liệu bao gồm 10 năm liên tiếp (2015–2024). Điều này cho phép quan sát xu hướng biến động dài hạn của các khoản nợ phải trả, vốn chủ sở hữu, và tổng nguồn vốn.

5. Phân loại biến theo nhóm

phan_loai_bien <- data.frame(
Nhom = c(
rep("NỢ PHẢI TRẢ - NỢ NGẮN HẠN", 8),
rep("NỢ PHẢI TRẢ - NỢ DÀI HẠN", 1),
rep("VỐN CHỦ SỞ HỮU", 5),
"TỔNG CỘNG NGUỒN VỐN"
),
Bien = c(
"no_phai_tra",
"no_ngan_han",
"phai_tra_nguoi_ban_ngan_han",
"nguoi_mua_tra_tien_truoc_ngan_han",
"thue_va_cac_khoan_phai_nop_nha_nuoc",
"phai_tra_nguoi_lao_dong",
"chi_phi_phai_tra_ngan_han",
"phai_tra_ngan_han_khac",
"no_dai_han",
"von_chu_so_huu",
"von_gop_cua_chu_so_huu",
"thang_du_von_co_phan",
"quy_dau_tu_phat_trien",
"loi_nhuan_sau_thue_chua_phan_phoi",
"tong_cong_nguon_von"
)
)
print(phan_loai_bien)
##                         Nhom                                Bien
## 1  NỢ PHẢI TRẢ - NỢ NGẮN HẠN                         no_phai_tra
## 2  NỢ PHẢI TRẢ - NỢ NGẮN HẠN                         no_ngan_han
## 3  NỢ PHẢI TRẢ - NỢ NGẮN HẠN         phai_tra_nguoi_ban_ngan_han
## 4  NỢ PHẢI TRẢ - NỢ NGẮN HẠN   nguoi_mua_tra_tien_truoc_ngan_han
## 5  NỢ PHẢI TRẢ - NỢ NGẮN HẠN thue_va_cac_khoan_phai_nop_nha_nuoc
## 6  NỢ PHẢI TRẢ - NỢ NGẮN HẠN             phai_tra_nguoi_lao_dong
## 7  NỢ PHẢI TRẢ - NỢ NGẮN HẠN           chi_phi_phai_tra_ngan_han
## 8  NỢ PHẢI TRẢ - NỢ NGẮN HẠN              phai_tra_ngan_han_khac
## 9   NỢ PHẢI TRẢ - NỢ DÀI HẠN                          no_dai_han
## 10            VỐN CHỦ SỞ HỮU                      von_chu_so_huu
## 11            VỐN CHỦ SỞ HỮU              von_gop_cua_chu_so_huu
## 12            VỐN CHỦ SỞ HỮU                thang_du_von_co_phan
## 13            VỐN CHỦ SỞ HỮU               quy_dau_tu_phat_trien
## 14            VỐN CHỦ SỞ HỮU   loi_nhuan_sau_thue_chua_phan_phoi
## 15       TỔNG CỘNG NGUỒN VỐN                 tong_cong_nguon_von

Hàm data.frame() giúp tạo bảng phan_loai_bien sẽ có 2 cột: Nhom: nhóm phân loại chính (bài báo cáo này phân tích Nguồn vốn của doanh nghiệp gồm 2 chỉ tiêu chính: Nợ phải trả và Vốn chủ sở hữu) và Bien: tên biến tương ứng trong dữ liệu

6. Xác định đơn vị tính

debt_2024 <- dataDBC %>% filter(date == 2024) %>% pull(no_phai_tra)
equity_2024 <- dataDBC %>% filter(date == 2024) %>% pull(von_chu_so_huu)




cat("Giá trị mẫu - Tổng Nợ phải trả năm 2024:",
format(debt_2024, big.mark = ",", scientific = FALSE), "\n")
## Giá trị mẫu - Tổng Nợ phải trả năm 2024: 7,355,476,127,696
cat("Giá trị mẫu - Vốn chủ sở hữu năm 2024:",
format(equity_2024, big.mark = ",", scientific = FALSE), "\n\n")
## Giá trị mẫu - Vốn chủ sở hữu năm 2024: 6,766,079,699,901
cat("Nhận xét:\n")
## Nhận xét:
cat(" Các giá trị nằm trong khoảng 10^12 đến 10^13\n")
##  Các giá trị nằm trong khoảng 10^12 đến 10^13
cat(" Điều này tương ứng với quy mô hàng nghìn tỷ đồng\n")
##  Điều này tương ứng với quy mô hàng nghìn tỷ đồng
cat("Kết luận: Đơn vị dữ liệu gốc là Đồng Việt Nam (VND)\n")
## Kết luận: Đơn vị dữ liệu gốc là Đồng Việt Nam (VND)
cat("Để thuận tiện cho phân tích, nên quy đổi sang Tỷ VNĐ (chia 1e9).\n")
## Để thuận tiện cho phân tích, nên quy đổi sang Tỷ VNĐ (chia 1e9).

7. Cấu trúc dữ liệu

str(dataDBC)
## tibble [10 × 18] (S3: tbl_df/tbl/data.frame)
##  $ date                               : num [1:10] 2024 2023 2022 2021 2020 ...
##  $ no_phai_tra                        : num [1:10] 7.36e+12 8.35e+12 8.33e+12 6.18e+12 5.89e+12 ...
##  $ no_ngan_han                        : num [1:10] 6.42e+12 7.14e+12 7.21e+12 5.17e+12 4.25e+12 ...
##  $ phai_tra_nguoi_ban_ngan_han        : num [1:10] 7.63e+11 7.96e+11 2.13e+12 1.39e+12 1.01e+12 ...
##  $ nguoi_mua_tra_tien_truoc_ngan_han  : num [1:10] 2.07e+11 2.21e+11 8.87e+11 5.88e+11 5.52e+11 ...
##  $ thue_va_cac_khoan_phai_nop_nha_nuoc: num [1:10] 1.00e+11 3.25e+10 4.54e+10 7.96e+10 1.39e+11 ...
##  $ phai_tra_nguoi_lao_dong            : num [1:10] 8.63e+10 7.63e+10 6.49e+10 1.09e+11 1.07e+11 ...
##  $ chi_phi_phai_tra_ngan_han          : num [1:10] 5.31e+10 1.04e+11 6.45e+10 7.65e+10 6.35e+10 ...
##  $ phai_tra_ngan_han_khac             : num [1:10] 2.69e+11 1.04e+12 2.21e+11 2.38e+11 2.00e+11 ...
##  $ vay_va_no_thue_tai_chinh_ngan_han  : num [1:10] 4.93e+12 4.84e+12 3.70e+12 2.60e+12 2.16e+12 ...
##  $ quy_khen_thuong_phuc_loi           : num [1:10] 1.35e+10 3.34e+10 9.55e+10 8.97e+10 2.21e+10 ...
##  $ no_dai_han                         : num [1:10] 9.35e+11 1.20e+12 1.12e+12 1.00e+12 1.64e+12 ...
##  $ von_chu_so_huu                     : num [1:10] 6.77e+12 4.67e+12 4.64e+12 4.69e+12 4.21e+12 ...
##  $ von_gop_cua_chu_so_huu             : num [1:10] 3.35e+12 2.42e+12 2.42e+12 1.15e+12 1.05e+12 ...
##  $ thang_du_von_co_phan               : num [1:10] 8.22e+11 4.18e+11 4.18e+11 4.18e+11 4.18e+11 ...
##  $ quy_dau_tu_phat_trien              : num [1:10] 1.82e+12 1.80e+12 1.79e+12 2.52e+12 1.50e+12 ...
##  $ loi_nhuan_sau_thue_chua_phan_phoi  : num [1:10] 7.72e+11 2.79e+10 8.10e+09 5.95e+11 1.24e+12 ...
##  $ tong_cong_nguon_von                : num [1:10] 1.41e+13 1.30e+13 1.30e+13 1.09e+13 1.01e+13 ...

Hàm str() giúp mô tả cấu trúc dữ liệu tài chính: - Là tibble(bảng dữ liệu) có 10 dòng × 18 cột. - Từ kết quả cho thấy các biến đều là kiểu dữ liệu số (numeric). - Mỗi biến biểu diễn một chỉ tiêu trong phần “Nguồn vốn” của bảng cân đối kế toán.

8. Ý nghĩa các biến

Bộ dữ liệu được thu thập từ Báo cáo tài chính hợp nhất của Công ty Cổ phần Tập đoàn Dabaco Việt Nam (mã chứng khoán: DBC) giai đoạn 2015–2024, bao gồm 18 biến phản ánh cơ cấu Nguồn vốn. Các biến được chia thành 2 nhóm chính: Nợ phải trả và Vốn chủ sở hữu. Ý nghĩa chi tiết của từng biến được trình bày trong bảng dưới đây.

# --- Tạo bảng giải thích ý nghĩa các biến trong bộ dữ liệu ---
library(dplyr)

# Tạo data frame chứa tên biến và ý nghĩa chi tiết
giai_thich_bien <- data.frame(
  Bien = c(
    "date",
    "no_phai_tra",
    "no_ngan_han",
    "phai_tra_nguoi_ban_ngan_han",
    "nguoi_mua_tra_tien_truoc_ngan_han",
    "thue_va_cac_khoan_phai_nop_nha_nuoc",
    "phai_tra_nguoi_lao_dong",
    "chi_phi_phai_tra_ngan_han",
    "phai_tra_ngan_han_khac",
    "vay_va_no_thue_tai_chinh_ngan_han",
    "quy_khen_thuong_phuc_loi",
    "no_dai_han",
    "von_chu_so_huu",
    "von_gop_cua_chu_so_huu",
    "thang_du_von_co_phan",
    "quy_dau_tu_phat_trien",
    "loi_nhuan_sau_thue_chua_phan_phoi",
    "tong_cong_nguon_von"
  ),
  Y_nghia = c(
    "Năm tài chính của dữ liệu – thể hiện chu kỳ thời gian để so sánh biến động nguồn vốn qua các năm.",
    "Tổng nợ phải trả – bao gồm toàn bộ nghĩa vụ tài chính mà doanh nghiệp cần thanh toán trong tương lai.",
    "Tổng nợ ngắn hạn – các khoản nợ có thời hạn thanh toán dưới 1 năm.",
    "Khoản doanh nghiệp phải trả cho nhà cung cấp hàng hóa, dịch vụ trong ngắn hạn.",
    "Các khoản tiền mà khách hàng trả trước cho doanh nghiệp để nhận hàng hóa/dịch vụ trong tương lai.",
    "Các khoản thuế và nghĩa vụ tài chính doanh nghiệp phải nộp cho Nhà nước.",
    "Tiền lương, thưởng và các khoản phải trả cho người lao động chưa chi trả.",
    "Các chi phí đã phát sinh nhưng chưa thanh toán trong kỳ kế toán (như chi phí lãi vay, thuê ngoài, bảo trì…).",
    "Các khoản phải trả khác không nằm trong các mục trên, ví dụ: ký quỹ, ký cược, hoặc tạm giữ hộ.",
    "Các khoản vay và nợ thuê tài chính ngắn hạn, phải trả trong vòng 12 tháng tới.",
    "Nguồn quỹ dùng để thưởng cho nhân viên hoặc phúc lợi tập thể (mang tính chất nội bộ).",
    "Tổng nợ dài hạn – các khoản nợ có kỳ hạn thanh toán trên 1 năm, thường gồm vay ngân hàng dài hạn, trái phiếu…",
    "Tổng vốn chủ sở hữu – phần tài sản ròng thuộc về các cổ đông sau khi trừ đi nghĩa vụ nợ.",
    "Phần vốn góp ban đầu hoặc bổ sung của các chủ sở hữu (cổ đông).",
    "Khoản chênh lệch giữa giá phát hành cổ phần và mệnh giá – thể hiện phần vốn thặng dư từ phát hành cổ phiếu.",
    "Quỹ được trích lập từ lợi nhuận sau thuế nhằm tái đầu tư, mở rộng sản xuất kinh doanh.",
    "Lợi nhuận tích lũy qua các năm mà doanh nghiệp chưa phân phối hoặc chia cổ tức.",
    "Tổng cộng toàn bộ nguồn hình thành nên tài sản – bằng tổng nợ phải trả và vốn chủ sở hữu."
  )
)

# In ra bảng
print(giai_thich_bien)
##                                   Bien
## 1                                 date
## 2                          no_phai_tra
## 3                          no_ngan_han
## 4          phai_tra_nguoi_ban_ngan_han
## 5    nguoi_mua_tra_tien_truoc_ngan_han
## 6  thue_va_cac_khoan_phai_nop_nha_nuoc
## 7              phai_tra_nguoi_lao_dong
## 8            chi_phi_phai_tra_ngan_han
## 9               phai_tra_ngan_han_khac
## 10   vay_va_no_thue_tai_chinh_ngan_han
## 11            quy_khen_thuong_phuc_loi
## 12                          no_dai_han
## 13                      von_chu_so_huu
## 14              von_gop_cua_chu_so_huu
## 15                thang_du_von_co_phan
## 16               quy_dau_tu_phat_trien
## 17   loi_nhuan_sau_thue_chua_phan_phoi
## 18                 tong_cong_nguon_von
##                                                                                                          Y_nghia
## 1              Năm tài chính của dữ liệu – thể hiện chu kỳ thời gian để so sánh biến động nguồn vốn qua các năm.
## 2          Tổng nợ phải trả – bao gồm toàn bộ nghĩa vụ tài chính mà doanh nghiệp cần thanh toán trong tương lai.
## 3                                             Tổng nợ ngắn hạn – các khoản nợ có thời hạn thanh toán dưới 1 năm.
## 4                                 Khoản doanh nghiệp phải trả cho nhà cung cấp hàng hóa, dịch vụ trong ngắn hạn.
## 5              Các khoản tiền mà khách hàng trả trước cho doanh nghiệp để nhận hàng hóa/dịch vụ trong tương lai.
## 6                                       Các khoản thuế và nghĩa vụ tài chính doanh nghiệp phải nộp cho Nhà nước.
## 7                                      Tiền lương, thưởng và các khoản phải trả cho người lao động chưa chi trả.
## 8   Các chi phí đã phát sinh nhưng chưa thanh toán trong kỳ kế toán (như chi phí lãi vay, thuê ngoài, bảo trì…).
## 9                 Các khoản phải trả khác không nằm trong các mục trên, ví dụ: ký quỹ, ký cược, hoặc tạm giữ hộ.
## 10                                Các khoản vay và nợ thuê tài chính ngắn hạn, phải trả trong vòng 12 tháng tới.
## 11                         Nguồn quỹ dùng để thưởng cho nhân viên hoặc phúc lợi tập thể (mang tính chất nội bộ).
## 12 Tổng nợ dài hạn – các khoản nợ có kỳ hạn thanh toán trên 1 năm, thường gồm vay ngân hàng dài hạn, trái phiếu…
## 13                      Tổng vốn chủ sở hữu – phần tài sản ròng thuộc về các cổ đông sau khi trừ đi nghĩa vụ nợ.
## 14                                               Phần vốn góp ban đầu hoặc bổ sung của các chủ sở hữu (cổ đông).
## 15   Khoản chênh lệch giữa giá phát hành cổ phần và mệnh giá – thể hiện phần vốn thặng dư từ phát hành cổ phiếu.
## 16                        Quỹ được trích lập từ lợi nhuận sau thuế nhằm tái đầu tư, mở rộng sản xuất kinh doanh.
## 17                               Lợi nhuận tích lũy qua các năm mà doanh nghiệp chưa phân phối hoặc chia cổ tức.
## 18                     Tổng cộng toàn bộ nguồn hình thành nên tài sản – bằng tổng nợ phải trả và vốn chủ sở hữu.

9. Kiểm tra số quan sát bị thiếu hoặc trùng lặp

so_bien <- ncol(dataDBC)
so_quan_sat <- nrow(dataDBC)
so_trung_lap <- sum(duplicated(dataDBC))
so_thieu <- sum(is.na(dataDBC))
ty_le_thieu <- round(so_thieu / (so_bien * so_quan_sat) * 100, 2)

thong_tin_co_ban <- data.frame(
Chi_tieu = c(
"Số biến (cột)",
"Số quan sát (dòng)",
"Số quan sát trùng lặp",
"Số quan sát bị thiếu",
"Tỷ lệ quan sát bị thiếu (%)"
),
Gia_tri = c(so_bien, so_quan_sat, so_trung_lap, so_thieu, ty_le_thieu)
)
print(thong_tin_co_ban)
##                      Chi_tieu Gia_tri
## 1               Số biến (cột)      18
## 2          Số quan sát (dòng)      10
## 3       Số quan sát trùng lặp       0
## 4        Số quan sát bị thiếu       0
## 5 Tỷ lệ quan sát bị thiếu (%)       0

Hàm ncol() và nrow() thể hiện cột(số biến) và hàng(số quan sát). Hàm sum(duplicated()), sum(is.na()) hai chỉ tiêu này đều cho thấy số quan sát trùng lặp và số quan sát bị thiếu đều là 0, do đó tỉ lệ quan sát bị thiếu là không có

10. Đánh giá sơ bộ các chỉ tiêu chính

# --- ĐÁNH GIÁ SƠ BỘ XU HƯỚNG CÁC KHOẢN MỤC CHÍNH ---

# --- PHÂN TÍCH XU HƯỚNG 3 CHỈ TIÊU CHÍNH (2015–2024) ---
library(dplyr)

# 1. Tổng NỢ PHẢI TRẢ
cat("Xu hướng tổng NỢ PHẢI TRẢ (2015–2024):\n")
## Xu hướng tổng NỢ PHẢI TRẢ (2015–2024):
liabilities_trend <- dataDBC %>%
  arrange(date) %>%
  select(date, no_phai_tra)

for (i in 1:nrow(liabilities_trend)) {
  year <- liabilities_trend$date[i]
  value <- liabilities_trend$no_phai_tra[i]
  cat("  ", year, ": ", format(value, big.mark = ",", scientific = FALSE), "\n", sep = "")
}
##   2015: 2,668,763,190,851
##   2016: 3,190,129,918,957
##   2017: 4,486,599,351,977
##   2018: 5,603,485,031,551
##   2019: 6,565,967,444,140
##   2020: 5,894,311,104,553
##   2021: 6,176,631,172,021
##   2022: 8,332,876,258,119
##   2023: 8,345,469,400,426
##   2024: 7,355,476,127,696
trend_direction_liab <- ifelse(tail(liabilities_trend$no_phai_tra, 1) > head(liabilities_trend$no_phai_tra, 1),
                               "Tăng", "Giảm")
cat("\nNhận xét tổng quan: Xu hướng tổng NỢ PHẢI TRẢ là", trend_direction_liab, "qua giai đoạn 2015–2024.\n\n")
## 
## Nhận xét tổng quan: Xu hướng tổng NỢ PHẢI TRẢ là Tăng qua giai đoạn 2015–2024.
# 2. VỐN CHỦ SỞ HỮU
cat("Xu hướng VỐN CHỦ SỞ HỮU (2015–2024):\n")
## Xu hướng VỐN CHỦ SỞ HỮU (2015–2024):
equity_trend <- dataDBC %>%
  arrange(date) %>%
  select(date, von_chu_so_huu)

for (i in 1:nrow(equity_trend)) {
  year <- equity_trend$date[i]
  value <- equity_trend$von_chu_so_huu[i]
  cat("  ", year, ": ", format(value, big.mark = ",", scientific = FALSE), "\n", sep = "")
}
##   2015: 1,946,447,536,231
##   2016: 2,339,141,904,502
##   2017: 2,502,616,605,237
##   2018: 2,746,528,417,636
##   2019: 3,025,957,478,860
##   2020: 4,206,960,190,688
##   2021: 4,685,923,120,134
##   2022: 4,641,227,653,231
##   2023: 4,666,234,857,446
##   2024: 6,766,079,699,901
trend_direction_equity <- ifelse(tail(equity_trend$von_chu_so_huu, 1) > head(equity_trend$von_chu_so_huu, 1),
                                 "Tăng", "Giảm")
cat("\nNhận xét tổng quan: Xu hướng VỐN CHỦ SỞ HỮU là", trend_direction_equity, "qua giai đoạn 2015–2024.\n\n")
## 
## Nhận xét tổng quan: Xu hướng VỐN CHỦ SỞ HỮU là Tăng qua giai đoạn 2015–2024.
# 3. TỔNG CỘNG NGUỒN VỐN
cat("Xu hướng TỔNG CỘNG NGUỒN VỐN (2015–2024):\n")
## Xu hướng TỔNG CỘNG NGUỒN VỐN (2015–2024):
total_capital_trend <- dataDBC %>%
  arrange(date) %>%
  select(date, tong_cong_nguon_von)

for (i in 1:nrow(total_capital_trend)) {
  year <- total_capital_trend$date[i]
  value <- total_capital_trend$tong_cong_nguon_von[i]
  cat("  ", year, ": ", format(value, big.mark = ",", scientific = FALSE), "\n", sep = "")
}
##   2015: 4,615,210,727,082
##   2016: 5,529,271,823,459
##   2017: 6,989,215,957,214
##   2018: 8,350,013,449,187
##   2019: 9,591,924,923,000
##   2020: 10,101,271,295,241
##   2021: 10,862,564,292,155
##   2022: 12,974,103,921,350
##   2023: 13,011,704,257,872
##   2024: 14,121,555,827,597
trend_direction_total <- ifelse(tail(total_capital_trend$tong_cong_nguon_von, 1) > head(total_capital_trend$tong_cong_nguon_von, 1),
                                "Tăng", "Giảm")
cat("\nNhận xét tổng quan: Xu hướng TỔNG CỘNG NGUỒN VỐN là", trend_direction_total, "qua giai đoạn 2015–2024.\n")
## 
## Nhận xét tổng quan: Xu hướng TỔNG CỘNG NGUỒN VỐN là Tăng qua giai đoạn 2015–2024.

11. Đánh giá các chỉ tiêu chính qua biểu đồ

library(ggplot2)
install.packages("tidyr")
## Installing package into 'C:/Users/Admin/AppData/Local/R/win-library/4.5'
## (as 'lib' is unspecified)
## package 'tidyr' successfully unpacked and MD5 sums checked
## Warning: cannot remove prior installation of package 'tidyr'
## Warning in file.copy(savedcopy, lib, recursive = TRUE): problem copying
## C:\Users\Admin\AppData\Local\R\win-library\4.5\00LOCK\tidyr\libs\x64\tidyr.dll
## to C:\Users\Admin\AppData\Local\R\win-library\4.5\tidyr\libs\x64\tidyr.dll:
## Permission denied
## Warning: restored 'tidyr'
## 
## The downloaded binary packages are in
##  C:\Users\Admin\AppData\Local\Temp\RtmpKYkmzk\downloaded_packages
library(tidyr)
## Warning: package 'tidyr' was built under R version 4.5.1
dataDBC %>%
  select(date, no_phai_tra, von_chu_so_huu, tong_cong_nguon_von) %>%
  pivot_longer(-date, names_to = "Chi_tieu", values_to = "Gia_tri") %>%
  ggplot(aes(x = date, y = Gia_tri, color = Chi_tieu, group = Chi_tieu)) +
  geom_line(size = 1.2) +
  geom_point(size = 2) +
  theme_minimal() +
  labs(title = "Xu hướng Nợ phải trả, Vốn chủ sở hữu và Tổng nguồn vốn (2015–2024)",
       x = "Năm", y = "Giá trị (tỷ VND)")
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

II. XỬ LÝ DỮ LIỆU

1. Kiểm tra và xử lý giá trị ngoại lai**

for (b in c("no_phai_tra", "von_chu_so_huu", "tong_cong_nguon_von")) {
  boxplot(dataDBC[[b]], main = paste("Kiểm tra ngoại lai -", b))
  print(summary(dataDBC[[b]]))
}

##      Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
## 2.669e+12 4.766e+12 6.035e+12 5.862e+12 7.158e+12 8.345e+12

##      Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
## 1.946e+12 2.564e+12 3.616e+12 3.753e+12 4.660e+12 6.766e+12

##      Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
## 4.615e+12 7.329e+12 9.847e+12 9.615e+12 1.245e+13 1.412e+13

Nhận xét kiểm tra ngoại lai – Nợ phải trả - Không có điểm ngoại lai (outlier): Biểu đồ không xuất hiện các chấm rời nằm ngoài hai “râu” (whiskers), tức là không có giá trị ngoại lai đáng kể. Điều này cho thấy dữ liệu khá ổn định, không có năm nào có giá trị nợ phải trả quá khác biệt so với các năm khác. - Phân bố dữ liệu: Chiều dài hộp và râu cho thấy dữ liệu phân bố khá đều, không bị lệch nhiều. Trung vị nằm gần giữa hộp → nợ phải trả phân bố đối xứng, không nghiêng về phía tăng hay giảm mạnh trong giai đoạn phân tích. - Khoảng biến động: Phạm vi từ đáy hộp đến đỉnh hộp thể hiện sự biến động trung bình của nợ phải trả giữa các năm. Nhìn chung, biến động không quá lớn, chứng tỏ doanh nghiệp duy trì mức nợ phải trả ổn định qua thời gian.

Nhận xét kiểm tra ngoại lai – Vốn chủ sở hữu - Phạm vi giá trị của “vốn chủ sở hữu” nằm trong khoảng từ 2.000 đến 6700 (tỷ đồng). - Đường giữa hộp (Median) nằm gần khoảng 3.600–3.800, cho thấy phân bố giá trị khá cân đối, không bị lệch mạnh. - Không có điểm dữ liệu nào nằm ngoài râu trên hoặc râu dưới ⟹ không xuất hiện ngoại lai (outlier). - Độ cao của hộp (IQR) cho thấy biến động vừa phải, phản ánh sự tăng trưởng tương đối ổn định của vốn chủ sở hữu qua các năm.

Nhận xét kiểm tra ngoại lai – Tổng cộng nguồn vốn - Dữ liệu phân bố khá cân đối, đường trung vị (đường đậm trong hộp) nằm gần giữa hộp, cho thấy phân bố không bị lệch mạnh. - Khoảng giá trị dao động từ khoảng 6.000 tỷ đồng đến 13.000 tỷ đồng. - Không có điểm ngoại lai (outlier) nào được thể hiện trên đồ thị, vì không có điểm riêng lẻ nằm ngoài hai “râu” của hộp. Điều này cho thấy tổng cộng nguồn vốn biến động ổn định, không có năm nào bất thường về quy mô vốn.

2. Chuẩn hóa đơn vị**

dataDBC <- dataDBC %>%
mutate(across(
.cols = -date,
.fns = ~ round(.x / 1e9, 3)
))
head(dataDBC)
## # A tibble: 6 × 18
##    date no_phai_tra no_ngan_han phai_tra_nguoi_ban_ngan…¹ nguoi_mua_tra_tien_t…²
##   <dbl>       <dbl>       <dbl>                     <dbl>                  <dbl>
## 1  2024       7355.       6421.                      763.                   207.
## 2  2023       8345.       7142.                      796.                   221.
## 3  2022       8333.       7213.                     2129.                   887.
## 4  2021       6177.       5172.                     1392.                   588.
## 5  2020       5894.       4255.                     1012.                   552.
## 6  2019       6566.       4820.                      911.                   410.
## # ℹ abbreviated names: ¹​phai_tra_nguoi_ban_ngan_han,
## #   ²​nguoi_mua_tra_tien_truoc_ngan_han
## # ℹ 13 more variables: thue_va_cac_khoan_phai_nop_nha_nuoc <dbl>,
## #   phai_tra_nguoi_lao_dong <dbl>, chi_phi_phai_tra_ngan_han <dbl>,
## #   phai_tra_ngan_han_khac <dbl>, vay_va_no_thue_tai_chinh_ngan_han <dbl>,
## #   quy_khen_thuong_phuc_loi <dbl>, no_dai_han <dbl>, von_chu_so_huu <dbl>,
## #   von_gop_cua_chu_so_huu <dbl>, thang_du_von_co_phan <dbl>, …

3. Chuẩn hóa thời gian

dataDBC$date <- as.numeric(dataDBC$date)

4. Sắp xếp theo thời gian

dataDBC <- dataDBC[order(dataDBC$date), ]
head(dataDBC)
## # A tibble: 6 × 18
##    date no_phai_tra no_ngan_han phai_tra_nguoi_ban_ngan…¹ nguoi_mua_tra_tien_t…²
##   <dbl>       <dbl>       <dbl>                     <dbl>                  <dbl>
## 1  2015       2669.       2411.                      534.                   94.5
## 2  2016       3190.       2630.                      318.                  147. 
## 3  2017       4487.       3462.                      564.                  132. 
## 4  2018       5603.       4075.                      923.                  207. 
## 5  2019       6566.       4820.                      911.                  410. 
## 6  2020       5894.       4255.                     1012.                  552. 
## # ℹ abbreviated names: ¹​phai_tra_nguoi_ban_ngan_han,
## #   ²​nguoi_mua_tra_tien_truoc_ngan_han
## # ℹ 13 more variables: thue_va_cac_khoan_phai_nop_nha_nuoc <dbl>,
## #   phai_tra_nguoi_lao_dong <dbl>, chi_phi_phai_tra_ngan_han <dbl>,
## #   phai_tra_ngan_han_khac <dbl>, vay_va_no_thue_tai_chinh_ngan_han <dbl>,
## #   quy_khen_thuong_phuc_loi <dbl>, no_dai_han <dbl>, von_chu_so_huu <dbl>,
## #   von_gop_cua_chu_so_huu <dbl>, thang_du_von_co_phan <dbl>, …

Dữ liệu được sắp xếp từ năm 2015 đến năm 2024.

5. Đặt nhãn cho các biến (Label encoding)

library(dplyr)

# Tạo vector nhãn ngắn gọn (để dùng khi vẽ biểu đồ)
labels <- c(
  no_phai_tra = "Nợ phải trả",
  no_ngan_han = "Nợ ngắn hạn",
  phai_tra_nguoi_ban_ngan_han = "Phải trả người bán NH",
  nguoi_mua_tra_tien_truoc_ngan_han = "Người mua trả tiền trước NH",
  thue_va_cac_khoan_phai_nop_nha_nuoc = "Thuế và khoản nộp NN",
  phai_tra_nguoi_lao_dong = "Phải trả NLĐ",
  chi_phi_phai_tra_ngan_han = "Chi phí phải trả NH",
  phai_tra_ngan_han_khac = "Phải trả NH khác",
  vay_va_no_thue_tai_chinh_ngan_han = "Vay và nợ thuê TC NH",
  quy_khen_thuong_phuc_loi = "Quỹ KTPL",
  no_dai_han = "Nợ dài hạn",
  von_chu_so_huu = "Vốn chủ sở hữu",
  von_gop_cua_chu_so_huu = "Vốn góp CSH",
  thang_du_von_co_phan = "Thặng dư VCP",
  quy_dau_tu_phat_trien = "Quỹ ĐTPT",
  loi_nhuan_sau_thue_chua_phan_phoi = "LNST chưa PP",
  tong_cong_nguon_von = "Tổng nguồn vốn"
)

# Gán nhãn làm thuộc tính
attr(dataDBC, "variable_labels") <- labels

6. Tạo biến hệ số nợ trên vốn chủ sở hữu

III. THỐNG KÊ CƠ BẢN

1. Thống kê mô tả cơ bản

library(psych)
describe(dataDBC[ , !names(dataDBC) %in% c("date")])
##                                     vars  n    mean      sd  median trimmed
## no_phai_tra                            1 10 5861.97 1954.86 6035.47 5950.68
## no_ngan_han                            2 10 4759.97 1734.75 4537.13 4746.96
## phai_tra_nguoi_ban_ngan_han            3 10  934.31  513.14  853.54  861.93
## nguoi_mua_tra_tien_truoc_ngan_han      4 10  344.59  258.36  214.39  307.99
## thue_va_cac_khoan_phai_nop_nha_nuoc    5 10   58.11   38.42   44.27   53.08
## phai_tra_nguoi_lao_dong                6 10   72.03   23.14   66.43   71.93
## chi_phi_phai_tra_ngan_han              7 10   68.00   25.29   64.01   68.37
## phai_tra_ngan_han_khac                 8 10  269.26  281.48  227.98  202.91
## vay_va_no_thue_tai_chinh_ngan_han      9 10 2974.18 1195.71 2655.01 2912.98
## quy_khen_thuong_phuc_loi              10 10   39.49   30.29   27.75   35.73
## no_dai_han                            11 10 1102.00  465.00 1072.02 1126.99
## von_chu_so_huu                        12 10 3752.71 1496.13 3616.46 3601.82
## von_gop_cua_chu_so_huu                13 10 1433.44  940.06  979.32 1295.04
## thang_du_von_co_phan                  14 10  458.74  127.47  418.43  418.43
## quy_dau_tu_phat_trien                 15 10 1441.47  564.50 1423.05 1401.99
## loi_nhuan_sau_thue_chua_phan_phoi     16 10  418.96  373.11  354.20  367.29
## tong_cong_nguon_von                   17 10 9614.68 3250.81 9846.60 9676.26
##                                         mad     min      max   range  skew
## no_phai_tra                         2126.70 2668.76  8345.47 5676.71 -0.27
## no_ngan_han                         2192.97 2410.96  7213.03 4802.07  0.15
## phai_tra_nguoi_ban_ngan_han          332.15  318.47  2129.22 1810.75  1.07
## nguoi_mua_tra_tien_truoc_ngan_han    149.77   94.49   887.48  792.99  0.83
## thue_va_cac_khoan_phai_nop_nha_nuoc   26.92   16.95   139.47  122.52  0.85
## phai_tra_nguoi_lao_dong               18.42   36.33   108.53   72.20  0.30
## chi_phi_phai_tra_ngan_han             24.39   28.73   104.36   75.63  0.11
## phai_tra_ngan_han_khac                50.85   31.90  1037.39 1005.49  1.92
## vay_va_no_thue_tai_chinh_ngan_han   1096.32 1509.51  4928.46 3418.96  0.50
## quy_khen_thuong_phuc_loi              20.45   13.52    95.53   82.02  0.88
## no_dai_han                           439.89  257.80  1746.29 1488.49 -0.26
## von_chu_so_huu                      1570.99 1946.45  6766.08 4819.63  0.53
## von_gop_cua_chu_so_huu               296.14  627.42  3346.69 2719.27  0.89
## thang_du_von_co_phan                   0.00  418.43   821.52  403.09  2.28
## quy_dau_tu_phat_trien                554.83  679.13  2519.66 1840.53  0.30
## loi_nhuan_sau_thue_chua_phan_phoi    294.31    8.10  1243.15 1235.05  0.89
## tong_cong_nguon_von                 4436.60 4615.21 14121.56 9506.35 -0.12
##                                     kurtosis      se
## no_phai_tra                            -1.36  618.18
## no_ngan_han                            -1.56  548.58
## phai_tra_nguoi_ban_ngan_han             0.28  162.27
## nguoi_mua_tra_tien_truoc_ngan_han      -0.74   81.70
## thue_va_cac_khoan_phai_nop_nha_nuoc    -0.62   12.15
## phai_tra_nguoi_lao_dong                -1.19    7.32
## chi_phi_phai_tra_ngan_han              -1.50    8.00
## phai_tra_ngan_han_khac                  2.63   89.01
## vay_va_no_thue_tai_chinh_ngan_han      -1.31  378.12
## quy_khen_thuong_phuc_loi               -0.91    9.58
## no_dai_han                             -1.11  147.05
## von_chu_so_huu                         -0.95  473.12
## von_gop_cua_chu_so_huu                 -0.91  297.27
## thang_du_von_co_phan                    3.57   40.31
## quy_dau_tu_phat_trien                  -1.03  178.51
## loi_nhuan_sau_thue_chua_phan_phoi      -0.25  117.99
## tong_cong_nguon_von                    -1.54 1027.99

2. Phân tích chi tiết xu hướng tổng nợ phải trả

library(ggplot2)
library(dplyr)

# Đảm bảo sắp xếp theo thời gian
dataDBC <- dataDBC %>% arrange(date)

# --- Vẽ xu hướng tổng nợ phải trả ---
ggplot(dataDBC, aes(x = date, y = no_phai_tra)) +
  geom_line(color = "#0072B2", size = 1.2) +             # Đường xu hướng
  geom_point(color = "#D55E00", size = 3) +              # Các điểm dữ liệu
  geom_smooth(method = "lm", se = FALSE, color = "gray40", linetype = "dashed") +  # Đường hồi quy tuyến tính
  theme_minimal(base_size = 13) +
  labs(title = "Xu hướng Tổng nợ phải trả qua các năm",
       x = "Năm",
       y = "Tổng nợ phải trả (Tỷ đồng)") +
  theme(
    plot.title = element_text(face = "bold", hjust = 0.5, size = 15),
    axis.title = element_text(face = "bold")
  )
## `geom_smooth()` using formula = 'y ~ x'

Nhận xét chi tiết xu hướng tổng nợ phải trả Giai đoạn 2015 – 2018: Đây là giai đoạn doanh nghiệp mở rộng quy mô hoạt động. Tổng nợ phải trả tăng mạnh, từ khoảng 2.800 tỷ đồng lên gần 5.500 tỷ đồng

Giai đoạn 2018 – 2020: Nợ tiếp tục tăng lên mức khoảng 6.800 tỷ đồng vào năm 2019, sau đó giảm nhẹ còn khoảng 5.900 tỷ đồng vào năm 2020. Sự giảm nhẹ này có thể liên quan đến giai đoạn dịch COVID-19, khi doanh nghiệp giảm vay mới hoặc trả bớt nợ.

Giai đoạn 2020 – 2023: Sau năm 2020, tổng nợ tăng mạnh trở lại, đạt đỉnh hơn 8.500 tỷ đồng vào năm 2022 và duy trì mức cao đến năm 2023. Cho thấy doanh nghiệp phục hồi và mở rộng trở lại sau dịch.

3. Phân tích cơ cấu nợ

library(dplyr)
library(ggplot2)
library(tidyr)

co_cau_no <- dataDBC %>%
  mutate(
    ty_trong_no_ngan_han = no_ngan_han / no_phai_tra * 100,
    ty_trong_no_dai_han  = no_dai_han  / no_phai_tra * 100,
    ty_le_no_tren_von    = no_phai_tra / tong_cong_nguon_von * 100
  )

# Biểu đồ cơ cấu nợ
co_cau_long <- co_cau_no %>%
  select(date, ty_trong_no_ngan_han, ty_trong_no_dai_han) %>%
  pivot_longer(-date, names_to = "Loai_no", values_to = "Ty_trong")

ggplot(co_cau_long, aes(x = factor(date), y = Ty_trong, fill = Loai_no)) +
  geom_bar(stat = "identity", position = "stack") +
  labs(title = "Cơ cấu nợ qua các năm",
       x = "Năm", y = "Tỷ trọng (%)") +
  scale_fill_manual(values = c("#0073C2", "#E69F00"),
                    name = "Loại nợ",
                    labels = c("Nợ dài hạn", "Nợ ngắn hạn")) +
  theme_minimal(base_size = 13)

Nhận xét cơ cấu nợ qua các năm (2015–2024) Dựa vào biểu đồ cột chồng thể hiện tỷ trọng nợ ngắn hạn và nợ dài hạn, ta có thể thấy: 1. Nợ ngắn hạn chiếm tỷ trọng chủ yếu Trong toàn giai đoạn 2015–2024, nợ ngắn hạn luôn chiếm phần lớn trong tổng nợ phải trả, dao động từ khoảng 70% đến 90%. Điều này cho thấy doanh nghiệp phụ thuộc nhiều vào các khoản vay ngắn hạn, chủ yếu để phục vụ nhu cầu vốn lưu động, hàng tồn kho hoặc hoạt động sản xuất – kinh doanh ngắn kỳ. 2. Nợ dài hạn có xu hướng biến động ngược chiều Tỷ trọng nợ dài hạn nhìn chung ở mức thấp (10–30%), tuy nhiên có sự dao động nhẹ giữa các năm. 3. Cơ cấu nợ ít biến động mạnh nhưng thể hiện chiến lược rõ ràng: Cơ cấu nợ qua các năm khá ổn định, tỷ trọng nợ ngắn hạn luôn duy trì mức cao, cho thấy doanh nghiệp giữ chiến lược tài chính linh hoạt — tận dụng nguồn vốn ngắn hạn chi phí thấp nhưng có rủi ro thanh khoản cao hơn. Việc tỷ lệ nợ dài hạn thấp cũng đồng nghĩa với áp lực trả nợ ngắn hạn lớn hơn, nhất là khi điều kiện tín dụng hoặc thị trường thay đổi. 4. Cơ cấu nợ mất cân đối (nợ ngắn hạn chiếm tỷ trọng lớn) → rủi ro thanh toán cao hơn, đặc biệt nếu dòng tiền ngắn hạn bị gián đoạn. Tuy nhiên, chiến lược sử dụng nợ ngắn hạn cũng giúp doanh nghiệp tận dụng lãi suất thấp, tăng hiệu quả sử dụng vốn trong ngắn hạn.

4. Phân tích thành phần nợ ngắn hạn

library(dplyr)
library(tidyr)
library(ggplot2)

# Lấy nhãn từ thuộc tính đã gán
labels <- attr(dataDBC, "variable_labels")

# Tạo bảng cơ cấu nợ ngắn hạn (trừ no_phai_tra)
co_cau_no_ngan_han <- dataDBC %>%
  mutate(
    tong_no_ngan_han = phai_tra_nguoi_ban_ngan_han +
                       nguoi_mua_tra_tien_truoc_ngan_han +
                       thue_va_cac_khoan_phai_nop_nha_nuoc +
                       phai_tra_nguoi_lao_dong +
                       chi_phi_phai_tra_ngan_han +
                       phai_tra_ngan_han_khac
  ) %>%
  select(date, phai_tra_nguoi_ban_ngan_han, nguoi_mua_tra_tien_truoc_ngan_han,
         thue_va_cac_khoan_phai_nop_nha_nuoc, phai_tra_nguoi_lao_dong,
         chi_phi_phai_tra_ngan_han, phai_tra_ngan_han_khac, tong_no_ngan_han) %>%
  pivot_longer(
    cols = -c(date, tong_no_ngan_han),
    names_to = "khoan_muc",
    values_to = "gia_tri"
  ) %>%
  mutate(
    ty_trong = gia_tri / tong_no_ngan_han * 100,
    # Thay tên khoản mục bằng nhãn thân thiện
    khoan_muc = labels[khoan_muc]
  )

# Vẽ biểu đồ cơ cấu nợ ngắn hạn qua các năm
ggplot(co_cau_no_ngan_han, aes(x = date, y = ty_trong, fill = khoan_muc)) +
  geom_bar(stat = "identity") +
  scale_fill_brewer(palette = "Set2") +
  labs(
    title = "Cơ cấu các khoản mục trong Nợ ngắn hạn qua các năm",
    x = "Năm", y = "Tỷ trọng (%)",
    fill = "Khoản mục"
  ) +
  theme_minimal(base_size = 14) +
  theme(
    plot.title = element_text(face = "bold", hjust = 0.5),
    legend.position = "right"
  )

5. Phân tích cơ cấu Vốn chủ sở hữu

library(dplyr)
library(tidyr)
library(ggplot2)

# Lấy nhãn từ thuộc tính đã gán trước đó
labels <- attr(dataDBC, "variable_labels")

# Tính cơ cấu vốn chủ sở hữu
co_cau_von_chu_so_huu <- dataDBC %>%
  mutate(
    tong_von_csh = von_gop_cua_chu_so_huu +
      thang_du_von_co_phan +
      quy_dau_tu_phat_trien +
      loi_nhuan_sau_thue_chua_phan_phoi
  ) %>%
  select(date, von_gop_cua_chu_so_huu, thang_du_von_co_phan,
         quy_dau_tu_phat_trien, loi_nhuan_sau_thue_chua_phan_phoi, tong_von_csh) %>%
  pivot_longer(
    cols = -c(date, tong_von_csh),
    names_to = "khoan_muc",
    values_to = "gia_tri"
  ) %>%
  mutate(
    ty_trong = gia_tri / tong_von_csh * 100,
    khoan_muc = labels[khoan_muc]
  )

# Vẽ biểu đồ cơ cấu vốn chủ sở hữu
ggplot(co_cau_von_chu_so_huu, aes(x = date, y = ty_trong, fill = khoan_muc)) +
  geom_bar(stat = "identity") +
  scale_fill_brewer(palette = "Pastel1") +
  labs(
    title = "Cơ cấu vốn chủ sở hữu qua các năm",
    x = "Năm", y = "Tỷ trọng (%)",
    fill = "Khoản mục"
  ) +
  theme_minimal(base_size = 14) +
  theme(
    plot.title = element_text(face = "bold", hjust = 0.5),
    legend.position = "right"
  )

6. Tính hệ số nợ trên vốn chủ sở hữu(D/E)

\[ D/E = \frac{\text{Tổng nợ phải trả}}{\text{Vốn chủ sở hữu}} \]

dataDBC <- dataDBC %>%
mutate(he_so_no_tren_von_csh = no_phai_tra / von_chu_so_huu)

ggplot(dataDBC, aes(x = date, y = he_so_no_tren_von_csh)) +
geom_line(color = "steelblue", linewidth = 1.2) +
geom_point(color = "darkred", size = 3) +
geom_text(aes(label = round(he_so_no_tren_von_csh, 2)),
vjust = -1, size = 3.5, color = "black") +
labs(
title = "Hệ số nợ trên vốn chủ sở hữu (D/E) qua các năm",
x = "Năm",
y = "Hệ số D/E"
) +
ylim(0.5, 2.25) +
theme_minimal(base_size = 13) +
theme(
plot.title = element_text(face = "bold", hjust = 0.5),
axis.title = element_text(face = "bold")
)

Đánh giá: 2017–2019: Doanh nghiệp sử dụng đòn bẩy tài chính cao, tiềm ẩn rủi ro. 2020–2021: Cải thiện rõ rệt, D/E giảm xuống mức an toàn (~1.3). 2024: Mức D/E chỉ còn 1.09, thể hiện cơ cấu vốn ổn định và lành mạnh hơn. → Sau giai đoạn biến động, doanh nghiệp đang giảm dần phụ thuộc vào nợ, tăng khả năng tự chủ tài chính.

7. Phân tích tốc độ tăng trưởng LNST chưa phân phối

\[ Tốc~độ~tăng~trưởng~(\%) = \frac{X_t - X_{t-1}}{X_{t-1}} \times 100 \]

library(dplyr)
library(reshape2)
## 
## Attaching package: 'reshape2'
## The following object is masked from 'package:tidyr':
## 
##     smiths
library(ggplot2)

# --- 1. Tính tốc độ tăng trưởng ---
tang_truong_vcsh <- dataDBC %>%
  arrange(date) %>%
  mutate(
    tang_truong_von_csh = ((von_chu_so_huu - lag(von_chu_so_huu)) / lag(von_chu_so_huu)) * 100,
    tang_truong_ln_chua_pp = ((loi_nhuan_sau_thue_chua_phan_phoi - lag(loi_nhuan_sau_thue_chua_phan_phoi)) / lag(loi_nhuan_sau_thue_chua_phan_phoi)) * 100
  ) %>%
  select(date, starts_with("tang_truong"))

print(tang_truong_vcsh)
## # A tibble: 10 × 3
##     date tang_truong_von_csh tang_truong_ln_chua_pp
##    <dbl>               <dbl>                  <dbl>
##  1  2015              NA                      NA   
##  2  2016              20.2                    87.3 
##  3  2017               6.99                  -52.2 
##  4  2018               9.75                   81.5 
##  5  2019              10.2                    -3.35
##  6  2020              39.0                   257.  
##  7  2021              11.4                   -52.1 
##  8  2022              -0.954                 -98.6 
##  9  2023               0.539                 245.  
## 10  2024              45.0                  2666.
# --- 2. Chuyển đổi định dạng năm ---
tang_truong_vcsh$date <- as.integer(tang_truong_vcsh$date)  # Đảm bảo là số nguyên


# --- 2. Lấy nhãn tiếng Việt ngắn gọn cho các biến ---
labels_vcsh <- c(
  tang_truong_von_csh = "Vốn chủ sở hữu",
  tang_truong_ln_chua_pp = "LNST chưa phân phối"
)

# --- 3. Chuyển dữ liệu sang dạng dài ---
tang_truong_long <- melt(tang_truong_vcsh, id.vars = "date",
                         variable.name = "Khoan_muc", value.name = "Tang_truong")

# --- 4. Vẽ biểu đồ ---
ggplot(tang_truong_long, aes(x = date, y = Tang_truong, color = Khoan_muc, group = Khoan_muc)) +
  geom_line(size = 1.2) +
  geom_point(size = 2.5) +
  scale_color_manual(
    values = c("steelblue", "orange"),
    labels = labels_vcsh
  ) +
  labs(
    title = "Tốc độ tăng trưởng (%) các khoản mục trong Vốn chủ sở hữu",
    x = "Năm",
    y = "Tốc độ tăng trưởng (%)",
    color = "Khoản mục"
  ) +
  theme_minimal(base_size = 13) +
  theme(plot.title = element_text(face = "bold", hjust = 0.5))+
  scale_x_continuous(breaks = unique(tang_truong_long$date))
## Warning: Removed 2 rows containing missing values or values outside the scale range
## (`geom_line()`).
## Warning: Removed 2 rows containing missing values or values outside the scale range
## (`geom_point()`).