Mục lục

CHƯƠNG 1: PHÂN TÍCH BỘ DỮ LIỆU LOAN_DEFAULT

Giới thiệu về bộ dữ liệu Loan

Giới thiệu dữ liệu

Bộ dữ liệu Loan Default Prediction Dataset được cung cấp trên nền tảng Kaggle với mục tiêu hỗ trợ phân tích và dự đoán khả năng khách hàng vỡ nợ khoản vay (loan default) dựa trên các thông tin nhân khẩu học và đặc điểm của khoản vay. Đây là một bộ dữ liệu mô phỏng thực tế trong lĩnh vực tín dụng tiêu dùng, nơi các tổ chức tài chính cần đánh giá rủi ro trước khi đưa ra quyết định cho vay. Bộ dữ liệu có 255.347 quan sát và 18 biến, bao gồm nhiều nhóm thông tin như: đặc điểm cá nhân (tuổi, thu nhập, nghề nghiệp), lịch sử tín dụng (credit score, số lần trễ hạn), thông tin khoản vay (số tiền vay, thời hạn vay, mục đích vay), và biến kết quả (default: có vỡ nợ hay không).

Tên bộ dữ liệu: Loan Default Prediction Dataset

Nguồn dữ liệu: Nền tảng Kaggle

Số lượng quan sát: 255.347

số biến: 18

Dạng dữ liệu: Định tính và định lượng

Đọc dữ liệu

df <- read_csv("Loan_default.csv")

Kỹ thuật:

1. Đọc file Loan_default.csv và lưu dữ liệu vào biến df.

Ý nghĩa: câu lệnh này giúp nạp dữ liệu gốc để bắt đầu các bước xử lý, thống kê và phân tích tiếp theo.

Kiểm tra cấu trúc dữ liệu

str(df)

Kỹ thuật:

1. Hàm str() hiển thị cấu trúc tổng quát của đối tượng df, gồm tên cột, kiểu dữ liệu và vài giá trị đầu tiên của mỗi cột.

Ý nghĩa: Giúp nhanh chóng nắm được dạng dữ liệu và xác định cần chỉnh sửa, chuyển kiểu hay xử lý cột nào trước khi phân tích.

Xem 6 dòng dữ liệu đầu tiên

head(df)

Kỹ thuật:

1. Hàm head() hiển thị mặc định 6 dòng đầu tiên của bảng dữ liệu df.

Ý nghĩa: Giúp quan sát sơ bộ nội dung dữ liệu, nhận biết cách sắp xếp và định dạng các cột trước khi tiến hành phân tích chi tiết.

Xem 6 dòng dữ liệu cuối

tail(df)

Kỹ thuật:

1. Hàm tail() hiển thị mặc định 6 dòng cuối cùng của bảng dữ liệu df.

Ý nghĩa: Giúp kiểm tra phần cuối của dữ liệu, phát hiện các giá trị trống, lỗi nhập hoặc định dạng bất thường trước khi xử lý.

Kiểm tra kích thước của bộ dữ liệu

dim(df)
## [1] 255347     18

Kỹ thuật:

1. Hàm dim() trả về số hàng và số cột của bảng dữ liệu df.

Ý nghĩa: Bộ dữ liệu có 255347 quan sát và 18 biến.

Kiểm tra toàn bộ giá trị bị thiếu

colSums(is.na(df))
##         LoanID            Age         Income     LoanAmount 
##              0              0              0              0 
##    CreditScore MonthsEmployed NumCreditLines   InterestRate 
##              0              0              0              0 
##       LoanTerm       DTIRatio      Education EmploymentType 
##              0              0              0              0 
##  MaritalStatus    HasMortgage  HasDependents    LoanPurpose 
##              0              0              0              0 
##    HasCoSigner        Default 
##              0              0

Kỹ thuật:

1. Kết hợp is.na() để xác định giá trị bị thiếu trong từng ô và colSums() để tính tổng số giá trị thiếu theo từng cột.

Ý nghĩa: Không có giá trị bị thiếu.

Kiểm tra giá trị trùng lặp

duplicates <- sum(duplicated(df))
cat("\nSố bản ghi trùng lặp:", duplicates, "\n")
## 
## Số bản ghi trùng lặp: 0

Kỹ thuật:

1. Tạo biến duplicates để lưu tổng số bản ghi trùng lặp trong df bằng cách dùng hàm sum(duplicated(df)).

2. In ra màn hình dòng thông báo: “Số bản ghi trùng lặp:” kèm theo giá trị của biến duplicates.

Ý nghĩa: Không có giá trị nào bị trùng lặp.

Xem tên các cột (biến)

names(df)
##  [1] "LoanID"         "Age"            "Income"        
##  [4] "LoanAmount"     "CreditScore"    "MonthsEmployed"
##  [7] "NumCreditLines" "InterestRate"   "LoanTerm"      
## [10] "DTIRatio"       "Education"      "EmploymentType"
## [13] "MaritalStatus"  "HasMortgage"    "HasDependents" 
## [16] "LoanPurpose"    "HasCoSigner"    "Default"

Kỹ thuật:

1. Hàm names() liệt kê toàn bộ tên cột (biến) trong bảng dữ liệu df.

Ý nghĩa: Bộ dữ liệu có các biến sau: LoanID, Age, Income, LoanAmount, CreditScore, MonthsEmployed, NumCreditLines, InterestRate, LoanTerm, DTIRatio, Education, EmploymentType, MaritalStatus, HasMortgage, HasDependents, LoanPurpose, HasCoSigner, Default.

Đếm số lượng biến định lượng

numeric_count <- sum(sapply(df, is.numeric))
cat("Số lượng biến định lượng:", numeric_count, "\n\n")
## Số lượng biến định lượng: 10

Kỹ thuật:

1. Tính tổng số biến định lượng (numeric) trong bảng df bằng sum(sapply(df, is.numeric)) và lưu vào biến numeric_count.

2. In ra màn hình dòng chữ “Số lượng biến định lượng:” kèm giá trị của numeric_count.

Ý nghĩa: Bộ dữ liệu có 10 biến định lượng

Liệt kê các biến định lượng

numeric_vars <- names(df)[sapply(df, is.numeric)]
cat("Danh sách biến định lượng:\n")
print(numeric_vars)
## Danh sách biến định lượng:
##  [1] "Age"            "Income"         "LoanAmount"    
##  [4] "CreditScore"    "MonthsEmployed" "NumCreditLines"
##  [7] "InterestRate"   "LoanTerm"       "DTIRatio"      
## [10] "Default"

Kỹ thuật:

1. Lọc và lưu tên các biến định lượng trong bảng df vào biến numeric_vars.

2. In dòng tiêu đề “Danh sách biến định lượng:”.

3. Hiển thị danh sách các biến định lượng bằng print(numeric_vars).

Ý nghĩa: Bộ dữ liệu có các biến định lượng sau: Age, Income, LoanAmount, CreditScore, MonthsEmployed, NumCreditLines, InterestRate, LoanTerm, DTIRatio, Default

Đếm số lượng biến định tính

categorical_count <- sum(sapply(df, is.character))
cat("Số lượng biến định tính:", categorical_count, "\n\n")
## Số lượng biến định tính: 8

Kỹ thuật:

1. Tính số lượng biến định tính trong bảng df bằng sum(sapply(df, is.character)) và lưu vào biến categorical_count.

2. In ra màn hình dòng chữ “Số lượng biến định tính:” kèm giá trị của categorical_count.

Ý nghĩa: Bộ dữ liệu có 8 biến định tính

Liệt kê tên biến định tính

categorical_vars <- names(df)[sapply(df, is.character)]
cat("Danh sách biến định tính:\n")
print(categorical_vars)
## Danh sách biến định tính:
## [1] "LoanID"         "Education"      "EmploymentType"
## [4] "MaritalStatus"  "HasMortgage"    "HasDependents" 
## [7] "LoanPurpose"    "HasCoSigner"

Kỹ thuật:

1. Lọc và lưu tên các biến định tính trong bảng df vào biến categorical_vars.

2. In dòng tiêu đề “Danh sách biến định tính:”.

3. Hiển thị danh sách các biến định tính bằng print(categorical_vars).

Ý nghĩa: Bộ dữ liệu có các biến định tính: LoanID, Education, EmploymentType, MaritalStatus, HasMortgage, HasDependents, LoanPurpose, HasCoSigner

Ý nghĩa các biến

variable_description <- data.frame(
  Variable = c("LoanID", "Age", "Income", "LoanAmount", "CreditScore",
               "MonthsEmployed", "NumCreditLines", "InterestRate", "LoanTerm", "DTIRatio",
               "Education", "EmploymentType", "MaritalStatus", "HasMortgage",
               "HasDependents", "LoanPurpose", "HasCoSigner", "Default"),
  Description = c("Mã khoản vay",
                  "Tuổi khách hàng",
                  "Thu nhập hàng năm",
                  "Số tiền vay",
                  "Điểm tín dụng",
                  "Số tháng đã làm việc",
                  "Số lượng dòng tín dụng hiện tại/trước đây",
                  "Lãi suất vay (%)",
                  "Thời hạn vay",
                  "Tỷ lệ nợ trên thu nhập",
                  "Trình độ học vấn",
                  "Loại hình công việc",
                  "Tình trạng hôn nhân",
                  "Có vay thế chấp hay không",
                  "Có người phụ thuộc hay không",
                  "Mục đích vay",
                  "Có người đồng ký vay hay không",
                  "Khả năng vỡ nợ ")
)

variable_description

|Variable |Description ||:————–|:—————————————–||LoanID |Mã khoản vay ||Age |Tuổi khách hàng ||Income |Thu nhập hàng năm ||LoanAmount |Số tiền vay ||CreditScore |Điểm tín dụng ||MonthsEmployed |Số tháng đã làm việc ||NumCreditLines |Số lượng dòng tín dụng hiện tại/trước đây ||InterestRate |Lãi suất vay (%) ||LoanTerm |Thời hạn vay ||DTIRatio |Tỷ lệ nợ trên thu nhập ||Education |Trình độ học vấn ||EmploymentType |Loại hình công việc ||MaritalStatus |Tình trạng hôn nhân ||HasMortgage |Có vay thế chấp hay không ||HasDependents |Có người phụ thuộc hay không ||LoanPurpose |Mục đích vay ||HasCoSigner |Có người đồng ký vay hay không ||Default |Khả năng vỡ nợ |

Kỹ thuật:

1. Tạo bảng mô tả biến tên variable_description bằng hàm data.frame(), gồm hai cột:

Variable: chứa tên các biến trong tập dữ liệu df.

Description: chứa phần mô tả ý nghĩa tương ứng của từng biến.

26. Bảng này giúp hiểu rõ nội dung và vai trò của từng biến trong bộ dữ liệu.

Ý nghĩa: nêu lên nội dung của từng biến

Xử lý dữ liệu thô, mã hóa dữ liệu

Loại bỏ biến không liên quan

df_clean <- df %>% 
  select(-LoanID)

Kỹ thuật:

1. Tạo bảng dữ liệu mới tên df_clean từ df bằng toán tử pipe (%>%).

2. Loại bỏ cột LoanID khỏi bảng dữ liệu bằng hàm select(-LoanID).

Ý nghĩa: Biến LoanID chỉ là mã định danh duy nhất cho từng khoản vay, không mang thông tin phân tích định lượng hay định tính, nên được loại bỏ để tránh ảnh hưởng đến các phép thống kê và mô hình hóa.

Tổ hợp nhóm biến Age

df_clean <- df_clean %>%
  mutate(Age_Group = cut(Age,
                         breaks = c(18, 30, 45, 60, Inf),
                         labels = c("18-30", "31-45", "46-60", "61+"),
                         right = TRUE, include.lowest = TRUE))

Kỹ thuật:

1. Tạo biến mới Age_Group trong bảng df_clean bằng hàm mutate().

2. Dùng cut() để chia biến Age thành các nhóm tuổi: Khoảng: 18–30, 31–45, 46–60, và 61+. Gán nhãn tương ứng cho từng nhóm bằng labels.

Ý nghĩa: Tạo ra biến phân loại Age_Group giúp dễ dàng so sánh, mô tả và trực quan hóa dữ liệu theo độ tuổi — ví dụ phân tích tỷ lệ vỡ nợ hay thu nhập trung bình giữa các nhóm tuổi.

Chuẩn hóa dữ liệu văn bản

df_clean <- df_clean %>%
  mutate(across(where(is.character), str_to_lower)) %>%
  mutate(across(where(is.character), str_trim))

Kỹ thuật:

1. Áp dụng xử lý cho các cột kiểu ký tự (text) trong bảng df_clean trước khi chuyển sang factor.

2. Dùng mutate(across(where(is.character), str_to_lower)) để chuyển toàn bộ chữ trong các cột ký tự thành chữ thường.

3. Dùng mutate(across(where(is.character), str_trim)) để xóa khoảng trắng thừa ở đầu và cuối chuỗi trong các cột ký tự.

Ý nghĩa: Bước này giúp chuẩn hóa dữ liệu định tính để tránh lỗi khi phân tích, ví dụ “Male”, “male” và “MALE” sẽ được coi là một giá trị duy nhất, đảm bảo kết quả nhóm hoặc thống kê chính xác hơn.

Xử lý ngoại lệ của biến thu nhập

p99_income <- quantile(df_clean$Income, 0.99, na.rm = TRUE)
df_clean <- df_clean %>%
  mutate(Income = ifelse(Income > p99_income, p99_income, Income))

Kỹ thuật:

1. Tính phân vị 99% của Income bằng quantile(), bỏ qua giá trị NA và lưu vào p99_income.

2. Dùng pipe (%>%) để truyền dữ liệu từ df_clean sang mutate().

3. Dùng ifelse() trong mutate() để thay các giá trị Income lớn hơn p99_income bằng chính p99_income, giữ nguyên các giá trị còn lại.

Ý nghĩa: Bước này giúp giảm ảnh hưởng của các giá trị ngoại lệ quá lớn (outliers) trong biến thu nhập. Việc cắt ngưỡng ở P99 giúp dữ liệu ổn định hơn, tránh làm sai lệch trung bình hoặc mô hình phân tích thống kê và hồi quy.

Biến đổi Logarithm (Log Transform) xử lý độ lệch

df_clean <- df_clean %>%
  mutate(
    Income_log = log1p(Income), # log1p(x) = log(x + 1)
    LoanAmount_log = log1p(LoanAmount)
  )

Kỹ thuật:

1. Dùng pipe (%>%) để truyền dữ liệu từ df_clean sang mutate().

2. Dùng mutate() để tạo hai biến mới: Income_log và LoanAmount_log.

Ý nghĩa: Chuyển đổi log giúp giảm độ lệch phân phối (skewness) và làm mượt dữ liệu, giúp các biến có thang đo rộng trở nên gần chuẩn hơn — điều này rất quan trọng khi thực hiện phân tích hồi quy hoặc mô hình dự báo.

Tạo biến Tỷ lệ (Ratio Feature) - Payment_per_Term

df_clean <- df_clean %>%
  mutate(Payment_per_Term = LoanAmount / LoanTerm)

Kỹ thuật:

1. Dùng pipe (%>%) để truyền dữ liệu từ df_clean sang mutate().

2. Dùng mutate() để tạo biến mới Payment_per_Term.

Ý nghĩa: Tạo biến số tiền phải trả trung bình mỗi kỳ giúp đánh giá khả năng thanh toán của khách hàng và so sánh giữa các nhóm vay khác nhau. Chỉ số này cũng thường được dùng làm biến dự báo trong mô hình rủi ro tín dụng hoặc phân tích hành vi trả nợ.

Tổ hợp nhóm biến CreditScore

df_clean <- df_clean %>%
  mutate(Credit_Score_Band = cut(CreditScore,
                         breaks = c(300, 580, 670, 740, 800, Inf),
                         labels = c("Poor", "Fair", "Good", "Very Good", "Excellent"),
                         right = FALSE, include.lowest = TRUE))

Kỹ thuật:

1. Dùng pipe (%>%) để truyền dữ liệu từ df_clean sang mutate().

2. Dùng mutate() để tạo biến mới Credit_Score_Band từ biến CreditScore. Hàm cut() chia CreditScore thành các khoảng: 300–579, 580–669, 670–739, 740–799 và ≥800.

Ý nghĩa: Tạo ra biến Credit_Score_Band giúp phân loại khách hàng theo mức độ tín nhiệm tín dụng – từ “Poor” đến “Excellent”. Điều này hỗ trợ so sánh rủi ro giữa các nhóm khách hàng, phân tích khả năng vỡ nợ, và xây dựng chiến lược lãi suất hoặc phê duyệt tín dụng phù hợp.

Tạo cờ nhị phân biến Is_Unemployed

df_clean <- df_clean %>%
  mutate(Is_Unemployed = ifelse(EmploymentType == "unemployed", 1, 0))

Kỹ thuật:

1. Dùng pipe (%>%) để truyền dữ liệu từ df_clean sang mutate().

2. Dùng mutate() để tạo biến mới Is_Unemployed. Hàm ifelse() gán giá trị 1 nếu EmploymentType == “unemployed”, ngược lại gán 0.

Ý nghĩa: Biến Is_Unemployed là biến nhị phân (dummy variable) biểu thị trạng thái việc làm của khách hàng. Giá trị 1 cho thấy người vay thất nghiệp, 0 là có việc làm, giúp phân tích mức độ ảnh hưởng của thất nghiệp đến rủi ro vỡ nợ hoặc khả năng trả nợ.

Tạo cờ nhị phân biến Has_Dependents

df_clean <- df_clean %>%
  mutate(Has_Dependents_Bin = ifelse(HasDependents == "yes", 1, 0))

Kỹ thuật:

1. Dùng pipe (%>%) để truyền dữ liệu từ df_clean sang mutate().

2. Dùng mutate() để tạo biến mới Has_Dependents_Bin. Hàm ifelse() gán giá trị 1 nếu HasDependents == “yes”, ngược lại gán 0.

Ý nghĩa: Tạo biến Has_Dependents_Bin dạng nhị phân (0–1) để thể hiện trách nhiệm gia đình của người vay. Giá trị này giúp phân tích xem việc có người phụ thuộc (con cái, người thân…) có làm tăng rủi ro vỡ nợ hay ảnh hưởng đến khả năng trả nợ hay không.

Chuẩn hóa các biến số

df_clean <- df_clean %>%
  mutate(across(c(Age, Income_log, LoanAmount_log, CreditScore, 
                  MonthsEmployed, InterestRate, DTIRatio),
                scale))

Kỹ thuật:

1. Dùng pipe (%>%) để truyền dữ liệu từ df_clean sang mutate().

2. Dùng mutate(across()) để áp dụng hàm scale() cho nhiều biến cùng lúc. Các biến được chuẩn hóa gồm: Age, Income_log, LoanAmount_log, CreditScore, MonthsEmployed, InterestRate, và DTIRatio.

Ý nghĩa: Chuẩn hóa giúp đưa các biến về cùng thang đo, tránh trường hợp biến có đơn vị lớn (như thu nhập) lấn át biến nhỏ (như lãi suất) trong mô hình hồi quy hoặc phân tích đa biến, đảm bảo so sánh công bằng và ổn định hơn trong tính toán.

Chuyển đổi hàng loạt sang Factor

# Xác định các cột phân loại (bao gồm cả các cột mới tạo)
categorical_cols <- c("Education", "EmploymentType", "MaritalStatus", 
                      "LoanPurpose", "HasMortgage", "HasCoSigner", 
                      "Age_Group", "Credit_Score_Band")

df_clean <- df_clean %>%
  mutate(across(all_of(categorical_cols), as.factor))

Kỹ thuật:

1. Tạo danh sách categorical_cols chứa tên các biến phân loại, bao gồm cả những biến mới được tạo như Age_Group và Credit_Score_Band.

6. Dùng pipe (%>%) để truyền dữ liệu từ df_clean sang mutate(). 7. Dùng mutate(across()) để áp dụng hàm as.factor() cho tất cả các biến trong categorical_cols.

Ý nghĩa: Việc chuyển các biến định tính sang factor giúp R nhận diện rõ đây là biến phân loại.

Mã hóa thứ bậc cho biến Education

education_levels <- c("high school" = 1, 
                      "bachelor's" = 2, 
                      "master's" = 3, 
                      "phd" = 4)

df_clean <- df_clean %>%
  mutate(Education_Ordinal = recode(Education, !!!education_levels, .default = 0))

Kỹ thuật:

1. Tạo vector education_levels để quy định thứ tự trình độ học vấn theo mức độ tăng dần: high school → bachelor’s → master’s → PhD.

6. Dùng pipe (%>%) để truyền dữ liệu từ df_clean sang mutate().

7. Dùng mutate() để tạo biến mới Education_Ordinal. Hàm recode() thay thế giá trị trong biến Education theo quy tắc trong education_levels.

Ý nghĩa: Biến Education_Ordinal là phiên bản mã hóa theo thứ bậc của trình độ học vấn — từ 1 (thấp nhất) đến 4 (cao nhất).

Thực hiện thống kê cơ bản

Xác định độ phân tán và xu hướng trung tâm của thu nhập sau khi xử lý Log(Income)

df_clean %>% 
  summarise(
    Mean_Log_Income = mean(Income_log), 
    SD_Log_Income = sd(Income_log), 
    Median_Log_Income = median(Income_log)
  )
Mean_Log_Income| SD_Log_Income| Median_Log_Income||—————:|————-:|—————–:|| 0| 1| 0.25|

Kỹ thuật:

1. Dùng pipe (%>%) để truyền dữ liệu từ df_clean sang summarise().

2. Dùng summarise() để tính các thống kê mô tả cho biến Income_log. Mean_Log_Income: tính giá trị trung bình bằng hàm mean(). SD_Log_Income: tính độ lệch chuẩn bằng hàm sd(). Median_Log_Income: tính trung vị bằng hàm median().

Ý nghĩa thống kê:

Giá trị trung bình (Mean_Log_Income ≈ 0) cho thấy dữ liệu đã được chuẩn hóa, có trung tâm xấp xỉ 0.

Độ lệch chuẩn (SD_Log_Income = 1) xác nhận rằng biến đã được chuẩn hóa theo z-score, nghĩa là mỗi giá trị thể hiện số độ lệch chuẩn so với trung bình.

Trung vị (Median_Log_Income = 0.2483) lớn hơn trung bình, cho thấy phân phối hơi lệch trái, tức là phần lớn giá trị nằm trên mức trung bình một chút.

Kiểm tra tỷ lệ của biến mục tiêu Default

df_clean %>% count(Default) %>% mutate(Rate = n / sum(n) * 100)
Default| n| Rate||——-:|——-:|—–:|| 0| 225.694| 88.39|| 1| 29.653| 11.61|

Kỹ thuật:

1. Đếm số lượng bản ghi theo biến Default bằng count(), sau đó dùng mutate() để tính tỷ lệ phần trăm (Rate) của từng nhóm bằng công thức n / sum(n) * 100.

Ý nghĩa thống kê: Kết quả cho thấy trong tổng số khách hàng được khảo sát, có 225,694 người (chiếm khoảng 88.39%) không rơi vào tình trạng vỡ nợ và 29,653 người (tương đương 11.61%) đã vỡ nợ. Điều này phản ánh rằng phần lớn khách hàng trong danh mục vay có khả năng trả nợ đúng hạn, thể hiện chất lượng tín dụng tương đối tốt của tổ chức cho vay. Tuy nhiên, tỷ lệ 11.61% khách hàng vỡ nợ vẫn là một con số đáng lưu ý, cho thấy cần có các biện pháp quản trị rủi ro tín dụng phù hợp, chẳng hạn như tăng cường thẩm định hồ sơ, theo dõi lịch sử tín dụng hoặc điều chỉnh chính sách lãi suất đối với nhóm khách hàng có nguy cơ cao.

Bảng tần suất và tỷ lệ trình độ học vấn

df_clean %>%
  count(Education) %>%
  mutate(Percentage = n / sum(n) * 100) %>%
  arrange(desc(n))

|Education | n| Percentage||:———–|——:|———-:||bachelor’s | 64.366| 25.21||high school | 63.903| 25.03||master’s | 63.541| 24.88||phd | 63.537| 24.88|

Kỹ thuật:

1. Dùng pipe (%>%) để truyền dữ liệu từ df_clean sang count().

2. Hàm count(Education) đếm số lượng bản ghi theo từng mức học vấn trong biến Education.

3. Dùng mutate() để tạo biến mới Percentage, tính tỷ lệ phần trăm của từng nhóm bằng công thức n / sum(n) * 100.

4. Dùng arrange(desc(n)) để sắp xếp kết quả giảm dần theo số lượng.

Ý nghĩa thống kê: Kết quả cho thấy sự phân bố trình độ học vấn của khách hàng trong tập dữ liệu khá đồng đều giữa các nhóm. Cụ thể, nhóm có bằng đại học (bachelor’s) chiếm tỷ lệ cao nhất với 25.21%, tiếp đến là nhóm trung học phổ thông (high school) chiếm 25.03%, trong khi nhóm thạc sĩ (master’s) và tiến sĩ (phd) chiếm tỷ lệ gần tương đương, lần lượt 24.88% và 24.88%. Điều này phản ánh rằng tệp khách hàng vay vốn có trình độ học vấn tương đối cao và cân bằng, cho thấy mức độ tiếp cận tài chính không phụ thuộc mạnh vào trình độ học vấn.

Bảng tần suất và tỷ lệ mục đích vay

# Gộp đếm và tỷ lệ cho biến LoanPurpose, sắp xếp theo số lượng
df_clean %>%
  count(LoanPurpose) %>%
  mutate(Percentage = n / sum(n) * 100) %>%
  arrange(desc(n))

|LoanPurpose | n| Percentage||:———–|——:|———-:||business | 51.298| 20.09||home | 51.286| 20.08||education | 51.005| 19.97||other | 50.914| 19.94||auto | 50.844| 19.91|

Kỹ thuật:

1. Dùng pipe (%>%) để truyền dữ liệu từ df_clean sang count().

2. Hàm count(LoanPurpose) đếm số lượng bản ghi theo từng mục đích vay trong biến LoanPurpose.

3. Dùng mutate() để tạo biến Percentage, tính tỷ lệ phần trăm mỗi nhóm bằng công thức n / sum(n) * 100.

4. Dùng arrange(desc(n)) để sắp xếp kết quả giảm dần theo số lượng bản ghi.

Ý nghĩa thống kê: Các nhóm mục đích vay có tỷ lệ gần tương đương nhau, trong đó vay kinh doanh và mua nhà chiếm cao nhất (khoảng 20%), cho thấy danh mục vay vốn khá đa dạng và cân bằng giữa các nhu cầu của khách hàng.

Bảng tần suất tỷ lệ tình trạng hôn nhân

df_clean %>%
  count(MaritalStatus) %>%
  mutate(Percentage = n / sum(n) * 100) %>%
  arrange(desc(n))

|MaritalStatus | n| Percentage||:————-|——:|———-:||married | 85.302| 33.41||divorced | 85.033| 33.30||single | 85.012| 33.29|

Kỹ thuật:

1. Dùng pipe (%>%) để truyền dữ liệu từ df_clean sang count().

2. Hàm count(MaritalStatus) đếm số lượng bản ghi theo từng tình trạng hôn nhân trong biến MaritalStatus.

3. Dùng mutate() để tạo biến Percentage, tính tỷ lệ phần trăm từng nhóm bằng công thức n / sum(n) * 100.

4. Dùng arrange(desc(n)) để sắp xếp kết quả giảm dần theo số lượng bản ghi.

Ý nghĩa thống kê: Ba nhóm đã kết hôn, ly hôn và độc thân có tỷ lệ gần như ngang nhau, mỗi nhóm chiếm khoảng 33% tổng số khách hàng. Điều này cho thấy mẫu dữ liệu cân bằng, không có sự chênh lệch lớn giữa các nhóm hôn nhân.

Bảng tần suất tỷ lệ loại hình công việc

df_clean %>%
  count(EmploymentType) %>%
  mutate(Percentage = n / sum(n) * 100) %>%
  arrange(desc(n))

|EmploymentType | n| Percentage||:————–|——:|———-:||part-time | 64.161| 25.13||unemployed | 63.824| 25.00||self-employed | 63.706| 24.95||full-time | 63.656| 24.93|

Kỹ thuật:

1. Dùng pipe (%>%) để truyền dữ liệu từ df_clean sang count().

2. Hàm count(EmploymentType) đếm số lượng bản ghi theo từng loại hình công việc trong biến EmploymentType.

3. Dùng mutate() để tạo biến Percentage, tính tỷ lệ phần trăm của từng nhóm bằng công thức n / sum(n) * 100.

4. Dùng arrange(desc(n)) để sắp xếp kết quả giảm dần theo số lượng bản ghi.

Ý nghĩa thống kê: Kết quả cho thấy bốn nhóm việc làm có tỷ lệ gần như ngang nhau, trong đó lao động bán thời gian (part-time) chiếm cao nhất với 25.13%, tiếp theo là thất nghiệp (unemployed) chiếm 24.99%, tự kinh doanh (self-employed) chiếm 24.95%, và toàn thời gian (full-time) chiếm 24.93%.

Bảng so sánh thu nhập trung bình theo vỡ nợ

df %>%
  group_by(Default) %>%
  summarise(Mean_Income = mean(Income, na.rm = TRUE))
Default| Mean_Income||——-:|———–:|| 0| 83.899.17|| 1| 71.844.72|

Kỹ thuật:

1. Dùng pipe (%>%) để truyền dữ liệu từ df sang group_by().

2. Hàm group_by(Default) nhóm dữ liệu theo biến Default (0: không vỡ nợ, 1: có vỡ nợ).

3. Dùng summarise() để tính thu nhập trung bình (Mean_Income) cho từng nhóm, đồng thời bỏ qua các giá trị NA với tham số na.rm = TRUE.

Ý nghĩa thống kê: Kết quả cho thấy nhóm không vỡ nợ có thu nhập trung bình 83,899.17, cao hơn đáng kể so với nhóm vỡ nợ, chỉ 71,844.72. Điều này gợi ý rằng thu nhập có thể là yếu tố quan trọng ảnh hưởng đến khả năng trả nợ, khi khách hàng có thu nhập cao hơn thường có rủi ro vỡ nợ thấp hơn.

Bảng so sánh điểm tín dụng trung vị theo vỡ nợ

df %>%
  group_by(Default) %>%
  summarise(Median_CreditScore = median(CreditScore, na.rm = TRUE))
Default| Median_CreditScore||——-:|——————:|| 0| 577|| 1| 553|

Kỹ thuật:

1. Dùng pipe (%>%) để truyền dữ liệu từ df sang group_by().

2. Hàm group_by(Default) nhóm dữ liệu theo biến Default (0: không vỡ nợ, 1: có vỡ nợ).

3. Dùng summarise() để tính điểm tín dụng trung vị (Median_CreditScore) cho từng nhóm, đồng thời bỏ qua các giá trị NA với tham số na.rm = TRUE.

Ý nghĩa thống kê: Kết quả cho thấy nhóm không vỡ nợ có điểm tín dụng trung vị là 577, cao hơn nhóm vỡ nợ với 553. Điều này chứng tỏ rằng khách hàng có điểm tín dụng cao hơn thường có khả năng trả nợ tốt hơn, và điểm tín dụng là chỉ báo đáng tin cậy cho rủi ro vỡ nợ trong danh mục khách hàng.

Bảng so sánh lãi suất trung bình theo vỡ nợ

df %>%
  group_by(Default) %>%
  summarise(Mean_InterestRate = mean(InterestRate, na.rm = TRUE))
Default| Mean_InterestRate||——-:|—————–:|| 0| 13.18|| 1| 15.90|

Kỹ thuật:

1. Dùng pipe (%>%) để truyền dữ liệu từ df sang group_by().

2. Hàm group_by(Default) nhóm dữ liệu theo biến Default (0: không vỡ nợ, 1: có vỡ nợ).

3. Dùng summarise() để tính lãi suất trung bình (Mean_InterestRate) cho từng nhóm, đồng thời bỏ qua các giá trị thiếu (NA) bằng tham số na.rm = TRUE.

Ý nghĩa thống kê: Kết quả cho thấy nhóm vỡ nợ (1) có lãi suất trung bình là 15.90%, cao hơn so với nhóm không vỡ nợ (0) là 13.18%. Điều này phản ánh rằng những khách hàng phải chịu mức lãi suất cao hơn thường có nguy cơ vỡ nợ lớn hơn.

Bảng so sánh DTIRatio trung bình theo vỡ nợ

df %>%
  group_by(Default) %>%
  summarise(Mean_DTIRatio = mean(DTIRatio, na.rm = TRUE))
Default| Mean_DTIRatio||——-:|————-:|| 0| 0.50|| 1| 0.51| Kỹ thuật:

1. Dùng pipe (%>%) để truyền dữ liệu từ df sang group_by().

2. Hàm group_by(Default) nhóm dữ liệu theo biến Default (0: không vỡ nợ, 1: có vỡ nợ).

3. Dùng summarise() để tính tỷ lệ nợ trên thu nhập trung bình (Mean_DTIRatio) cho từng nhóm, đồng thời bỏ qua các giá trị thiếu (NA) bằng tham số na.rm = TRUE.

Ý nghĩa thống kê: Kết quả cho thấy nhóm vỡ nợ (1) có tỷ lệ nợ/thu nhập trung bình là 0.512, cao hơn nhóm không vỡ nợ (0) với 0.499. Điều này cho thấy những khách hàng có gánh nặng nợ cao hơn so với thu nhập thường dễ rơi vào tình trạng vỡ nợ, đồng thời khẳng định DTI là một chỉ số quan trọng trong đánh giá khả năng trả nợ của người vay.

Bảng tỷ lệ vỡ nợ theo mục đích vay

df_clean %>%
  group_by(LoanPurpose) %>%
  summarise(
    Count = n(),
    Default_Rate = mean(Default, na.rm = TRUE) * 100
  ) %>%
  arrange(desc(Default_Rate))

|LoanPurpose | Count| Default_Rate||:———–|——:|————:||business | 51.298| 12.33||auto | 50.844| 11.88||education | 51.005| 11.84||other | 50.914| 11.79||home | 51.286| 10.23|

Kỹ thuật:

1. Dùng pipe (%>%) để truyền dữ liệu từ df_clean sang group_by().

2. Hàm group_by(LoanPurpose) nhóm dữ liệu theo từng mục đích vay.

3. Dùng summarise() để tính hai giá trị:

7. Count = n(): số lượng khoản vay trong từng nhóm.

Default_Rate = mean(Default, na.rm = TRUE) * 100: tỷ lệ vỡ nợ trung bình (theo phần trăm) của từng nhóm.

Dùng arrange(desc(Default_Rate)) để sắp xếp kết quả giảm dần theo tỷ lệ vỡ nợ.

Ý nghĩa thống kê: Kết quả cho thấy nhóm vay cho mục đích kinh doanh (business) có tỷ lệ vỡ nợ cao nhất 12.33%, tiếp theo là vay mua xe (auto) và vay học tập (education) với khoảng 11.8%, trong khi vay mua nhà (home) có tỷ lệ thấp nhất 10.23%. Điều này cho thấy các khoản vay phục vụ mục đích đầu tư hoặc tiêu dùng có mức rủi ro cao hơn, trong khi vay mua nhà thường được kiểm soát chặt chẽ hơn nên ít xảy ra vỡ nợ.

Bảng tỷ lệ vỡ nợ theo trình độ học vấn

df_clean %>%
  group_by(Education) %>%
  summarise(
    Count = n(),
    Default_Rate = mean(Default, na.rm = TRUE) * 100
  ) %>%
  arrange(desc(Default_Rate))

|Education | Count| Default_Rate||:———–|——:|————:||high school | 63.903| 12.88||bachelor’s | 64.366| 12.10||master’s | 63.541| 10.87||phd | 63.537| 10.59| Kỹ thuật:

1. Dùng pipe (%>%) để truyền dữ liệu từ df_clean sang group_by().

2. Hàm group_by(Education) nhóm dữ liệu theo từng trình độ học vấn.

3. Dùng summarise() để tính hai giá trị:

Count = n(): số lượng bản ghi trong từng nhóm học vấn.

Default_Rate = mean(Default, na.rm = TRUE) * 100: tỷ lệ vỡ nợ trung bình (tính theo phần trăm) của từng nhóm.

7. Dùng arrange(desc(Default_Rate)) để sắp xếp kết quả giảm dần theo tỷ lệ vỡ nợ.

Ý nghĩa thống kê: Kết quả thống kê cho thấy tỷ lệ vỡ nợ giảm dần khi trình độ học vấn tăng lên, từ 12.88% ở nhóm trung học phổ thông xuống còn 10.59% ở nhóm tiến sĩ. Điều này phản ánh mối quan hệ nghịch biến giữa học vấn và rủi ro tín dụng: người có trình độ cao hơn thường có khả năng quản lý tài chính tốt hơn, thu nhập ổn định hơn nên ít vỡ nợ hơn.

Bảng tỷ lệ vỡ nợ theo loại hình công việc

df_clean %>%
  group_by(EmploymentType) %>%
  summarise(
    Count = n(),
    Default_Rate = mean(Default, na.rm = TRUE) * 100
  ) %>%
  arrange(desc(Default_Rate))

|EmploymentType | Count| Default_Rate||:————–|——:|————:||unemployed | 63.824| 13.55||part-time | 64.161| 11.97||self-employed | 63.706| 11.46||full-time | 63.656| 9.46|

Kỹ thuật:

1. Dùng pipe (%>%) để truyền dữ liệu từ df_clean sang group_by().

2. Hàm group_by(EmploymentType) nhóm dữ liệu theo từng loại hình công việc.

3. Dùng summarise() để tính hai giá trị:

Count = n(): số lượng bản ghi trong từng nhóm.

Default_Rate = mean(Default, na.rm = TRUE) * 100: tỷ lệ vỡ nợ trung bình (tính theo phần trăm) của từng nhóm công việc.

7. Dùng arrange(desc(Default_Rate)) để sắp xếp kết quả giảm dần theo tỷ lệ vỡ nợ.

Ý nghĩa thống kê: Kết quả thống kê cho thấy tỷ lệ vỡ nợ giảm dần theo mức độ ổn định của công việc. Nhóm thất nghiệp có tỷ lệ cao nhất (13.55%), trong khi nhóm làm việc toàn thời gian thấp nhất (9.46%). Điều này phản ánh rằng người có việc làm ổn định thường có thu nhập và khả năng chi trả tốt hơn, giúp giảm rủi ro vỡ nợ. Ngược lại, thất nghiệp hoặc việc làm không ổn định làm tăng khả năng mất khả năng thanh toán.

Bảng tỷ lệ vỡ nợ theo tình trạng hôn nhân

df_clean %>%
  group_by(MaritalStatus) %>%
  summarise(
    Count = n(),
    Default_Rate = mean(Default, na.rm = TRUE) * 100
  ) %>%
  arrange(desc(Default_Rate))

|MaritalStatus | Count| Default_Rate||:————-|——:|————:||divorced | 85.033| 12.53||single | 85.012| 11.91||married | 85.302| 10.40|

Kỹ thuật:

1. Dùng pipe (%>%) để truyền dữ liệu từ df_clean sang group_by().

2. Hàm group_by(MaritalStatus) nhóm dữ liệu theo từng tình trạng hôn nhân.

3. Dùng summarise() để tính:

Count = n(): số lượng bản ghi trong từng nhóm.

Default_Rate = mean(Default, na.rm = TRUE) * 100: tỷ lệ vỡ nợ trung bình (tính theo phần trăm) của từng nhóm.

7. Dùng arrange(desc(Default_Rate)) để sắp xếp kết quả giảm dần theo tỷ lệ vỡ nợ.

Ý nghĩa thống kê: Kết quả cho thấy tỷ lệ vỡ nợ cao nhất thuộc nhóm đã ly hôn (12.53%), tiếp theo là nhóm độc thân (11.91%), và thấp nhất ở nhóm đã kết hôn (10.40%). Điều này cho thấy tình trạng hôn nhân ổn định có thể giúp giảm rủi ro tín dụng, có thể do người đã kết hôn thường có trách nhiệm tài chính và nguồn thu nhập ổn định hơn so với các nhóm còn lại.

Bảng tỷ lệ vỡ nợ theo nhóm tuổi

df_clean %>%
  group_by(Age_Group) %>%
  summarise(
    Count = n(),
    Default_Rate = mean(Default, na.rm = TRUE) * 100
  ) %>%
  arrange(desc(Default_Rate))

|Age_Group | Count| Default_Rate||:———|——:|————:||18-30 | 63.577| 19.39||31-45 | 74.067| 12.70||46-60 | 73.501| 7.74||61+ | 44.202| 5.05|

Kỹ thuật:

1. Dùng pipe (%>%) để truyền dữ liệu từ df_clean sang group_by().

2. Hàm group_by(Age_Group) nhóm dữ liệu theo từng nhóm tuổi (biến được tạo trước đó bằng cut()).

3. Dùng summarise() để tính:

Count = n(): số lượng bản ghi trong mỗi nhóm tuổi.

Default_Rate = mean(Default, na.rm = TRUE) * 100: tỷ lệ vỡ nợ trung bình (theo phần trăm) của từng nhóm tuổi.

7. Dùng arrange(desc(Default_Rate)) để sắp xếp kết quả giảm dần theo tỷ lệ vỡ nợ.

Ý nghĩa thống kê: Kết quả cho thấy nhóm tuổi trẻ (18–30) có tỷ lệ vỡ nợ cao nhất (19.39%), trong khi nhóm từ 61 tuổi trở lên thấp nhất (5.05%). Xu hướng này cho thấy tuổi tác có mối quan hệ nghịch biến với rủi ro tín dụng: người trẻ thường có thu nhập và kinh nghiệm tài chính hạn chế, dẫn đến khả năng vỡ nợ cao hơn so với nhóm trung niên và cao tuổi có tài chính ổn định hơn.

Bảng tỷ lệ vỡ nợ theo nhóm điểm tín dụng

df_clean %>%
  group_by(Credit_Score_Band) %>%
  summarise(
    Count = n(),
    Default_Rate = mean(Default, na.rm = TRUE) * 100
  ) %>%
  arrange(Credit_Score_Band) 

|Credit_Score_Band | Count| Default_Rate||:—————–|——-:|————:||Poor | 130.223| 12.47||Fair | 41.847| 11.43||Good | 32.073| 10.63||Very Good | 27.736| 10.50||Excellent | 23.468| 9.81|

Kỹ thuật:

1. Dùng pipe (%>%) để truyền dữ liệu từ df_clean sang group_by().

2. Hàm group_by(Credit_Score_Band) nhóm dữ liệu theo nhóm điểm tín dụng (đã được tạo bằng cut() trước đó).

3. Dùng summarise() để tính:

Count = n(): số lượng bản ghi trong từng nhóm điểm.

Default_Rate = mean(Default, na.rm = TRUE) * 100: tỷ lệ vỡ nợ trung bình của từng nhóm (tính theo phần trăm).

7. arrange(Credit_Score_Band) sắp xếp kết quả theo thứ tự các nhóm điểm tín dụng từ thấp đến cao.

Ý nghĩa thống kê: Kết quả cho thấy tỷ lệ vỡ nợ giảm dần theo chất lượng điểm tín dụng, từ 12.47% ở nhóm Poor xuống còn 9.81% ở nhóm Excellent. Xu hướng này phản ánh rằng điểm tín dụng càng cao thì rủi ro vỡ nợ càng thấp, do người có lịch sử tín dụng tốt thường có khả năng quản lý tài chính hiệu quả và tuân thủ nghĩa vụ trả nợ tốt hơn.

Bảng ma trận tương quan giữa các biến số chính

numeric_vars <- df_clean %>%
  select(Income, LoanAmount, CreditScore, InterestRate, DTIRatio, MonthsEmployed, Age)
cor_matrix <- cor(numeric_vars, use = "complete.obs")
print(cor_matrix)
##                       Income    LoanAmount   CreditScore
## Income          1.0000000000 -0.0008653241 -0.0014279068
## LoanAmount     -0.0008653241  1.0000000000  0.0012612696
## CreditScore    -0.0014279068  0.0012612696  1.0000000000
## InterestRate   -0.0023032864 -0.0022911190  0.0004361387
## DTIRatio        0.0001963299  0.0011224209 -0.0010392521
## MonthsEmployed  0.0026780310  0.0028168363  0.0006128273
## Age            -0.0012421429 -0.0022127413 -0.0005481709
##                 InterestRate      DTIRatio MonthsEmployed
## Income         -2.303286e-03  0.0001963299   2.678031e-03
## LoanAmount     -2.291119e-03  0.0011224209   2.816836e-03
## CreditScore     4.361387e-04 -0.0010392521   6.128273e-04
## InterestRate    1.000000e+00  0.0005753188   9.557276e-05
## DTIRatio        5.753188e-04  1.0000000000   1.764627e-03
## MonthsEmployed  9.557276e-05  0.0017646268   1.000000e+00
## Age            -1.127383e-03 -0.0046891917  -3.413880e-04
##                          Age
## Income         -0.0012421429
## LoanAmount     -0.0022127413
## CreditScore    -0.0005481709
## InterestRate   -0.0011273828
## DTIRatio       -0.0046891917
## MonthsEmployed -0.0003413880
## Age             1.0000000000

Kỹ thuật:

1. Dùng pipe (%>%) để truyền dữ liệu từ df_clean sang select().

2. Hàm select() chọn ra các biến định lượng gồm Income, LoanAmount, CreditScore, InterestRate, DTIRatio, MonthsEmployed, và Age để phân tích mối quan hệ giữa chúng.

3. Dùng cor() để tính ma trận tương quan giữa các biến, với tham số use = “complete.obs” nhằm loại bỏ các hàng có giá trị thiếu (NA).

4. print(cor_matrix) được dùng để hiển thị ma trận tương quan, giúp đánh giá mức độ và chiều hướng tương quan giữa các biến định lượng.

Ý nghĩa thống kê: Kết quả cho thấy các hệ số tương quan đều nhỏ (gần 0), thể hiện mối quan hệ tuyến tính giữa các biến là rất yếu hoặc gần như không đáng kể.

Bảng đếm chéo giữa trình độ học vấn và vỡ nợ

contingency_table_edu <- table(df_clean$Education, df_clean$Default)
print(contingency_table_edu)
##              
##                   0     1
##   bachelor's  56577  7789
##   high school 55673  8230
##   master's    56633  6908
##   phd         56811  6726

Kỹ thuật:

1. Dùng table() để tạo bảng chéo giữa Education và Default, thể hiện số lượng vỡ nợ theo từng trình độ học vấn. Gán kết quả vào contingency_table_edu 2. print() ra để xem phân bố.

Ý nghĩa thống kê: Bảng cho thấy số người vỡ nợ giảm dần theo trình độ học vấn: nhóm trung học phổ thông có 8,230 người vỡ nợ, cao hơn so với nhóm cử nhân (7,789), thạc sĩ (6,908) và tiến sĩ (6,726). Điều này củng cố nhận định rằng trình độ học vấn càng cao thì khả năng vỡ nợ càng thấp, có thể do nhóm này có thu nhập ổn định và khả năng quản lý tài chính tốt hơn.

Bảng thống kê chỉ số Income, CreditScore theo mục đích vay

df_clean %>%
  group_by(LoanPurpose) %>%
  summarise(
    Count = n(), # Đếm số lượng
    Mean_Income = mean(Income, na.rm = TRUE),
    Default_Rate = mean(Default, na.rm = TRUE) * 100
  ) %>%
  arrange(desc(Default_Rate))

|LoanPurpose | Count| Mean_Income| Default_Rate||:———–|——:|———–:|————:||business | 51.298| 82.890.65| 12.33||auto | 50.844| 82.501.80| 11.88||education | 51.005| 82.211.21| 11.84||other | 50.914| 82.462.52| 11.79||home | 51.286| 82.395.63| 10.23|

Kỹ thuật:

2. Nhóm dữ liệu theo LoanPurpose bằng group_by().

3. Tính Count (số bản ghi), Mean_Income (thu nhập trung bình) và Default_Rate (tỷ lệ vỡ nợ trung bình %).

8. arrange(desc(Default_Rate)) sắp xếp các mục đích vay theo tỷ lệ vỡ nợ giảm dần.

Ý nghĩa thống kê: Kết quả cho thấy các khoản vay phục vụ kinh doanh (business) có tỷ lệ vỡ nợ cao nhất (12.33%), trong khi vay mua nhà (home) có tỷ lệ thấp nhất (10.23%). Điều này cho thấy mục đích vay ảnh hưởng đến rủi ro tín dụng: vay kinh doanh thường tiềm ẩn rủi ro cao do biến động lợi nhuận và thị trường, còn vay mua nhà thường được bảo đảm bằng tài sản, giúp giảm khả năng vỡ nợ.

Bảng so sánh tài chính theo Credit_Score_Band

df_clean %>%
  group_by(Credit_Score_Band) %>%
  summarise(
    Count = n(),
    Mean_Income = mean(Income, na.rm = TRUE),
    Default_Rate = mean(Default, na.rm = TRUE) * 100
  ) %>%
  arrange(Credit_Score_Band)

|Credit_Score_Band | Count| Mean_Income| Default_Rate||:—————–|——-:|———–:|————:||Poor | 130.223| 82.599.77| 12.47||Fair | 41.847| 82.454.53| 11.43||Good | 32.073| 82.146.38| 10.63||Very Good | 27.736| 82.416.80| 10.50||Excellent | 23.468| 82.529.82| 9.81|

Kỹ thuật:

2. Nhóm dữ liệu theo Credit_Score_Band bằng group_by().

3. Dùng summarise() để tính:

Count: số lượng bản ghi.

Mean_Income: thu nhập trung bình.

Default_Rate: tỷ lệ vỡ nợ trung bình (%).

8. arrange(Credit_Score_Band) sắp xếp kết quả theo thứ tự nhóm điểm tín dụng.

Ý nghĩa thống kê: Kết quả cho thấy khi điểm tín dụng càng cao, tỷ lệ vỡ nợ càng giảm, từ 12.47% ở nhóm Poor xuống còn 9.81% ở nhóm Excellent. Thu nhập trung bình giữa các nhóm không chênh lệch đáng kể ( 82,416 - 82,599), cho thấy điểm tín dụng phản ánh chủ yếu thói quen và uy tín tín dụng hơn là thu nhập. Như vậy, nhóm có điểm tín dụng cao không chỉ ít vỡ nợ hơn mà còn thể hiện mức độ tín nhiệm tài chính tốt hơn.

Bảng tóm tắt thu nhập trung bình và số tiền vay trung bình theo nhóm tuổi

df_clean %>%
  group_by(Age_Group) %>%
  summarise(
    Count = n(),
    Mean_Income = mean(Income, na.rm = TRUE),
    Mean_LoanAmount = mean(LoanAmount, na.rm = TRUE)
  ) %>%
  arrange(Age_Group)

|Age_Group | Count| Mean_Income| Mean_LoanAmount||:———|——:|———–:|—————:||18-30 | 63.577| 82.695.57| 127.783.8||31-45 | 74.067| 82.301.43| 127.657.4||46-60 | 73.501| 82.337.25| 127.469.2||61+ | 44.202| 82.780.00| 127.334.8|

Kỹ thuật:

2. Nhóm dữ liệu theo Age_Group bằng group_by().

3. Dùng summarise() để tính:

Count: số lượng bản ghi.

Mean_Income: thu nhập trung bình.

Mean_LoanAmount: số tiền vay trung bình.

8. arrange(Age_Group) sắp xếp kết quả theo thứ tự nhóm tuổi.

Ý nghĩa thống kê: Kết quả cho thấy các nhóm tuổi có thu nhập trung bình và khoản vay khá tương đồng ( 82,301 - 82,780), nhưng nhóm từ 61 tuổi trở lên có thu nhập cao nhất (82,780).

Thống kê mô tả các biến độc lập CreditScore, Income, LoanAmount, LoanTerm

summary(df[, c("CreditScore", "Income", "LoanAmount")])
##   CreditScore        Income         LoanAmount    
##  Min.   :300.0   Min.   : 15000   Min.   :  5000  
##  1st Qu.:437.0   1st Qu.: 48826   1st Qu.: 66156  
##  Median :574.0   Median : 82466   Median :127556  
##  Mean   :574.3   Mean   : 82499   Mean   :127579  
##  3rd Qu.:712.0   3rd Qu.:116219   3rd Qu.:188985  
##  Max.   :849.0   Max.   :149999   Max.   :249999

Kỹ thuật:

1. Hàm summary() được dùng để thống kê mô tả nhanh các biến CreditScore, Income, LoanAmount và LoanTerm trong tập dữ liệu df.

Ý nghĩa thống kê: Kết quả cho thấy điểm tín dụng dao động từ 300 đến 849, với trung bình khoảng 574, phản ánh mức tín dụng phổ biến ở mức trung bình khá. Thu nhập của người vay trung bình khoảng 82,499, trong khi khoản vay trung bình khoảng 127,579, tương đương gấp 1.5 lần thu nhập.

Bảng thống kê tỷ lệ vỡ nợ cho nhóm có/không có người phụ thuộc

df_clean %>%
  group_by(HasDependents) %>%
  summarise(
    Count = n(),
    Default_Rate = mean(Default, na.rm = TRUE) * 100
  ) %>%
  arrange(desc(Default_Rate))

|HasDependents | Count| Default_Rate||:————-|——-:|————:||no | 127.605| 12.72||yes | 127.742| 10.50|

Kỹ thuật:

2. Dùng group_by(HasDependents) để nhóm dữ liệu theo việc có người phụ thuộc hay không.

3. summarise() tính:

Count = n(): số lượng khách hàng trong mỗi nhóm.

Default_Rate = mean(Default) × 100: tỷ lệ vỡ nợ trung bình (phần trăm).

7. arrange(desc(Default_Rate)) sắp xếp nhóm có tỷ lệ vỡ nợ cao nhất lên trước.

Ý nghĩa thống kê: Khách hàng không có người phụ thuộc có tỷ lệ vỡ nợ cao hơn (12.72%) so với nhóm có người phụ thuộc (10.50%). Điều này cho thấy những người có trách nhiệm gia đình thường có xu hướng quản lý tài chính tốt hơn, nên ít rủi ro vỡ nợ hơn.

Trực quan hóa dữ liệu

Tạo bộ dữ liệu mới để trực quan hóa dữ liệu

df_viz <- df %>%
  # Tạo các biến Log 
  mutate(
    Income_log = log1p(Income),
    LoanAmount_log = log1p(LoanAmount)
  ) %>%
  
  # Tạo các biến phân nhóm
  mutate(
    Age_Group = cut(
      Age,
      breaks = c(17, 25, 35, 45, 55, 69),
      labels = c("18-25", "26-35", "36-45", "46-55", "56-69")
    ),
    Credit_Score_Band = cut(
      CreditScore,
      breaks = c(0, 579, 669, 739, 799, 850),
      labels = c("Poor", "Fair", "Good", "Very Good", "Excellent")
    )
  ) %>%
  
  # Chuẩn hóa text 
  mutate(
    across(
      c(
        HasMortgage, HasDependents, HasCoSigner,
        Education, EmploymentType, MaritalStatus, LoanPurpose
      ),
      str_to_lower
    )
  ) %>%
  
  # Chuyển đổi hàng loạt sang Factor
  mutate(
    across(
      c(
        Education, EmploymentType, MaritalStatus, LoanPurpose,
        HasMortgage, HasCoSigner, HasDependents,
        Age_Group, Credit_Score_Band
      ),
      as.factor
    ),
    Default = as.factor(Default)
  )

Kỹ thuật:

1. . Khởi tạo df_viz từ df và dùng pipe %>% để thực hiện các bước xử lý tiếp theo.

3. Dùng mutate() tạo hai biến log: • Income_log = log1p(Income) • LoanAmount_log = log1p(LoanAmount)

9. Tạo biến nhóm tuổi Age_Group bằng cut(), chia Age thành 5 khoảng: 18–25, 26–35, 36–45, 46–55, 56–69.

15. Tạo biến nhóm điểm tín dụng Credit_Score_Band bằng cut() theo thang điểm: • Poor (0–579), Fair (580–669), Good (670–739), Very Good (740–799), Excellent (800–850).

23. Chuẩn hóa dữ liệu text: Dùng mutate(across(…, str_to_lower)) để chuyển các biến ký tự (HasMortgage, HasDependents, HasCoSigner, Education, EmploymentType, MaritalStatus, LoanPurpose) về chữ thường.

34. Chuyển các biến phân loại sang factor bằng mutate(across(…, as.factor)). Các biến gồm: Education, EmploymentType, MaritalStatus, LoanPurpose, HasMortgage, HasCoSigner, HasDependents, Age_Group, Credit_Score_Band.

43. Biến Default cũng được chuyển thành factor để phục vụ phân tích mô hình hoặc trực quan hóa dữ liệu.

Ý nghĩa: Mục đích là làm sạch, chuẩn hóa và cấu trúc dữ liệu, giúp thuận lợi cho các bước phân tích thống kê và trực quan hóa sau đó.

Đồ thị 1: Phân bổ thu nhập

ggplot(df_viz, aes(x = Income)) +
  geom_histogram(bins = 50, fill = "steelblue", alpha = 0.8) +
  scale_x_log10(labels = comma_format()) + 
  labs(
    title = " Đồ thị 1: Phân bổ thu nhập khách hàng",
    x = "Thu nhập (Log Scale)",
    y = "Số lượng (Count)"
  ) +
  theme_minimal()

Kỹ thuật:

1. Gọi hàm ggplot() với dữ liệu df_viz, gán trục hoành x = Income.

2. Dùng geom_histogram() để vẽ biểu đồ histogram, chia dữ liệu thành 50 bins, tô màu steelblue, độ trong suốt alpha = 0.8.

3. Áp dụng scale_x_log10() để chuyển trục X sang thang logarit, đồng thời định dạng nhãn bằng dấu phẩy cho dễ đọc.

4. Hàm labs() thêm tiêu đề và nhãn trục: • title: “Đồ thị 1: Phân bố thu nhập khách hàng” • x: “Thu nhập (Log Scale)” • y: “Số lượng (Count)”

8. theme_minimal() áp dụng giao diện tối giản cho biểu đồ.

Ý nghĩa thống kê: Biểu đồ cho thấy phân bố thu nhập của khách hàng lệch phải (right-skewed) — phần lớn người vay có thu nhập trung bình hoặc thấp, trong khi chỉ có một nhóm nhỏ có thu nhập cao.

Đồ thị 2: Phân bổ số tiền vay

ggplot(df_viz, aes(x = LoanAmount)) +
  geom_histogram(
    bins = 50,
    fill = "darkgreen",
    alpha = 0.8
  ) +
  scale_x_log10(labels = comma_format()) +  
  geom_vline(
    aes(xintercept = median(LoanAmount, na.rm = TRUE)),
    color = "red",
    linetype = "dashed",
    linewidth = 1
  ) +  # Đường trung vị
  labs(
    title = "Đồ thị 2: Phân bổ số tiền vay",
    x = "Số tiền vay (Log Scale)",
    y = "Số lượng (Count)"
  ) +
  theme_light()

Kỹ thuật:

1. Gọi hàm ggplot() với dữ liệu df_viz, thiết lập trục hoành x = LoanAmount.

2. Dùng geom_histogram() để vẽ biểu đồ tần suất: chia dữ liệu thành 50 bins, tô màu darkgreen, độ trong suốt alpha = 0.8.

7. Áp dụng scale_x_log10() để chuyển trục X sang thang logarit, giúp hiển thị rõ hơn các giá trị lớn.

8. Thêm đường trung vị (median) bằng geom_vline(), có màu đỏ, kiểu nét đứt (dashed) và độ dày đường linewidth = 1.

14. Dùng labs() để đặt tiêu đề và nhãn trục: • title: “Đồ thị 2: Phân bổ số tiền vay” • x: “Số tiền vay (Log Scale)” • y: “Số lượng (Count)”

19. theme_light() để tạo giao diện sáng, dễ đọc cho biểu đồ.

Ý nghĩa thống kê: Biểu đồ cho thấy phần lớn khách hàng vay những khoản tiền ở mức trung bình, trong khi chỉ có một số ít vay số tiền lớn — thể hiện phân bố lệch phải. Đường trung vị màu đỏ cho thấy một nửa số khoản vay nhỏ hơn khoảng 127,500, phản ánh xu hướng chung là đa số khách hàng vay ở mức vừa phải, phù hợp với khả năng tài chính và thu nhập trung bình của họ.

Đồ thị 3: Phân bổ mật độ lãi suất theo tình trạng hôn nhân

ggplot(df_viz, aes(x = InterestRate, fill = MaritalStatus)) +
  geom_density(alpha = 0.5) + # Vẽ biểu đồ mật độ
  labs(
    title = "Đồ thị 3: Phân bổ mật độ lãi suất theo tình trạng hôn nhân",
    x = "Lãi suất (%)",
    y = "Mật độ (Density)",
    fill = "Tình trạng Hôn nhân"
  ) +
  theme_bw() +
  scale_fill_brewer(palette = "Set1") 

Kỹ thuật:

1. Gọi hàm ggplot(df_viz, aes(x = InterestRate, fill = MaritalStatus)) — khởi tạo biểu đồ, trục hoành là InterestRate, vùng tô màu phân biệt theo MaritalStatus.

2. Dùng geom_density(alpha = 0.5) để vẽ biểu đồ mật độ (density plot), với độ trong suốt 50% giúp chồng màu dễ quan sát.

3. Sử dụng labs() để thêm nhãn cho biểu đồ: • title: “Đồ thị 3: Phân bố mật độ lãi suất theo tình trạng hôn nhân”. • x: “Lãi suất (%)”. • y: “Mật độ (Density)”. • fill: “Tình trạng Hôn nhân” — chú giải phần tô màu.

9. Kết thúc bằng theme_bw() để áp dụng giao diện nền trắng – đen, tạo cảm giác trang nhã và rõ nét.

Ý nghĩa thống kê: Biểu đồ cho thấy phân bố lãi suất giữa các nhóm hôn nhân tương đối giống nhau, tập trung chủ yếu trong khoảng 5–25%. Không có sự khác biệt đáng kể về mức lãi suất trung bình giữa người độc thân, đã kết hôn và ly hôn.

Đồ thị 4: Phân bổ điểm tín dụng

ggplot(df_viz, aes(x = CreditScore)) +
  geom_histogram(
    binwidth = 10,
    fill = "purple",
    alpha = 0.7
  ) +
  geom_vline(
    aes(xintercept = mean(CreditScore, na.rm = TRUE)),
    color = "blue",
    linetype = "dashed",
    linewidth = 1
  ) +  # Trung bình
  geom_vline(
    aes(xintercept = median(CreditScore, na.rm = TRUE)),
    color = "red",
    linetype = "dotted",
    linewidth = 1
  ) +  # Trung vị
  labs(
    title = "Đồ thị 4: Phân bổ điểm tín dụng",
    subtitle = "Xanh = Trung bình, Đỏ = Trung vị",
    x = "Điểm tín dụng",
    y = "Số lượng (Count)"
  ) +
  theme_classic()

Kỹ thuật:

1. Gọi ggplot(df_viz, aes(x = CreditScore)) — khởi tạo biểu đồ, trục X là CreditScore.

2. Dùng geom_histogram() để vẽ biểu đồ tần suất, chia khoảng 10 điểm, tô màu tím và đặt độ trong suốt 70%.

7. Thêm đường trung bình bằng geom_vline() màu xanh, nét đứt, biểu thị giá trị trung bình của điểm tín dụng.

13. Thêm đường trung vị bằng geom_vline() màu đỏ, nét chấm, thể hiện giá trị trung vị.

19. Dùng labs() thêm tiêu đề và nhãn: “Đồ thị 4: Phân bổ điểm tín dụng”, phụ đề “Xanh = Trung bình, Đỏ = Trung vị”.

25. Kết thúc bằng theme_classic() để biểu đồ đơn giản, dễ đọc và chuyên nghiệp.

Ý nghĩa thống kê: Biểu đồ cho thấy phân bố điểm tín dụng khá đồng đều trong khoảng từ 300–850, không có nhóm khách hàng nào chiếm ưu thế rõ rệt. Hai đường trung bình và trung vị gần trùng nhau quanh mức ~574 điểm, cho thấy dữ liệu phân bố đối xứng và ổn định. Điều này phản ánh rằng đa phần khách hàng có mức tín dụng trung bình, không quá thấp cũng chưa đạt mức xuất sắc.

Đồ thị 5: Phân bổ tuổi theo loại hình công việc

ggplot(df_viz, aes(x = Age, color = EmploymentType)) +
  geom_freqpoly(binwidth = 1, linewidth = 1) + # Đồ thị đa giác tần suất
  labs(
    title = "Đồ thị 5: Phân bổ tuổi theo loại hình công việc",
    x = "Tuổi",
    y = "Số lượng (Count)",
    color = "Loại hình Công việc"
  ) +
  theme_minimal() +
  scale_color_brewer(palette = "Set2")

Kỹ thuật:

1. Gọi ggplot(df_viz, aes(x = Age, color = EmploymentType)) — khởi tạo biểu đồ, trục X là Age, màu phân biệt theo EmploymentType.

2. Dùng geom_freqpoly(binwidth = 1, linewidth = 1) để vẽ đồ thị đa giác tần suất, mỗi khoảng 1 tuổi, đường vẽ dày 1 đơn vị.

3. Hàm labs() thêm tiêu đề và nhãn: • title: “Đồ thị 5: Phân bố tuổi theo loại hình công việc”. • x: “Tuổi”. • y: “Số lượng (Count)”. • color: “Loại hình Công việc”.

9. Áp dụng theme_minimal() để biểu đồ sáng, đơn giản.

10. Dùng scale_color_brewer(palette = “Set2”) để chọn bảng màu dịu, dễ phân biệt giữa các nhóm nghề nghiệp.

Ý nghĩa thống kê: Biểu đồ cho thấy phân bố tuổi giữa các loại hình công việc khá đồng đều, không có sự khác biệt rõ rệt. Số lượng người trong các nhóm tuổi gần như tương đương, cho thấy lực lượng lao động được phân bổ tương đối cân bằng giữa các loại hình như toàn thời gian, bán thời gian, tự doanh hay thất nghiệp.

Đồ thị 6: Phân bổ tỷ lệ nợ/thu nhập

ggplot(df_viz, aes(x = DTIRatio)) +
  geom_histogram(
    bins = 40,
    fill = "orange",
    alpha = 0.8,
    color = "white"
  ) +
  geom_vline(
    aes(xintercept = mean(DTIRatio, na.rm = TRUE)),
    color = "black",
    linetype = "dashed",
    linewidth = 1
  ) +
  labs(
    title = "Đồ thị 6: Phân bổ tỷ lệ nợ trên thu nhập",
    subtitle = "Đường đen là Trung bình",
    x = "DTIRatio (Tỷ lệ Nợ/Thu nhập)",
    y = "Số lượng (Count)"
  ) +
  theme_bw()

Kỹ thuật:

1 Khởi tạo biểu đồ với ggplot(…), trục X là DTIRatio.

2. geom_histogram(…) vẽ histogram: 40 bins, tô orange, alpha = 0.8, viền white.

8. geom_vline(…) kẻ đường trung bình của DTIRatio (na.rm = TRUE), màu đen, dashed, linewidth = 1.

14. labs(…) đặt title, subtitle (“Đường đen là Trung bình”), nhãn x và y.

20. theme_bw() áp dụng giao diện nền trắng–đen, nét rõ.

Ý nghĩa thống kê: Biểu đồ cho thấy tỷ lệ nợ trên thu nhập (DTIRatio) của khách hàng phân bố khá đều, với trung bình xấp xỉ 0.5 (tức nợ chiếm khoảng 50% thu nhập). Điều này phản ánh đa số khách hàng có mức vay trong giới hạn hợp lý, chưa vượt ngưỡng rủi ro tài chính.

Đồ thị 7: Số lượng khách hàng theo trình độ học vấn

ggplot(
  df_viz,
  aes(x = reorder(Education, Education, function(x) -length(x)))
) +
  geom_bar(fill = "steelblue", width = 0.7) +
  geom_text(
    stat = "count",
    aes(label = after_stat(count)),
    hjust = 0.95,
    color = "white",
    size = 3.8
  ) +
  labs(
    title = "Đồ thị 7: Số lượng khách hàng theo trình độ học vấn",
    subtitle = "Sắp xếp theo số lượng (cao đến thấp)",
    x = "Trình độ học vấn",
    y = "Số lượng (Count)"
  ) +
  coord_flip(clip = "off") +
  theme_minimal(base_size = 13) +
  theme(
    plot.margin = margin(15, 20, 15, 15),
    plot.title = element_text(face = "bold", hjust = 0.5),
    plot.subtitle = element_text(hjust = 0.5)
  )

Kỹ thuật:

1. Gọi hàm ggplot() để khởi tạo biểu đồ, với trục X là biến Education, sắp xếp theo tần suất giảm dần bằng reorder().

5. Dùng geom_bar() để vẽ biểu đồ cột, tô màu xanh steelblue và đặt width = 0.7 giúp thanh gọn và cân đối.

6. Thêm nhãn bằng geom_text() hiển thị số lượng (count) bên trong mỗi thanh, căn lề phải (hjust = 0.95), màu chữ trắng giúp tương phản rõ.

13. Sử dụng labs() để thêm tiêu đề, phụ đề, nhãn trục X – Y rõ ràng, phục vụ mô tả nội dung biểu đồ.

19. Dùng coord_flip() để lật ngang biểu đồ, kết hợp theme_minimal() và theme() để căn giữa tiêu đề.

Ý nghĩa thống kê: Biểu đồ cho thấy số lượng khách hàng phân bố khá đồng đều giữa các nhóm học vấn, trong đó nhóm bachelor’s chiếm cao nhất với 64,366 người, tiếp đến là high school (63,903 người), master’s (63,541 người) và phd thấp nhất với 63,537 người.

Đồ thị 8: Số lượng khách hàng theo mục đích vay

df_purpose_counts <- df_viz %>%
  count(LoanPurpose, name = "Count")

ggplot(
  df_purpose_counts,
  aes(x = reorder(LoanPurpose, Count), y = Count)
) +
  geom_col(fill = "coral", width = 0.7) +
  geom_text(
    aes(label = Count),
    hjust = 1.05,                    
    size = 4
  ) +
  expand_limits(y = max(df_purpose_counts$Count) * 1.05) +
  labs(
    title = "Đồ thị 8: Số lượng khách hàng theo mục đích vay",
    subtitle = "Sắp xếp theo số lượng (thấp đến cao)",
    x = "Mục đích vay",
    y = "Số lượng (Count)"
  ) +
  coord_flip(clip = "off") +         
  theme_minimal(base_size = 14) +
  theme(
    plot.margin = margin(15, 25, 15, 15),
    plot.title = element_text(face = "bold", hjust = 0.5),
    plot.subtitle = element_text(hjust = 0.5)
  )

Kỹ thuật: 1. Tạo bảng dữ liệu df_purpose_counts bằng cách đếm số lượng từng mục đích vay (LoanPurpose) và lưu kết quả vào cột Count.

4. Khởi tạo biểu đồ với ggplot(), trục hoành là mục đích vay được sắp xếp theo số lượng tăng dần, trục tung là Count.

8. Sử dụng geom_col() để vẽ các thanh cột ngang, tô màu cam (coral) và điều chỉnh độ rộng cột cho cân đối.

9. Dùng geom_text() để thêm nhãn số lượng khách hàng vào trong mỗi thanh, với hjust = 1.05 để chữ nằm gọn bên trong và không bị tràn, kích cỡ chữ size = 4 dễ đọc.

14. expand_limits() nới giới hạn trục Y thêm 5% giúp chữ không chạm biên khi hiển thị.

15. Dùng labs() thêm tiêu đề, phụ đề và nhãn trục rõ ràng cho biểu đồ.

21. coord_flip(clip = “off”) lật ngang biểu đồ và cho phép hiển thị đầy đủ nhãn nằm sát mép.

22. Áp dụng theme_minimal() tạo nền gọn nhẹ và tùy chỉnh lề, căn giữa tiêu đề – phụ đề để bố cục hài hòa và không tràn khung khi in.

Ý nghĩa thống kê: Biểu đồ cho thấy số lượng khách hàng vay theo mục đích khá cân bằng, dao động quanh 50,000 khoản vay cho mỗi loại. Cụ thể, vay business cao nhất với 51,298 khách hàng, kế đến là home (51,286), education (51,005), other (50,914) và auto thấp nhất (50,844).

Đồ thị 9: Tình trạng hôn nhân trong từng nhóm học vấn

ggplot(df_viz, aes(x = Education, fill = MaritalStatus)) +
  geom_bar(position = "stack") +
  geom_text(stat = 'count', aes(label = after_stat(count)), 
            position = position_stack(vjust = 0.5), size = 3) +
  labs(
    title = "Đồ thị 9: Tình trạng hôn nhân trong từng nhóm học vấn",
    x = "Trình độ học vấn",
    y = "Số lượng (Count)",
    fill = "Tình trạng Hôn nhân"
  ) +
  theme_light() +
  scale_fill_brewer(palette = "Paired")

Kỹ thuật:

1. Gọi ggplot(df_viz, aes(x = Education, fill = MaritalStatus)) — khởi tạo biểu đồ cột, trong đó trục X là trình độ học vấn, màu sắc các phần thể hiện tình trạng hôn nhân.

2. Dùng geom_bar(position = “stack”) để vẽ biểu đồ cột chồng, các phần của mỗi cột thể hiện tỷ lệ từng nhóm hôn nhân.

3. Thêm nhãn số lượng bằng geom_text(), đặt vị trí giữa mỗi phần cột với vjust = 0.5 để dễ đọc, và size = 3 giúp chữ rõ ràng nhưng không che dữ liệu.

5. Sử dụng labs() để thêm tiêu đề, nhãn trục và chú giải: • Tiêu đề: “Đồ thị 9: Tình trạng hôn nhân trong từng nhóm học vấn” • Trục X: “Trình độ học vấn”, Trục Y: “Số lượng (Count)” • Chú giải: “Tình trạng Hôn nhân”.

11. theme_light() áp dụng phong cách sáng, dễ quan sát dữ liệu.

12. scale_fill_brewer(palette = “Paired”) chọn bảng màu Paired giúp phân biệt rõ ràng các nhóm hôn nhân, đồng thời giữ tính thẩm mỹ và chuyên nghiệp cho biểu đồ.

Đồ thị 10: Số lượng Có/Không người phụ thuộc theo nhóm điểm tín dụng

ggplot(df_viz, aes(x = Credit_Score_Band, fill = HasDependents)) +
  geom_bar(position = "dodge") +
  geom_text(stat = 'count', aes(label = after_stat(count)), 
            position = position_dodge(width = 0.9), vjust = -0.3, size = 3) +
  labs(
    title = "Đồ thị 10: Số lượng Có/Không người phụ thuộc theo nhóm điểm tín dụng",
    x = "Nhóm Điểm Tín dụng",
    y = "Số lượng (Count)",
    fill = "Có Người phụ thuộc?"
  ) +
  theme_minimal() +
  scale_fill_brewer(palette = "Set2")

Kỹ thuật:

1. Khởi tạo biểu đồ với ggplot(df_viz, aes(x = Credit_Score_Band, fill = HasDependents)) — trục X là nhóm điểm tín dụng, phần tô màu phân biệt nhóm có hoặc không người phụ thuộc.

2. Dùng geom_bar(position = “dodge”) để vẽ biểu đồ cột đặt cạnh nhau, giúp so sánh rõ ràng giữa hai nhóm trong mỗi hạng điểm tín dụng.

3. Thêm nhãn bằng geom_text() hiển thị số lượng khách hàng ngay trên đầu mỗi cột, căn chỉnh vị trí bằng position_dodge(width = 0.9) và vjust = -0.3 để nhãn nằm gọn bên trên.

5. labs() đặt tiêu đề, nhãn trục và chú giải: • Title: “Đồ thị 10: Số lượng Có/Không người phụ thuộc theo nhóm điểm tín dụng”. • Trục X: “Nhóm Điểm Tín dụng”. • Trục Y: “Số lượng (Count)”. • Chú giải: “Có Người phụ thuộc?”.

11. theme_minimal() tạo bố cục gọn gàng, sáng rõ, tập trung vào dữ liệu.

12. scale_fill_brewer(palette = “Set2”) chọn bảng màu nhẹ, dễ phân biệt hai nhóm, đảm bảo tính trực quan và dễ nhìn khi in ấn.

Ý nghĩa thống kê: Biểu đồ cho thấy số lượng khách hàng có và không có người phụ thuộc gần như tương đương trong mọi nhóm điểm tín dụng. Cụ thể, nhóm Poor có 64,804 người không có và 65,419 người có người phụ thuộc; nhóm Fair lần lượt là 21,040 và 20,807; nhóm Good là 16,135 và 15,938; nhóm Very Good là 13,832 và 13,904; còn nhóm Excellent là 11,794 và 11,674. theme_minimal(): tạo nền sáng, giúp dữ liệu nổi bật.

Đồ thị 11: Tỷ lệ các loại hình công việc

df_viz %>%
  count(EmploymentType) %>%
  mutate(Percentage = n / sum(n)) %>%
  ggplot(
    aes(
      x = "",
      y = Percentage,
      fill = EmploymentType
    )
  ) +
  geom_bar(
    stat = "identity",
    width = 1
  ) +
  coord_polar(theta = "y") +
  geom_text(
    aes(label = percent(Percentage, accuracy = 0.01)),
    position = position_stack(vjust = 0.5),
    size = 3
  ) +
  labs(
    title = "Đồ thị 11: Tỷ lệ các loại hình công việc",
    fill = "Loại hình Công việc"
  ) +
  theme_void()

Kỹ thuật:

1. Gọi df_viz %>% — bắt đầu chuỗi thao tác dữ liệu bằng pipe (%>%).

2. count(EmploymentType) — đếm số lượng từng loại hình công việc trong dữ liệu.

3. mutate(Percentage = n / sum(n)) — tính tỷ lệ phần trăm của mỗi loại công việc so với tổng số.

4. ggplot(…) — khởi tạo biểu đồ, trục X để trống (“”) vì đây là biểu đồ tròn, trục Y là Percentage, màu (fill) thể hiện từng nhóm công việc.

11. geom_bar(stat = “identity”, width = 1) — vẽ biểu đồ cột tròn, mỗi phần tương ứng tỷ lệ từng nhóm.

15. coord_polar(theta = “y”) — chuyển biểu đồ cột thành biểu đồ tròn bằng cách dùng hệ tọa độ cực.

16. geom_text(…) — thêm nhãn phần trăm vào giữa từng lát tròn, căn giữa theo chiều dọc với vjust = 0.5, chữ kích thước size = 3 giúp dễ đọc mà không bị chồng lấn.

21. labs(…) — đặt tiêu đề “Đồ thị 11: Tỷ lệ các loại hình công việc” và chú giải “Loại hình Công việc”.

25. theme_void() — loại bỏ toàn bộ lưới, trục và nền để biểu đồ tròn sạch, tối giản, phù hợp trình bày báo cáo hoặc in ấn.

Ý nghĩa thống kê: Biểu đồ cho thấy tỷ lệ các loại hình công việc trong mẫu dữ liệu gần như bằng nhau, thể hiện sự phân bố đồng đều giữa bốn nhóm. Cụ thể, nhóm self-employed chiếm 25.13%, unemployed chiếm 25.00%, part-time chiếm 24.95% và full-time chiếm 24.93%. Sự chênh lệch chỉ khoảng 0.2% giữa các nhóm cho thấy cơ cấu việc làm trong dữ liệu được phân bổ cân bằng, không có nhóm nào chiếm ưu thế vượt trội.

Đồ thị 12: Biểu đồ Treemap thể hiện số lượng theo mục đích vay

df_viz %>%
  count(LoanPurpose) %>%
  ggplot(aes(area = n, fill = LoanPurpose, label = paste(LoanPurpose, n, sep = "\n"))) +
  geom_treemap() +
  geom_treemap_text(color = "white", place = "centre", grow = FALSE, size = 13) +
  labs(
    title = "Đồ thị 12: Treemap thể hiện số lượng theo mục đích vay",
    fill = "Mục đích vay"
  ) +
  theme_minimal() +
  theme(legend.position = "none")

Kỹ thuật:

1. Gọi df_viz %>% — bắt đầu chuỗi xử lý dữ liệu.

2. Dùng count(LoanPurpose) để đếm số lượng từng mục đích vay.

3. Khởi tạo ggplot() và ánh xạ diện tích (area), màu (fill), nhãn (label).

5. Vẽ biểu đồ treemap bằng geom_treemap().

6. Thêm nhãn giữa các ô với geom_treemap_text().

8. Đặt tiêu đề và nhãn cho biểu đồ qua labs().

10. Dùng theme_minimal() để tạo bố cục sáng, đơn giản.

11. Ẩn chú giải bằng theme(legend.position = “none”).

Ý nghĩa thống kê: Biểu đồ cho thấy sự phân bổ số lượng khách hàng khá đồng đều giữa các nhóm mục đích vay. Cụ thể, nhóm business có 51,298 khách hàng, home 51,286, education 51,005, other 50,914 và auto 50,844.

Đồ thị 13: Tỷ lệ vỡ nợ theo nhóm tuổi

df_age_rate <- df_viz %>%
  group_by(Age_Group) %>%
  summarise(
    Default_Rate = mean(Default == "1", na.rm = TRUE),
    Count = n()
  ) %>%
  ungroup()

ggplot(df_age_rate, aes(x = Age_Group, y = Default_Rate)) +
  geom_col(aes(fill = Age_Group), show.legend = FALSE) +
  geom_text(
    aes(label = percent(Default_Rate, accuracy = 0.1)),
    vjust = -0.5,
    color = "black",
    fontface = "bold"
  ) +
  scale_y_continuous(labels = percent_format(), limits = c(0, 0.25)) +
  scale_fill_brewer(palette = "YlOrRd") +
  labs(
    title = "Đồ thị 13: Tỷ lệ vỡ nợ theo nhóm tuổi",
    x = "Nhóm Tuổi",
    y = "Tỷ lệ Vỡ nợ"
  ) +
  theme_minimal(base_size = 14)

Kỹ thuật:

1.Gọi df_age_rate <- df_viz %>% — khởi tạo chuỗi xử lý và lưu kết quả vào biến mới.

2. Dùng group_by(Age_Group) để nhóm dữ liệu theo nhóm tuổi.

3. Dùng summarise() để tính tỷ lệ vỡ nợ trung bình (Default_Rate) và số lượng khách hàng (Count).

7. ungroup() — bỏ nhóm để không ảnh hưởng đến các phép tính sau.

9. Khởi tạo ggplot() với trục X là nhóm tuổi (Age_Group), trục Y là tỷ lệ vỡ nợ (Default_Rate).

10. Vẽ biểu đồ cột bằng geom_col() thể hiện tỷ lệ vỡ nợ theo từng nhóm.

11. Thêm nhãn phần trăm lên cột bằng geom_text().

17. Dùng scale_y_continuous() để hiển thị trục Y theo dạng phần trăm, giới hạn từ 0 đến 25%.

18. Dùng scale_fill_brewer() để tô màu biểu đồ bằng bảng màu “YlOrRd”.

19. Dùng labs() để thêm tiêu đề và tên trục.

24. Dùng theme_minimal(base_size = 14) để làm giao diện sáng và cân đối.

Ý nghĩa: Biểu đồ cho thấy tỷ lệ vỡ nợ có xu hướng giảm dần theo độ tuổi, phản ánh mối quan hệ nghịch đảo giữa tuổi tác và khả năng vỡ nợ. Cụ thể, nhóm tuổi 18–25 có tỷ lệ vỡ nợ cao nhất (20,8%), cho thấy những người trẻ tuổi thường gặp khó khăn hơn trong việc quản lý tài chính và duy trì khả năng thanh toán. Tỷ lệ này giảm dần ở các nhóm tuổi cao hơn, lần lượt là 16,1% ở nhóm 26–35, 11,5% ở nhóm 36–45, 8,4% ở nhóm 46–55 và thấp nhất là 5,5% ở nhóm 56–69. Điều này cho thấy rằng khi tuổi tác tăng, kinh nghiệm tài chính, thu nhập ổn định và ý thức về nghĩa vụ trả nợ cũng được cải thiện, giúp giảm đáng kể nguy cơ vỡ nợ.

Đồ thị 14: Phân phối điểm tín dụng theo loại hình công việc

ggplot(df_viz, aes(x = EmploymentType, y = CreditScore)) +
  geom_boxplot(aes(fill = EmploymentType), show.legend = FALSE) +
  coord_flip() +
  stat_summary(
    fun = median,
    geom = "text",
    aes(label = round(..y.., 0)),
    color = "black",
    fontface = "bold",
    hjust = -0.5
  ) +
  scale_fill_brewer(palette = "Set3") +
  labs(
    title = "Đồ thị 14: Phân phối điểm tín dụng theo loại hình công việc",
    x = "Loại hình Công việc",
    y = "Điểm Tín dụng"
  ) +
  theme_minimal(base_size = 14)

Kỹ thuật:

1. Gọi ggplot(df_viz, aes(x = EmploymentType, y = CreditScore)) — khởi tạo biểu đồ, trục X là loại hình công việc, trục Y là điểm tín dụng.

2. Dùng geom_boxplot() để vẽ biểu đồ hộp (boxplot) thể hiện phân bố điểm tín dụng theo từng loại công việc.

3. coord_flip() — lật ngang biểu đồ để dễ quan sát.

4. stat_summary() — tính giá trị trung vị và hiển thị bằng chữ.

12. Dùng scale_fill_brewer(palette = “Set3”) để tô màu bằng bảng màu dịu mắt.

13. Dùng labs() để thêm tiêu đề và nhãn cho trục.

18. Áp dụng theme_minimal(base_size = 14) để làm giao diện sáng, cân đối và dễ đọc.

Ý nghĩa thống kê: Biểu đồ cho thấy điểm tín dụng trung vị của các nhóm nghề nghiệp không có sự chênh lệch đáng kể, thể hiện mức độ ổn định tương đối giữa các loại hình công việc. Cụ thể, nhóm thất nghiệp có điểm tín dụng trung vị cao nhất (575), tiếp đến là nhóm tự kinh doanh và làm bán thời gian cùng đạt 574, trong khi nhóm làm toàn thời gian có điểm trung vị thấp nhất (572). Sự khác biệt nhỏ này cho thấy loại hình công việc không ảnh hưởng đáng kể đến điểm tín dụng, đồng thời gợi ý rằng các yếu tố khác như thu nhập, lịch sử tín dụng hay độ tuổi có thể đóng vai trò quan trọng hơn trong việc quyết định điểm tín dụng của cá nhân.

Đồ thị 15: Biểu đồ tương quan

numeric_vars <- df_viz %>% select(Age, Income,
LoanAmount, CreditScore, MonthsEmployed, InterestRate, DTIRatio)
cor_matrix <- cor(numeric_vars, use = "complete.obs")

melted_cor <- as.data.frame(cor_matrix) %>%
  tibble::rownames_to_column("Var1") %>%
  pivot_longer(-Var1, names_to = "Var2", values_to = "value")

ggplot(melted_cor, aes(x = Var1, y = Var2, fill = value)) +
  geom_tile() +
  scale_fill_gradient2(low = "blue", high = "red", mid = "white",
   midpoint = 0, limit = c(-1,1)) +
  geom_text(aes(label = round(value, 2)), size = 3) +
  labs(
    title = "Đồ thị 15: Ma trận Tương quan (Heatmap)",
    x = "", y = "", fill = "Hệ số Tương quan"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1))

Kỹ thuật:

1. Gọi numeric_vars <- df_viz %>% select(…) — chọn các biến số liên quan như Age, Income, LoanAmount,… để tính tương quan.

3. Tính ma trận tương quan bằng cor(…, use = “complete.obs”) — chỉ dùng các hàng không có giá trị thiếu.

5. Dùng as.data.frame() để chuyển ma trận thành dạng bảng dữ liệu.

6. Gắn tên biến vào cột bằng tibble::rownames_to_column(“Var1”).

7. Chuyển dữ liệu sang dạng dài bằng pivot_longer() — chuẩn bị cho việc vẽ heatmap.

9. Khởi tạo ggplot() với trục X = Var1, Y = Var2, và màu tô fill = value.

10. Dùng geom_tile() để vẽ các ô vuông đại diện cho giá trị tương quan.

11. Tô màu theo giá trị tương quan với scale_fill_gradient2(), từ xanh (âm) → trắng (0) → đỏ (dương).

13. Gắn nhãn giá trị hệ số tương quan lên từng ô bằng geom_text().

14. Dùng labs() để thêm tiêu đề và nhãn cho biểu đồ.

18. Áp dụng theme_minimal() cho bố cục sáng, đơn giản.

19. Tùy chỉnh góc xoay trục X bằng theme(axis.text.x = element_text(…)) để tránh chồng chữ.

Ý nghĩa thống kê:

Ma trận tương quan cho thấy các hệ số đều gần 0, tức không có mối quan hệ tuyến tính đáng kể giữa các biến định lượng như tuổi, thu nhập, số tiền vay, điểm tín dụng, lãi suất hay tỷ lệ nợ/thu nhập. Điều này hàm ý rằng các yếu tố tài chính và nhân khẩu học trong bộ dữ liệu này hoạt động khá độc lập, không ảnh hưởng mạnh lẫn nhau.

Đồ thị 16: Phân phối thu nhập theo học vấn

ggplot(df_viz, aes(x = Education, y = Income)) +
  geom_boxplot(fill = "lightblue", outlier.color = "red", outlier.alpha = 0.1) +
  stat_summary(fun = median, geom = "text", aes(label = comma(round(..y.., 0))), 
               hjust = -0.5, color = "black", size = 3) +
  scale_y_log10(labels = comma_format()) +
  coord_flip() +
  labs(
    title = "Đồ thị 16: Phân phối thu nhập theo học vấn ",
    x = "Trình độ học vấn",
    y = "Thu nhập (Log Scale)"
  ) +
  theme_light()

Kỹ thuật:

1. Gọi ggplot(df_viz, aes(x = Education, y = Income)) — khởi tạo biểu đồ, trục X là trình độ học vấn, trục Y là thu nhập.

2. Dùng geom_boxplot() để vẽ biểu đồ hộp thể hiện phân bố thu nhập theo từng nhóm học vấn; tô màu hộp bằng lightblue, đánh dấu ngoại lệ bằng chấm đỏ (outlier.color = “red”).

3. Dùng stat_summary() để hiển thị giá trị trung vị của từng hộp bằng chữ (median).

5. Dùng scale_y_log10() để biến đổi trục Y sang thang log, giúp dễ quan sát dữ liệu lệch.

6. coord_flip() — lật biểu đồ ngang để dễ đọc nhãn học vấn.

7. Dùng labs() để thêm tiêu đề và nhãn trục cho biểu đồ.

12. Áp dụng theme_light() cho giao diện sáng, nhẹ nhàng và rõ ràng.

Ý nghĩa thống kê: Biểu đồ cho thấy thu nhập trung vị giữa các nhóm học vấn có sự khác biệt nhỏ. Cụ thể, nhóm master’s có thu nhập trung vị cao nhất (≈ 83,103), tiếp đến là bachelor’s (≈ 82,386), high school (≈ 82,253) và phd (≈ 82,170).

Đồ thị 17: Phân phối lãi suất theo mục đích vay

ggplot(df_viz, aes(x = reorder(LoanPurpose, InterestRate,
                               median, na.rm=T), y = InterestRate,
                   fill = LoanPurpose)) +
  geom_boxplot(outlier.shape = NA) +
  stat_summary(fun = median, geom = "text", aes(label = round(..y.., 2)), 
               hjust = -0.5, color = "black", size = 3) +
  coord_flip() +
  labs(
    title = "Đồ thị 17: Phân phối lãi suất theo mục đích vay",
    subtitle = "Sắp xếp theo Lãi suất trung vị",
    x = "Mục đích vay",
    y = "Lãi suất (%)"
  ) +
  theme_minimal() +
  theme(legend.position = "none")

Kỹ thuật:

1. Gọi ggplot(df_viz, aes(x = reorder(LoanPurpose, InterestRate, median, na.rm=T), y = InterestRate, fill = LoanPurpose)) — khởi tạo biểu đồ, sắp xếp trục X theo trung vị lãi suất của từng mục đích vay.

4. Dùng geom_boxplot() để vẽ biểu đồ hộp (boxplot) thể hiện phân bố lãi suất theo mục đích vay, đồng thời ẩn các điểm ngoại lệ (outlier.shape = NA).

5. Dùng stat_summary() để thêm giá trị trung vị (median) hiển thị ngay trên mỗi hộp, giúp dễ so sánh.

7. coord_flip() — lật biểu đồ nằm ngang để dễ đọc nhãn trục X.

8. labs() — thêm tiêu đề, phụ đề, và tên trục, làm rõ ý nghĩa biểu đồ.

14. theme_minimal() — áp dụng giao diện sáng, gọn gàng.

15. theme(legend.position = “none”) — ẩn chú giải màu để biểu đồ sạch và tập trung vào dữ liệu.

Ý nghĩa thống kê: Biểu đồ cho thấy lãi suất trung vị giữa các mục đích vay gần như tương đương nhau, dao động quanh 13.42%–13.49%. Cụ thể, nhóm vay home có trung vị cao nhất (13.49%), kế đến là education và business (đều 13.48%), còn auto và other thấp hơn một chút (13.42%).

Đồ thị 18: Biểu đồ lãi suất theo tình trạng vỡ nợ

ggplot(df_viz, aes(x = Default, y = InterestRate, fill = Default)) +
  geom_violin(trim = FALSE, alpha = 0.8) +
  geom_boxplot(width = 0.1, fill = "white", outlier.size = 1) +
  stat_summary(fun = median, geom = "text", aes(label = round(..y.., 2)), 
               vjust = -2, color = "black", size = 4) +
  labs(
    title = "Đồ thị 18: Biểu đồ lãi suất theo tình trạng vỡ nợ",
    x = "Vỡ nợ (0 = Không, 1 = Có)",
    y = "Lãi suất (%)",
    fill = "Vỡ nợ"
  ) +
  theme_bw() +
  scale_fill_manual(values = c("0" = "green", "1" = "red"))

Kỹ thuật:

1. Gọi ggplot(df_viz, aes(x = Default, y = InterestRate, fill = Default)) — khởi tạo biểu đồ, trục X là tình trạng vỡ nợ, trục Y là lãi suất, và màu tô theo nhóm vỡ nợ.

2. Dùng geom_violin() để vẽ biểu đồ violin thể hiện mật độ phân bố lãi suất theo từng nhóm vỡ nợ.

3. Dùng geom_boxplot() chồng lên để biểu diễn thêm phạm vi và trung vị của dữ liệu.

4. Dùng stat_summary() hiển thị giá trị trung vị của mỗi nhóm bằng số trên đồ thị.

6. Dùng labs() để thêm tiêu đề, nhãn trục, và chú giải.

12. Áp dụng theme_bw() để tạo nền trắng – đen, rõ ràng.

13. Dùng scale_fill_manual() để tô màu tùy chỉnh: xanh cho nhóm không vỡ nợ (0) và đỏ cho nhóm vỡ nợ (1).

Ý nghĩa thống kê: Biểu đồ thể hiện sự khác biệt rõ giữa hai nhóm: khách hàng vỡ nợ có lãi suất trung vị 16.93%, cao hơn đáng kể so với nhóm không vỡ nợ (12.99%). Điều này gợi ý mối quan hệ thuận giữa lãi suất và khả năng vỡ nợ — lãi suất cao hơn có thể làm tăng gánh nặng tài chính, dẫn đến rủi ro vỡ nợ cao hơn.

Đồ thị 19: Biểu đồ điểm tín dụng theo tình trạng vỡ nợ

ggplot(df_viz, aes(x = Default, y = CreditScore, fill = Default)) +
  geom_boxplot() +
  stat_summary(fun = median, geom = "text", aes(label = round(..y.., 0)), 
               vjust = -0.7, color = "black", size = 4) +
  labs(
    title = "Đồ thị 19: Biểu đồ điểm tín dụng theo tình trạng vỡ nợ",
    x = "Vỡ nợ (0 = Không, 1 = Có)",
    y = "Điểm Tín dụng"
  ) +
  theme_minimal() +
  scale_fill_manual(values = c("0" = "skyblue", "1" = "orange")) +
  theme(legend.position = "none")

Kỹ thuật:

1. Gọi ggplot(df_viz, aes(x = Default, y = CreditScore, fill = Default)) — khởi tạo biểu đồ, trục X là tình trạng vỡ nợ, trục Y là điểm tín dụng, và tô màu theo nhóm vỡ nợ.

2. Dùng geom_boxplot() để vẽ biểu đồ hộp, thể hiện phân bố điểm tín dụng của hai nhóm khách hàng.

3. Dùng stat_summary() để hiển thị giá trị trung vị trên mỗi hộp, giúp dễ so sánh giữa các nhóm.

5. Dùng labs() để thêm tiêu đề, mô tả và tên trục cho biểu đồ.

10. Áp dụng theme_minimal() để tạo phong cách sáng, gọn gàng.

11. Dùng scale_fill_manual() để tô màu tùy chỉnh: xanh nhạt (skyblue) cho nhóm không vỡ nợ và cam (orange) cho nhóm vỡ nợ.

12. Dùng theme(legend.position = “none”) để ẩn chú giải, giúp biểu đồ gọn hơn.

Ý nghĩa thống kê: Biểu đồ cho thấy nhóm không vỡ nợ có điểm tín dụng trung vị là 577, cao hơn so với nhóm vỡ nợ (553). Sự chênh lệch khoảng 24 điểm cho thấy điểm tín dụng có mối quan hệ nghịch với khả năng vỡ nợ — khách hàng có điểm tín dụng thấp hơn thường đi kèm với rủi ro tín dụng cao hơn, phản ánh khả năng quản lý tài chính yếu hơn hoặc lịch sử thanh toán kém ổn định.

Đồ thị 20: Phân phối tuổi theo tình trạng vỡ nợ

ggplot(df_viz, aes(x = Default, y = Age, fill = Default)) +
  geom_boxplot() +
  stat_summary(fun = median, geom = "text", aes(label = round(..y.., 0)), 
               vjust = -0.7, color = "black", size = 4) +
  labs(
    title = "Đồ thị 20: Phân phối tuổi theo tình trạng vỡ nợ",
    x = "Vỡ nợ (0 = Không, 1 = Có)",
    y = "Tuổi"
  ) +
  theme_minimal() +
  scale_fill_manual(values = c("0" = "lightgreen", "1" = "salmon")) +
  theme(legend.position = "none")

Kỹ thuật:

1. Gọi ggplot(df_viz, aes(x = Default, y = Age, fill = Default)) — khởi tạo biểu đồ, trục X là tình trạng vỡ nợ, trục Y là tuổi, và màu tô theo nhóm vỡ nợ.

2. Dùng geom_boxplot() để vẽ biểu đồ hộp, biểu diễn phân bố độ tuổi của hai nhóm khách hàng.

3. Dùng stat_summary() để hiển thị giá trị trung vị (median) của tuổi trong từng nhóm ngay trên biểu đồ.

5. Dùng labs() để thêm tiêu đề, mô tả và nhãn trục giúp biểu đồ rõ ràng, dễ hiểu.

10. Áp dụng theme_minimal() để tạo phong cách sáng và tối giản.

11. Dùng scale_fill_manual() để tô màu tùy chỉnh: xanh nhạt (lightgreen) cho nhóm không vỡ nợ, và cam hồng (salmon) cho nhóm có vỡ nợ.

12. Dùng theme(legend.position = “none”) để ẩn chú giải, giúp biểu đồ gọn gàng hơn.

Ý nghĩa thống kê: Biểu đồ cho thấy khách hàng vỡ nợ có độ tuổi trung vị là 34, thấp hơn đáng kể so với nhóm không vỡ nợ (45 tuổi). Điều này phản ánh mối liên hệ giữa tuổi tác và khả năng quản lý tín dụng — nhóm khách hàng trẻ tuổi có xu hướng gặp rủi ro tín dụng cao hơn, có thể do kinh nghiệm tài chính hạn chế hoặc thu nhập chưa ổn định, trong khi nhóm lớn tuổi thường có lịch sử tín dụng và khả năng trả nợ tốt hơn.

CHƯƠNG 2: PHÂN TÍCH CÔNG TY CHỨNG KHOÁNG FPT

Giới thiệu về bộ dữ liệu FPT

Đọc dữ liệu

data <- read_excel("FPT.xlsx", sheet = "Sheet1")

Kỹ thuật:

1. R đọc Sheet1 file dữ liệu FPT.xlsl trong thư mục làm việc rồi lưu vào biến data

Ý nghĩa: câu lệnh này giúp nạp dữ liệu gốc để bắt đầu các bước xử lý, thống kê và phân tích tiếp theo.

Xem 6 dòng dữ liệu đầu tiên

head(data)

Kỹ thuật:

1. head(data) hiển thị 6 dòng đầu tiên của bảng dữ liệu data.

Đây là lệnh dùng để xem nhanh cấu trúc và giá trị mẫu của dữ liệu sau khi được đọc vào từ file Excel hoặc CSV.

Ý nghĩa thống kê: Lệnh này giúp kiểm tra dữ liệu đầu vào, bao gồm tên biến, kiểu dữ liệu, và các giá trị ban đầu. Việc xem 6 dòng đầu giúp người phân tích xác định xem dữ liệu đã được đọc đúng định dạng chưa, có bị thiếu, trùng lặp hoặc sai kiểu (ví dụ: số bị đọc thành text) hay không trước khi tiến hành các bước xử lý và phân tích tiếp theo.

Xem 6 dòng dữ liệu cuối cùng

tail(data)

Kỹ thuật:

1. tail(data) hiển thị 6 dòng cuối cùng của bảng dữ liệu data.

Hàm này thường được dùng để kiểm tra phần cuối của tập dữ liệu, giúp phát hiện lỗi nhập liệu hoặc định dạng bất thường ở các dòng cuối.

Ý nghĩa thống kê: Câu lệnh giúp đảm bảo dữ liệu được nạp đầy đủ và không bị cắt xén, đồng thời hỗ trợ phát hiện các giá trị bị thiếu, trùng hoặc không hợp lệ ở cuối bảng.

Kiểm tra cấu trúc (Structure) của bộ dữ liệu

str(data)

Kỹ thuật:

1. str(data) hiển thị cấu trúc tổng quát của đối tượng data, bao gồm loại dữ liệu (data frame hoặc tibble), số dòng, số cột, tên biến và kiểu dữ liệu của từng biến.

Lệnh này giúp người dùng xem nhanh kiểu dữ liệu (numeric, character, factor, date, v.v.) mà không cần mở toàn bộ bảng.

Ý nghĩa thống kê: Câu lệnh này cho phép kiểm tra cấu trúc và định dạng của dữ liệu trước khi phân tích. Qua đó, người phân tích có thể phát hiện sớm các vấn đề như kiểu dữ liệu sai (ví dụ số bị đọc thành ký tự), giúp điều chỉnh và chuẩn hóa dữ liệu để đảm bảo các phép thống kê sau đó được thực hiện chính xác.

Xem kích thước của bộ dữ liệu

dim(data)
## [1] 86 11

Kỹ thuật:

1. dim(data) trả về kích thước của bảng dữ liệu, gồm hai giá trị: số hàng (quan sát) và số cột (biến).

Đây là hàm cơ bản trong R dùng để xác định quy mô của tập dữ liệu mà không cần mở toàn bộ bảng.

Ý nghĩa thống kê: Lệnh này giúp người phân tích nắm được phạm vi và cấu trúc tổng thể của dữ liệu, biết được có bao nhiêu quan sát và bao nhiêu biến được thu thập. Thông tin này hỗ trợ đánh giá tính đại diện của mẫu, cũng như chuẩn bị cho các bước phân tích mô tả và mô hình hóa sau này.

Lấy tên các cột

colnames(data)
##  [1] "CHỈ TIÊU" "2015"     "2016"     "2017"     "2018"    
##  [6] "2019"     "2020"     "2021"     "2022"     "2023"    
## [11] "2024"

Kỹ thuật:

1. colnames(data) hiển thị tên của tất cả các cột (biến) trong bảng dữ liệu data.

Đây là lệnh cơ bản giúp xem, kiểm tra hoặc chỉnh sửa tên biến; có thể đổi tên bằng cách gán colnames(data) <- c(“Tên1”, “Tên2”, …).

Ý nghĩa thống kê: Câu lệnh giúp xác định rõ danh sách các biến trong tập dữ liệu, đảm bảo tên biến được đặt đúng, dễ hiểu và không trùng lặp. Việc nắm rõ tên cột là bước quan trọng để thuận tiện khi truy cập, lọc và phân tích từng biến trong các bước thống kê tiếp theo.

Đếm tổng số giá trị bị thiếu

sum(is.na(data))
## [1] 131

Kỹ thuật:

1. is.na(data) tạo một ma trận logic có giá trị TRUE tại các ô bị thiếu (NA).

sum(is.na(data)) cộng tất cả giá trị TRUE, trả về tổng số ô dữ liệu bị thiếu trong toàn bộ bảng data.

Ý nghĩa thống kê: Câu lệnh này giúp xác định mức độ thiếu dữ liệu trong tập mẫu. Nếu kết quả bằng 0, dữ liệu đầy đủ; nếu lớn hơn 0, cần xem xét xử lý giá trị thiếu bằng cách loại bỏ, thay thế (imputation) hoặc giữ nguyên tùy theo mục tiêu phân tích. Đây là bước kiểm tra quan trọng trong giai đoạn làm sạch dữ liệu để đảm bảo tính chính xác của các thống kê sau này.

Số dữ liệu bị trùng lặp

sum(duplicated(data))
## [1] 2

Kỹ thuật:

1. duplicated(data) trả về vector logic với giá trị TRUE cho những hàng trùng lặp trong bảng data. sum(duplicated(data)) đếm tổng số hàng bị trùng, tức là số lượng bản ghi lặp lại hoàn toàn trong dữ liệu.

Ý nghĩa thống kê: Câu lệnh này giúp phát hiện các dòng dữ liệu bị trùng, một lỗi thường gặp trong quá trình thu thập hoặc nhập liệu. Việc nhận diện và xử lý trùng lặp giúp đảm bảo tính duy nhất và độ tin cậy của dữ liệu, tránh ảnh hưởng đến các phép tính trung bình, tần suất và kết quả mô hình hóa sau này.

Tỷ lệ phần trăm ô thiếu dữ liệu

mean(is.na(data)) * 100
## [1] 13.84778

Kỹ thuật:

1. is.na(data) tạo ma trận logic đánh dấu các ô bị thiếu.

mean(is.na(data)) tính tỷ lệ trung bình của các giá trị NA trên toàn bộ dữ liệu (vì TRUE = 1, FALSE = 0).

Nhân với * 100 để chuyển đổi sang phần trăm (%) giá trị bị thiếu.

Ý nghĩa thống kê: Câu lệnh này cho biết tỷ lệ phần trăm dữ liệu bị thiếu trong toàn bộ tập dữ liệu. Nếu tỷ lệ này nhỏ (ví dụ <5%), có thể chấp nhận được; nếu cao, cần xem xét phương án xử lý thiếu dữ liệu như loại bỏ biến, điền giá trị trung bình hoặc áp dụng kỹ thuật suy diễn (imputation) nhằm đảm bảo độ tin cậy cho phân tích thống kê.

Xử lý dữ liệu thô, mã hóa dữ liệu FPT

Tạo bộ dữ liệu mới phục vụ việc phân tích

cac_chi_tieu_can_chon <- c(
  "TÀI SẢN NGẮN HẠN",
  "TÀI SẢN DÀI HẠN",
  "TỔNG CỘNG TÀI SẢN",
  "NỢ PHẢI TRẢ",
  "VỐN CHỦ SỞ HỮU",
  "TỔNG CỘNG NGUỒN VỐN",
  "Đầu tư tài chính ngắn hạn",
  "Đầu tư tài chính dài hạn",
  "Hàng tồn kho",
  "Lợi nhuận sau thuế thu nhập doanh nghiệp"
)

data_taichinh <- data %>%
    filter(`CHỈ TIÊU` %in% cac_chi_tieu_can_chon)

print(data_taichinh)
## # A tibble: 10 × 11
##    `CHỈ TIÊU`         `2015`  `2016`  `2017`  `2018`  `2019`
##    <chr>               <dbl>   <dbl>   <dbl>   <dbl>   <dbl>
##  1 TÀI SẢN NGẮN HẠN  1.90e13 2.19e13 1.61e13 1.84e13 1.90e13
##  2 Đầu tư tài chính… 2.62e12 3.47e12 4.38e12 5.57e12 6.71e12
##  3 Hàng tồn kho      5.27e12 4.55e12 1.02e12 1.34e12 1.28e12
##  4 TÀI SẢN DÀI HẠN   7.09e12 7.92e12 8.94e12 1.14e13 1.44e13
##  5 Đầu tư tài chính… 7.28e11 8.26e11 1.78e12 2.20e12 2.50e12
##  6 TỔNG CỘNG TÀI SẢN 2.60e13 2.98e13 2.50e13 2.98e13 3.34e13
##  7 NỢ PHẢI TRẢ       1.59e13 1.84e13 1.18e13 1.50e13 1.66e13
##  8 VỐN CHỦ SỞ HỮU    1.02e13 1.14e13 1.32e13 1.48e13 1.68e13
##  9 TỔNG CỘNG NGUỒN … 2.60e13 2.98e13 2.50e13 2.98e13 3.34e13
## 10 Lợi nhuận sau th… 2.44e12 2.58e12 3.53e12 3.23e12 3.91e12
## # ℹ 5 more variables: `2020` <dbl>, `2021` <dbl>,
## #   `2022` <dbl>, `2023` <dbl>, `2024` <dbl>

Kỹ thuật:

1. Tạo vector cac_chi_tieu_can_chon chứa danh sách các chỉ tiêu tài chính cần lọc, bao gồm tài sản, nợ, vốn và lợi nhuận.

14. Gọi data_taichinh <- data %>% để bắt đầu xử lý dữ liệu gốc và lưu kết quả mới vào biến data_taichinh.

15. Dùng filter() để lọc các hàng trong cột CHỈ TIÊU sao cho chỉ giữ lại những giá trị có trong danh sách cac_chi_tieu_can_chon.

17. Gọi print(data_taichinh) để in kết quả lọc ra màn hình, giúp kiểm tra dữ liệu đã chọn.

Ý nghĩa thống kê: Câu lệnh này giúp trích xuất tập con dữ liệu chỉ bao gồm các chỉ tiêu tài chính quan trọng, phục vụ cho việc phân tích cấu trúc tài sản, nguồn vốn và khả năng sinh lời của doanh nghiệp.

Hoán vị dữ liệu (đưa Năm về hàng)

# 1. Lấy cột `CHỈ TIÊU` làm tên hàng (rownames)
data_temp <- data_taichinh %>%
  tibble::column_to_rownames(var = "CHỈ TIÊU")

# 2. Hoán vị (Transpose) dữ liệu
data_transposed_matrix <- t(data_temp)

# 3. Chuyển lại thành data frame
data_taichinh <- as.data.frame(data_transposed_matrix) 

# 4. Chuyển tên hàng (năm) thành một cột 'Nam'
data_taichinh <- data_taichinh %>%  # 
  tibble::rownames_to_column(var = "Nam")

# 5. Chuyển đổi kiểu dữ liệu
data_taichinh <- data_taichinh %>%  
  mutate(
    Nam = as.integer(Nam),
    across(-Nam, as.numeric)
  )

Kỹ thuật:

2. Dùng column_to_rownames(var = “CHỈ TIÊU”) để chuyển cột “CHỈ TIÊU” thành tên hàng (rownames).

6. Dùng hàm t() để hoán vị dữ liệu (transpose), giúp đổi hàng thành cột và ngược lại.

9. Dùng as.data.frame() để chuyển ma trận vừa hoán vị thành data frame.

12. Dùng rownames_to_column(var = “Nam”) để chuyển tên hàng (năm) thành một cột dữ liệu mới có tên là Nam.

16. Dùng mutate() để chuyển kiểu dữ liệu: biến Nam sang kiểu số nguyên (integer) và toàn bộ các cột còn lại sang kiểu số (numeric).

Ý nghĩa thống kê: Chuỗi lệnh này chuẩn hóa cấu trúc dữ liệu tài chính, chuyển từ dạng dọc (long) sang dạng ngang (wide), phù hợp cho phân tích chuỗi thời gian. Mỗi hàng tương ứng với một năm, còn mỗi cột biểu diễn một chỉ tiêu tài chính (tài sản, vốn, lợi nhuận…).

Chuẩn hóa đơn vị (sang ngàn VNĐ)

# Áp dụng phép chia cho 1000 lên bộ data_taichinh
library(dplyr)

data_taichinh <- data_taichinh %>%
  mutate(across(where(is.numeric), ~ .x / 1000),
Nam = as.numeric(Nam) * 1000 
)

Kỹ thuật:

2. Gọi library(dplyr) để nạp thư viện dplyr, phục vụ cho các thao tác xử lý dữ liệu.

4. Gọi data_taichinh <- data_taichinh %>% để bắt đầu chuỗi xử lý trên bộ dữ liệu tài chính.

5. Dùng mutate(across(where(is.numeric), ~ .x / 1000)) để chia toàn bộ các cột số học cho 1000, giúp quy đổi đơn vị (từ đồng sang nghìn đồng).

6. Dòng Nam = as.numeric(Nam) * 1000 đảm bảo cột năm được ép kiểu số và nhân lại 1000 (tránh bị chia nhầm trong bước trên).

Ý nghĩa thống kê: Câu lệnh này giúp chuẩn hóa đơn vị đo trong bộ dữ liệu tài chính, giúp các chỉ tiêu có cùng thang giá trị, dễ đọc và thuận tiện cho việc so sánh, tính toán và trực quan hóa. Việc quy đổi đơn vị còn giúp tránh sai lệch trong biểu đồ hoặc thống kê mô tả khi các biến có giá trị quá lớn.

Kiểm tra lại bộ dữ liệu mới có bị thiếu hay trùng dữ liệu không

sum(is.na(data_taichinh))
sum(duplicated(data_taichinh))
## [1] 0
## [1] 0

Kỹ thuật:

1. sum(is.na(data_taichinh)) đếm tổng số giá trị bị thiếu (NA) trong toàn bộ dữ liệu.

2. sum(duplicated(data_taichinh)) đếm số dòng bị trùng lặp.

Ý nghĩa thống kê: Hai kết quả [1] 0 cho thấy không có dữ liệu bị thiếu hoặc bị trùng trong bảng.

Tạo biến tỷ lệ nợ/ tổng tài sản

# Dùng mutate() và tên cột dài (với dấu backtick ``)
data_taichinh <- data_taichinh %>%
  mutate(
    # Tỷ số 1: Tỷ lệ Nợ trên Tổng Tài sản (Debt Ratio)
    `Tỷ lệ Nợ trên TTS` = (`NỢ PHẢI TRẢ` / `TỔNG CỘNG TÀI SẢN`) * 100)

Kỹ thuật:

2. Gọi data_taichinh <- data_taichinh %>% để bắt đầu chuỗi xử lý dữ liệu trên bảng tài chính.

3. Dùng mutate() để tạo thêm một biến mới vào bộ dữ liệu.

Ý nghĩa thống kê: Tạo ra biến mới ‘Tỷ lệ Nợ trên TTS’

Tạo biến ROA

# Tỷ suất sinh lời trên tài sản (ROA)
data_taichinh <- data_taichinh %>%
  mutate(
    `ROA` = (`Lợi nhuận sau thuế thu nhập doanh nghiệp` / `TỔNG CỘNG TÀI SẢN`) * 100
  )

Kỹ thuật:

2. Gọi data_taichinh <- data_taichinh %>% để bắt đầu chuỗi xử lý dữ liệu trên bảng tài chính.

3. Dùng mutate() để tạo thêm biến mới vào bộ dữ liệu.

Ý nghĩa: Tạo ra biến mới ‘ROA’

Tạo biến ROE

# Dùng mutate() để tạo cột mới `ROE`
data_taichinh <- data_taichinh %>%
  mutate(
    `ROE` = (`Lợi nhuận sau thuế thu nhập doanh nghiệp` / `VỐN CHỦ SỞ HỮU`) * 100
  )

Kỹ thuật:

2. Gọi data_taichinh <- data_taichinh %>% để bắt đầu chuỗi xử lý dữ liệu trên bảng tài chính.

3. Dùng mutate() để tạo thêm biến mới vào bộ dữ liệu.

Ý nghĩa thống kê: Tạo ra biến mới ‘ROE’

Tạo biến tăng trưởng lợi nhuận

data_taichinh <- data_taichinh %>%
  arrange(Nam) %>% 
  mutate(
    `Tăng trưởng LNST (%)` = (
      (`Lợi nhuận sau thuế thu nhập doanh nghiệp` -
         lag(`Lợi nhuận sau thuế thu nhập doanh nghiệp`)) /
         lag(`Lợi nhuận sau thuế thu nhập doanh nghiệp`)
    ) * 100
  )

Kỹ thuật:

1. Gọi data_taichinh <- data_taichinh %>% — bắt đầu chuỗi xử lý dữ liệu.

2. Dùng arrange(Nam) để sắp xếp dữ liệu theo thứ tự năm tăng dần, đảm bảo tính đúng thứ tự thời gian.

3. Dùng mutate() để tạo thêm biến mới trong bảng dữ liệu.

Ý nghĩa thống kê: tạo ra biến mới ‘Tăng trưởng LNST (%)’

Mã hóa tăng trưởng lợi nhuận

data_taichinh <- data_taichinh %>%
  mutate(
    `Tình hình Tăng trưởng` = case_when(
      `Tăng trưởng LNST (%)` > 0  ~ "Tăng trưởng",
      `Tăng trưởng LNST (%)` < 0  ~ "Suy giảm",
      `Tăng trưởng LNST (%)` == 0 ~ "Không đổi",
      TRUE ~ "N/A" # Dành cho năm đầu tiên (NA)
    )
  )

Kỹ thuật:

1. Gọi data_taichinh <- data_taichinh %>% — bắt đầu chuỗi xử lý dữ liệu.

2. Dùng mutate() để tạo thêm cột mới trong bảng dữ liệu.

Ý nghĩa thống kê: Tạo ra biến mới “Tình hình Tăng trưởng”.

Tạo biến mới - tỷ trọng tài sản ngắn hạn

data_taichinh <- data_taichinh %>%
  mutate(
    `TyTrong_TSNH (%)` = (`TÀI SẢN NGẮN HẠN` / `TỔNG CỘNG TÀI SẢN`) * 100
  )

Kỹ thuật:

1. Gọi data_taichinh <- data_taichinh %>% — bắt đầu chuỗi xử lý dữ liệu.

2. Dùng mutate() để tạo thêm cột mới trong bảng dữ liệu.

Ý nghĩa thống kê: Tạo ra biến mới ‘TyTrong_TSNH (%)’

Phân nhóm giai đoạn

data_taichinh <- data_taichinh %>%
  mutate(
    GiaiDoan = ifelse(
      floor(Nam) <= 2019,
      "Giai đoạn 1 (2015–2019)",
      "Giai đoạn 2 (2020–2024)"
    )
  )

Kỹ thuật:

1. Gọi data_taichinh <- data_taichinh %>% — bắt đầu chuỗi xử lý dữ liệu.

2. Dùng mutate() để tạo thêm biến mới trong bảng dữ liệu.

3. Sử dụng ifelse() để phân chia dữ liệu theo giai đoạn thời gian.

Ý nghĩa thống kê: Tạo ra biến mới ‘GiaiDoan’

Thực hiện các thống kê cơ bản FPT

Thống kê mô tả lợi nhuận

data_taichinh %>%
  summarise(
    TrungBinh = mean(`Lợi nhuận sau thuế thu nhập doanh nghiệp`, na.rm = TRUE),
    TrungVi = median(`Lợi nhuận sau thuế thu nhập doanh nghiệp`, na.rm = TRUE),
    DoLechChuan = sd(`Lợi nhuận sau thuế thu nhập doanh nghiệp`, na.rm = TRUE),
    GiaTriNhoNhat = min(`Lợi nhuận sau thuế thu nhập doanh nghiệp`, na.rm = TRUE),
    GiaTriLonNhat = max(`Lợi nhuận sau thuế thu nhập doanh nghiệp`, na.rm = TRUE)
  )
    TrungBinh| TrungVi| DoLechChuan| GiaTriNhoNhat| GiaTriLonNhat||————-:|————-:|————-:|————-:|————-:|| 4.916.746.087| 4.167.728.692| 2.330.818.533| 2.438.084.765| 9.427.422.530|

Kỹ thuật:

1. Gọi data_taichinh %>% — bắt đầu chuỗi xử lý dữ liệu.

2. Dùng summarise() để tính toán các chỉ số thống kê tổng hợp.

Ý nghĩa thống kê:

Kết quả cho thấy lợi nhuận sau thuế của doanh nghiệp dao động đáng kể: trung bình đạt khoảng 4.917 tỷ đồng, trung vị là 4.168 tỷ đồng, độ lệch chuẩn lên tới 2.331 tỷ đồng, cho thấy mức biến động lợi nhuận khá lớn giữa các năm. Giá trị nhỏ nhất là 2.438 tỷ đồng và cao nhất 9.427 tỷ đồng.

Thống kê mô tả chi tiết cho ROA

data_taichinh %>%
  summarise(
    TrungBinh_ROA = mean(ROA, na.rm = TRUE),
    TrungVi_ROA = median(ROA, na.rm = TRUE),
    DoLechChuan_ROA = sd(ROA, na.rm = TRUE),
    Min_ROA = min(ROA, na.rm = TRUE),
    Max_ROA = max(ROA, na.rm = TRUE)
  )
TrungBinh_ROA| TrungVi_ROA| DoLechChuan_ROA| Min_ROA| Max_ROA||————-:|———–:|—————:|——-:|——-:|| 11.38| 11.29| 1.79| 8.63| 14.11|

Kỹ thuật:

1. Gọi data_taichinh %>% — bắt đầu chuỗi xử lý dữ liệu.

2. Dùng summarise() để tính các chỉ số thống kê mô tả cho biến ROA.

Ý nghĩa thống kê:

Kết quả cho thấy tỷ suất sinh lời trên tài sản (ROA) trung bình của doanh nghiệp đạt 11.38%, với trung vị 11.29%, phản ánh hiệu quả sử dụng tài sản khá ổn định. Độ lệch chuẩn chỉ 1.79%, cho thấy biến động lợi nhuận trên tài sản thấp qua các năm. ROA dao động từ 8.63% đến 14.11%, chứng tỏ doanh nghiệp duy trì hiệu quả sinh lời ổn định và bền vững trong giai đoạn quan sát.

Thống kê mô tả chi tiết cho ROE

data_taichinh %>%
  summarise(
    TrungBinh_ROE = mean(ROE, na.rm = TRUE),
    TrungVi_ROE = median(ROE, na.rm = TRUE),
    DoLechChuan_ROE = sd(ROE, na.rm = TRUE),
    Min_ROE = min(ROE, na.rm = TRUE),
    Max_ROE = max(ROE, na.rm = TRUE)
  )
TrungBinh_ROE| TrungVi_ROE| DoLechChuan_ROE| Min_ROE| Max_ROE||————-:|———–:|—————:|——-:|——-:|| 24.5| 24.46| 1.67| 21.89| 26.65|

Kỹ thuật:

1. Gọi data_taichinh %>% — bắt đầu chuỗi xử lý dữ liệu.

2. Dùng summarise() để tính các chỉ số thống kê mô tả cho biến ROE.

Ý nghĩa thống kê:

Kết quả cho thấy ROE trung bình đạt 24.50% và trung vị 24.46%, chứng tỏ hiệu suất sinh lời trên vốn chủ sở hữu khá ổn định. Độ lệch chuẩn chỉ 1.67%, cho thấy biến động thấp giữa các năm. Biên độ ROE dao động từ 21.89% đến 26.65%, phản ánh doanh nghiệp duy trì năng lực tạo lợi nhuận cao và ổn định trên vốn góp, là dấu hiệu tích cực về hiệu quả tài chính và khả năng quản trị vốn.

Thống kê mô tả chi tiết cho tỷ lệ nợ

data_taichinh %>%
  summarise(
    TrungBinh = mean(`Tỷ lệ Nợ trên TTS`, na.rm = TRUE),
    TrungVi = median(`Tỷ lệ Nợ trên TTS`, na.rm = TRUE),
    DoLechChuan = sd(`Tỷ lệ Nợ trên TTS`, na.rm = TRUE),
    Min = min(`Tỷ lệ Nợ trên TTS`, na.rm = TRUE),
    Max = max(`Tỷ lệ Nợ trên TTS`, na.rm = TRUE)
  )
TrungBinh| TrungVi| DoLechChuan| Min| Max||———:|——-:|———–:|—–:|—–:|| 53.68| 50.64| 5.38| 47.05| 61.63|

Kỹ thuật:

1. Gọi data_taichinh %>% — bắt đầu chuỗi xử lý dữ liệu.

2. Dùng summarise() để tính các chỉ số thống kê mô tả cho tỷ lệ Nợ trên Tổng Tài sản (TTS).

Ý nghĩa thống kê:

Kết quả cho thấy tỷ lệ nợ trên tổng tài sản của doanh nghiệp trung bình đạt 53.68%, với trung vị 50.64%, phản ánh mức sử dụng đòn bẩy tài chính tương đối cao nhưng cân đối. Độ lệch chuẩn 5.38% cho thấy tỷ lệ này biến động ở mức vừa phải giữa các năm. Tỷ lệ thấp nhất 47.05% và cao nhất 61.63%, chứng tỏ doanh nghiệp duy trì cơ cấu vốn ổn định, không phụ thuộc quá mức vào nợ vay nhưng vẫn tận dụng hợp lý nguồn vốn bên ngoài để tăng trưởng.

Thống kê mô tả chi tiết cho tổng tài sản

data_taichinh %>%
  summarise(
    TrungBinh = mean(`TỔNG CỘNG TÀI SẢN`, na.rm = TRUE),
    TrungVi = median(`TỔNG CỘNG TÀI SẢN`, na.rm = TRUE),
    DoLechChuan = sd(`TỔNG CỘNG TÀI SẢN`, na.rm = TRUE),
    Min = min(`TỔNG CỘNG TÀI SẢN`, na.rm = TRUE),
    Max = max(`TỔNG CỘNG TÀI SẢN`, na.rm = TRUE)
  )
     TrungBinh| TrungVi| DoLechChuan| Min| Max||————–:|————–:|————–:|————–:|——-:|| 42.339.524.975| 37.564.243.749| 16.257.254.828| 24.999.676.896| 7.2e+10|

Kỹ thuật:

1. Gọi data_taichinh %>% — bắt đầu chuỗi xử lý dữ liệu.

2. Dùng summarise() để tính các thống kê mô tả cho chỉ tiêu “Tổng cộng tài sản”.

Ý nghĩa thống kê:

Kết quả cho thấy tổng tài sản trung bình đạt khoảng 42.340 tỷ đồng, trong khi trung vị 37.564 tỷ đồng, cho thấy quy mô tài sản có xu hướng tăng dần và xuất hiện vài năm có giá trị vượt trội. Độ lệch chuẩn 16.257 tỷ đồng phản ánh sự chênh lệch khá lớn giữa các năm, thể hiện quá trình mở rộng đầu tư và tăng quy mô hoạt động của doanh nghiệp. Biên độ dao động từ 24.999 tỷ đồng đến 72.000 tỷ đồng, chứng minh doanh nghiệp có quá trình tích lũy và mở rộng tài sản rõ rệt trong giai đoạn nghiên cứu.

Thống kê trung bình nhóm tài sản

data_taichinh %>%
  summarise(
    across(
      c(`TÀI SẢN NGẮN HẠN`, `TÀI SẢN DÀI HẠN`, `TỔNG CỘNG TÀI SẢN`),
      mean,
      na.rm = TRUE
    )
  )
TÀI SẢN NGẮN HẠN| TÀI SẢN DÀI HẠN| TỔNG CỘNG TÀI SẢN||—————-:|—————:|—————–:|| 26.822.314.139| 15.517.210.836| 42.339.524.975|

Kỹ thuật:

1. Gọi data_taichinh %>% — bắt đầu chuỗi xử lý dữ liệu.

2. Dùng summarise() để tổng hợp dữ liệu theo các biến được chọn.

3. across() — áp dụng cùng một hàm cho nhiều cột cùng lúc.

Ý nghĩa thống kê:

Kết quả cho thấy trung bình giai đoạn, doanh nghiệp có tài sản ngắn hạn khoảng 26.822 tỷ đồng, tài sản dài hạn 15.517 tỷ đồng, và tổng tài sản 42.339 tỷ đồng. Cơ cấu này cho thấy tỷ trọng tài sản ngắn hạn chiếm ưu thế (khoảng 63%), phản ánh đặc trưng của doanh nghiệp có tính thanh khoản cao, chủ yếu đầu tư vào các tài sản lưu động phục vụ hoạt động kinh doanh ngắn hạn, trong khi vẫn duy trì một phần tài sản dài hạn để đảm bảo phát triển bền vững.

Thống kê trung bình nhóm nguồn vốn

data_taichinh %>%
  summarise(
    across(
      c(`NỢ PHẢI TRẢ`, `VỐN CHỦ SỞ HỮU`, `TỔNG CỘNG NGUỒN VỐN`),
      mean,
      na.rm = TRUE
    )
  )
   NỢ PHẢI TRẢ| VỐN CHỦ SỞ HỮU| TỔNG CỘNG NGUỒN VỐN||————–:|————–:|——————-:|| 22.591.192.369| 19.748.332.606| 42.339.524.975|

Kỹ thuật:

1. Gọi data_taichinh %>% — bắt đầu chuỗi xử lý dữ liệu.

2. Dùng summarise() để tổng hợp dữ liệu theo các biến được chọn.

3. across() — áp dụng cùng một hàm cho nhiều cột cùng lúc.

Ý nghĩa thống kê:

Kết quả cho thấy trung bình trong giai đoạn phân tích, doanh nghiệp có nợ phải trả khoảng 22.591 tỷ đồng, vốn chủ sở hữu đạt 19.748 tỷ đồng, và tổng nguồn vốn 42.339 tỷ đồng. Điều này cho thấy nguồn vốn được phân bổ khá cân đối, trong đó nợ chiếm khoảng 53% tổng nguồn vốn, phản ánh mức độ sử dụng đòn bẩy tài chính hợp lý. Cấu trúc vốn này giúp doanh nghiệp duy trì khả năng thanh toán và tối ưu chi phí vốn, đồng thời đảm bảo sự an toàn tài chính trong dài hạn.

Thống kê tổng lợi nhuận và trung bình tài sản

data_taichinh %>%
  summarise(
    TongLoiNhuan_10Nam = sum(`Lợi nhuận sau thuế thu nhập doanh nghiệp`, na.rm = TRUE),
    TaiSan_TrungBinh = mean(`TỔNG CỘNG TÀI SẢN`, na.rm = TRUE)
  )
TongLoiNhuan_10Nam| TaiSan_TrungBinh||——————:|—————-:|| 49.167.460.874| 42.339.524.975|

Kỹ thuật:

1. Gọi data_taichinh %>% — khởi tạo chuỗi xử lý dữ liệu.

2. Dùng summarise() để tính toán các chỉ số tổng hợp.

Ý nghĩa thống kê:

Kết quả cho thấy tổng lợi nhuận sau thuế trong 10 năm đạt khoảng 49.167 tỷ đồng, trong khi tổng tài sản bình quân ở mức 42.339 tỷ đồng. Điều này phản ánh doanh nghiệp duy trì hiệu quả sinh lời ổn định trên nền tảng tài sản lớn, cho thấy hoạt động đầu tư và sử dụng vốn được triển khai hiệu quả trong dài hạn, góp phần tăng trưởng bền vững và nâng cao giá trị doanh nghiệp.

Bảng thống kê Min/Max cho nhóm tài sản

ket_qua <- data_taichinh %>%
  summarise(
    across(
      c(`TÀI SẢN NGẮN HẠN`, `TÀI SẢN DÀI HẠN`),
      list(Min = min, Max = max),
      na.rm = TRUE
    )
  )

# Đổi tên ngắn hơn
colnames(ket_qua) <- c("TSNH_Min", "TSNH_Max", "TSDH_Min", "TSDH_Max")
print(ket_qua)
##      TSNH_Min    TSNH_Max   TSDH_Min    TSDH_Max
## 1 16059937821 45535942846 7086579408 26464052832

Kỹ thuật:

1. ket_qua <- data_taichinh %>% — bắt đầu chuỗi xử lý và lưu kết quả vào biến ket_qua.

2. Dùng summarise() để tổng hợp dữ liệu.

3. across() — áp dụng nhiều hàm cho nhiều cột cùng lúc.

4. Chọn hai cột TÀI SẢN NGẮN HẠN và TÀI SẢN DÀI HẠN làm đối tượng tính toán.

5. Dùng list(Min = min, Max = max) — tạo hai hàm: giá trị nhỏ nhất và lớn nhất.

6. na.rm = TRUE — bỏ qua các giá trị NA khi tính toán.

10. Dùng colnames() để đổi tên các cột kết quả thành dạng ngắn gọn.

11. print(ket_qua) — in bảng kết quả gọn, không bị tràn ra ngoài trang.

Ý nghĩa thống kê:

Kết quả cho thấy trong giai đoạn quan sát, tài sản ngắn hạn dao động từ 16.060 tỷ đến 45.536 tỷ đồng, trong khi tài sản dài hạn biến động từ 7.086 tỷ đến 26.464 tỷ đồng. Điều này phản ánh quy mô tài sản của doanh nghiệp tăng trưởng mạnh theo thời gian, đặc biệt ở nhóm tài sản ngắn hạn – cho thấy sự mở rộng vốn lưu động và khả năng thanh khoản được củng cố, góp phần tạo nền tảng tài chính vững chắc cho hoạt động đầu tư và kinh doanh dài hạn.

Thống kê trung bình nhóm chỉ số hiệu suất

data_taichinh %>%
  summarise(
    across(
      c(ROA, ROE, `Tăng trưởng LNST (%)`),
      mean,
      na.rm = TRUE
    )
  )
  ROA| ROE| Tăng trưởng LNST (%)||—–:|—-:|——————–:|| 11.38| 24.5| 16.85|

Kỹ thuật:

1. data_taichinh %>% — gọi bộ dữ liệu và bắt đầu chuỗi xử lý bằng toán tử pipe.

2. Dùng summarise() để tạo bảng tổng hợp dữ liệu.

3. across() — áp dụng cùng một hàm cho nhiều cột được chọn.

4. Chọn ba cột gồm ROA, ROE, và Tăng trưởng LNST (%) để tính giá trị trung bình.

5. Dùng hàm mean để tính giá trị trung bình của từng chỉ tiêu.

6. na.rm = TRUE — loại bỏ các giá trị thiếu (NA) khi tính toán.

Ý nghĩa thống kê:

Kết quả cho thấy trung bình trong giai đoạn nghiên cứu, ROA đạt 11.38%, ROE đạt 24.50%, và tốc độ tăng trưởng LNST trung bình 16.85%/năm. Điều này phản ánh doanh nghiệp có hiệu quả sử dụng tài sản và vốn chủ sở hữu cao, đồng thời duy trì được đà tăng trưởng lợi nhuận ổn định. Mức ROE gấp đôi ROA cho thấy đòn bẩy tài chính được tận dụng hiệu quả, nhưng vẫn nằm trong ngưỡng an toàn tài chính.

Thống kê các năm có ROE > 25%

data_taichinh %>%
  filter(ROE > 25) %>%
  select(Nam, ROE, `Lợi nhuận sau thuế thu nhập doanh nghiệp`)
  Nam| ROE| Lợi nhuận sau thuế thu nhập doanh nghiệp||—–:|—–:|—————————————-:|| 2.017| 26.65| 3.528.113.914|| 2.022| 25.60| 6.491.343.454|| 2.023| 26.02| 7.788.049.740|| 2.024| 26.39| 9.427.422.530|

Kỹ thuật:

1. data_taichinh %>% — gọi bộ dữ liệu và bắt đầu xử lý.

2. filter(ROE > 25) — lọc các dòng có ROE lớn hơn 25%.

3. select() — chọn hiển thị ba cột: Nam, ROE, và Lợi nhuận sau thuế thu nhập doanh nghiệp.

Ý nghĩa thống kê:

Dữ liệu cho thấy các năm 2017, 2022, 2023 và 2024 đều có ROE trên 25%, tương ứng với mức lợi nhuận sau thuế tăng mạnh qua từng năm, đặc biệt đạt đỉnh vào 2024 (khoảng 9.427 tỷ đồng). Điều này phản ánh giai đoạn doanh nghiệp mở rộng quy mô vốn và đầu tư hiệu quả, tận dụng tốt nguồn vốn chủ sở hữu để tạo ra lợi nhuận vượt trội, cho thấy sức khỏe tài chính mạnh và khả năng sinh lời bền vững.

Thống kê các năm có lợi nhuận tăng trưởng

data_taichinh %>%
  filter(`Tăng trưởng LNST (%)` > 0) %>%
  select(Nam, `Lợi nhuận sau thuế thu nhập doanh nghiệp`, `Tăng trưởng LNST (%)`)
  Nam| Lợi nhuận sau thuế thu nhập doanh nghiệp| Tăng trưởng LNST (%)||—–:|—————————————-:|——————–:|| 2.016| 2.575.690.845| 5.64|| 2.017| 3.528.113.914| 36.98|| 2.019| 3.911.712.167| 20.96|| 2.020| 4.423.745.218| 13.09|| 2.021| 5.349.301.100| 20.92|| 2.022| 6.491.343.454| 21.35|| 2.023| 7.788.049.740| 19.98|| 2.024| 9.427.422.530| 21.05|

Kỹ thuật:

1. data_taichinh %>% — bắt đầu chuỗi xử lý dữ liệu.

2. filter(‘Tăng trưởng LNST (%)’ > 0) — lọc các năm có lợi nhuận tăng trưởng dương.

3. select() — chọn hiển thị 3 cột:

Ý nghĩa thống kê:

Kết quả cho thấy doanh nghiệp liên tục đạt tăng trưởng lợi nhuận dương trong các năm từ 2016 đến 2024, thể hiện khả năng duy trì hiệu quả kinh doanh ổn định. Đặc biệt, năm 2017 ghi nhận mức tăng đột biến 36,98%, chứng tỏ doanh nghiệp có giai đoạn mở rộng mạnh mẽ hoặc cải thiện biên lợi nhuận vượt trội. Giai đoạn sau 2020, tốc độ tăng trưởng ổn định quanh mức 20%/năm, phản ánh hiệu quả quản trị và năng lực duy trì lợi nhuận bền vững trong môi trường thị trường có thể biến động.

Bảng lợi nhuận trung bình theo giai đoạn

data_taichinh %>%
  group_by(GiaiDoan) %>% # Phân nhóm dữ liệu theo cột GiaiDoan
  summarise(
    LNST_TrungBinh = mean(`Lợi nhuận sau thuế thu nhập doanh nghiệp`, na.rm = TRUE),
    LNST_TrungVi = median(`Lợi nhuận sau thuế thu nhập doanh nghiệp`, na.rm = TRUE)
  )

|GiaiDoan | LNST_TrungBinh| LNST_TrungVi||:———————–|————–:|————-:||Giai đoạn 1 (2015–2019) | 3.137.519.767| 3.233.997.141||Giai đoạn 2 (2020–2024) | 6.695.972.408| 6.491.343.454|

Kỹ thuật:

1. data_taichinh %>% — gọi dữ liệu gốc để xử lý.

2. group_by(GiaiDoan) — nhóm dữ liệu theo giai đoạn (2015–2019, 2020–2024).

3. summarise() — tạo bảng tổng hợp cho từng nhóm.

Ý nghĩa thống kê:

Kết quả cho thấy lợi nhuận sau thuế trung bình tăng mạnh từ 3.137 tỷ đồng (giai đoạn 2015–2019) lên 6.696 tỷ đồng (giai đoạn 2020–2024), tức là gần gấp đôi so với giai đoạn trước. Cả giá trị trung bình và trung vị đều tăng, chứng tỏ doanh nghiệp không chỉ tăng quy mô lợi nhuận mà còn duy trì sự ổn định trong tăng trưởng, phản ánh hiệu quả hoạt động kinh doanh và năng lực tài chính được cải thiện rõ rệt qua thời gian.

Bảng ROA/ROE trung bình theo giai đoạn

data_taichinh %>%
  group_by(GiaiDoan) %>%
  summarise(
    ROA_TrungBinh = mean(ROA, na.rm = TRUE),
    ROE_TrungBinh = mean(ROE, na.rm = TRUE)
  )

|GiaiDoan | ROA_TrungBinh| ROE_TrungBinh||:———————–|————-:|————-:||Giai đoạn 1 (2015–2019) | 10.94| 23.65||Giai đoạn 2 (2020–2024) | 11.83| 25.35|

Kỹ thuật:

1. data_taichinh %>% — gọi dữ liệu gốc để xử lý.

2. group_by(GiaiDoan) — nhóm dữ liệu theo giai đoạn (2015–2019, 2020–2024).

3. summarise() — tạo bảng tổng hợp cho từng nhóm.

Ý nghĩa thống kê:

ROA trung bình tăng nhẹ từ 10,94% lên 11,83%, cho thấy doanh nghiệp cải thiện hiệu quả khai thác tài sản trong giai đoạn sau. Trong khi đó, ROE tăng từ 23,65% lên 25,35%, phản ánh khả năng sinh lời trên vốn chủ sở hữu tiếp tục được củng cố. Sự tăng đồng thời của cả hai chỉ số này cho thấy FPT không chỉ duy trì mà còn tối ưu hóa năng lực sinh lợi, đồng thời quản trị tài sản và vốn hiệu quả hơn trong giai đoạn 2020–2024.

Bảng tổng lợi nhuận theo giai đoạn

data_taichinh %>%
  group_by(GiaiDoan) %>%
  summarise(
    TongLoiNhuan = sum(`Lợi nhuận sau thuế thu nhập doanh nghiệp`, na.rm = TRUE)
  )

|GiaiDoan | TongLoiNhuan||:———————–|————–:||Giai đoạn 1 (2015–2019) | 15.687.598.833||Giai đoạn 2 (2020–2024) | 33.479.862.042|

Kỹ thuật:

1. data_taichinh %>% — gọi dữ liệu gốc để xử lý.

2. group_by(GiaiDoan) — nhóm dữ liệu theo giai đoạn (2015–2019, 2020–2024).

3. summarise() — tạo bảng tổng hợp cho từng nhóm.

Ý nghĩa thống kê:

Tổng lợi nhuận sau thuế của FPT trong giai đoạn 2020–2024 đạt 33.479 tỷ đồng, gần gấp đôi giai đoạn 2015–2019 (15.687 tỷ đồng). Điều này cho thấy doanh nghiệp không chỉ tăng quy mô hoạt động mà còn nâng cao đáng kể hiệu quả sinh lời trong giai đoạn sau. Kết quả này phản ánh sự mở rộng mạnh mẽ của FPT trong lĩnh vực công nghệ và dịch vụ số, đồng thời khẳng định năng lực quản trị, chiến lược đầu tư và hiệu suất kinh doanh vượt trội trong bối cảnh thị trường cạnh tranh ngày càng cao.

Bảng tỷ lệ nợ theo giai đoạn

data_taichinh %>%
  group_by(GiaiDoan) %>%
  summarise(
    TyLeNo_TrungBinh = mean(`Tỷ lệ Nợ trên TTS`, na.rm = TRUE),
    TyLeNo_CaoNhat = max(`Tỷ lệ Nợ trên TTS`, na.rm = TRUE)
  )

|GiaiDoan | TyLeNo_TrungBinh| TyLeNo_CaoNhat||:———————–|—————-:|————–:||Giai đoạn 1 (2015–2019) | 53.92| 61.63||Giai đoạn 2 (2020–2024) | 53.43| 60.11|

Kỹ thuật:

1. data_taichinh %>% — gọi dữ liệu gốc để xử lý.

2. group_by(GiaiDoan) — nhóm dữ liệu theo giai đoạn (2015–2019, 2020–2024).

3. summarise() — tạo bảng tổng hợp cho từng nhóm.

Ý nghĩa thống kê:

Kết quả cho thấy tỷ lệ nợ trên tổng tài sản trung bình của FPT giảm nhẹ từ 53,92% xuống 53,43% giữa hai giai đoạn. Mức giảm tuy nhỏ nhưng phản ánh xu hướng giảm dần đòn bẩy tài chính, cho thấy doanh nghiệp dần chủ động hơn trong việc sử dụng vốn chủ sở hữu và kiểm soát nợ vay. Mặt khác, tỷ lệ nợ cao nhất cũng giảm từ 61,63% xuống 60,11%, củng cố nhận định rằng FPT đang duy trì cấu trúc tài chính an toàn và ổn định hơn trong giai đoạn gần đây.

Bảng thống kê cơ cấu tài sản theo giai đoạn

data_taichinh %>%
  group_by(GiaiDoan) %>%
  summarise(
    TSNH_TrungBinh = mean(`TÀI SẢN NGẮN HẠN`, na.rm = TRUE),
    TSDH_TrungBinh = mean(`TÀI SẢN DÀI HẠN`, na.rm = TRUE)
  )

|GiaiDoan | TSNH_TrungBinh| TSDH_TrungBinh||:———————–|————–:|————–:||Giai đoạn 1 (2015–2019) | 18.862.574.654| 9.943.377.080||Giai đoạn 2 (2020–2024) | 34.782.053.624| 21.091.044.591|

Kỹ thuật:

1. data_taichinh %>% — gọi dữ liệu gốc để xử lý.

2. group_by(GiaiDoan) — nhóm dữ liệu theo giai đoạn (2015–2019, 2020–2024).

3. summarise() — tạo bảng tổng hợp cho từng nhóm.

Ý nghĩa thống kê:

Cơ cấu tài sản của FPT có sự mở rộng mạnh mẽ trong giai đoạn 2020–2024. Tài sản ngắn hạn trung bình tăng từ 18.863 tỷ lên 34.782 tỷ đồng, còn tài sản dài hạn tăng gấp đôi từ 9.943 tỷ lên 21.091 tỷ đồng. Điều này phản ánh doanh nghiệp đã mở rộng quy mô hoạt động, đầu tư mạnh hơn vào tài sản cố định và hạ tầng công nghệ. Tốc độ tăng nhanh của cả hai nhóm tài sản cho thấy FPT duy trì được sự cân bằng giữa vốn lưu động và đầu tư dài hạn, góp phần củng cố nền tảng phát triển bền vững.

Bảng thống kê năm có ROA cao nhất

# filter() với điều kiện lồng
data_taichinh %>%
  filter(ROA == max(ROA, na.rm = TRUE)) %>%
  select(Nam, ROA, `Lợi nhuận sau thuế thu nhập doanh nghiệp`)
  Nam| ROA| Lợi nhuận sau thuế thu nhập doanh nghiệp||—–:|—–:|—————————————-:|| 2.017| 14.11| 3.528.113.914| Kỹ thuật:

1. data_taichinh %>% — gọi dữ liệu gốc để xử lý.

2. filter(ROA == max(ROA, na.rm = TRUE)) — lọc ra năm có ROA cao nhất trong toàn bộ dữ liệu.

3. select() — chọn hiển thị 3 cột quan trọng:

Ý nghĩa thống kê:

Năm 2017 là năm FPT đạt tỷ suất sinh lời trên tài sản (ROA) cao nhất – 14,11%, với lợi nhuận sau thuế đạt 3.528 tỷ đồng. Điều này cho thấy hiệu quả sử dụng tài sản của doanh nghiệp trong năm này đạt mức tối ưu, mỗi đồng tài sản tạo ra lợi nhuận nhiều hơn so với các năm khác.

Bảng thống kê năm có ROA thấp nhất

data_taichinh %>%
  filter(ROA == min(ROA, na.rm = TRUE)) %>%
  select(Nam, ROA, `Lợi nhuận sau thuế thu nhập doanh nghiệp`)
  Nam| ROA| Lợi nhuận sau thuế thu nhập doanh nghiệp||—–:|—-:|—————————————-:|| 2.016| 8.63| 2.575.690.845|

Kỹ thuật:

1. data_taichinh %>% — gọi dữ liệu gốc để xử lý.

2. lọc ra năm có ROA thấp nhất trong toàn bộ dữ liệu.

3. select() — chọn hiển thị 3 cột quan trọng:

Ý nghĩa thống kê:

Năm 2016 là thời điểm FPT có tỷ suất sinh lời trên tài sản (ROA) thấp nhất – chỉ đạt 8,63%, với lợi nhuận sau thuế khoảng 2.576 tỷ đồng.

Bảng thống kê trung bình nhóm đầu tư

data_taichinh %>%
  summarise(
    across(
      c(`Đầu tư tài chính ngắn hạn`, `Đầu tư tài chính dài hạn`),
      mean,
      na.rm = TRUE
    )
  )
Đầu tư tài chính ngắn hạn| Đầu tư tài chính dài hạn||————————-:|————————:|| 10.684.986.934| 2.361.111.093|

Kỹ thuật:

1. data_taichinh %>% — gọi dữ liệu để xử lý.

2. summarise() — tạo bảng tóm tắt dữ liệu.

3. across() — áp dụng cùng một hàm cho nhiều cột.

Ý nghĩa thống kê:

Kết quả cho thấy FPT duy trì trung bình đầu tư tài chính ngắn hạn khoảng 10.685 tỷ đồng, trong khi đầu tư tài chính dài hạn đạt trung bình 23.611 tỷ đồng. Tỷ trọng đầu tư dài hạn cao hơn cho thấy doanh nghiệp ưu tiên các danh mục mang tính chiến lược, ổn định và sinh lời lâu dài, chẳng hạn như góp vốn vào công ty con, mua cổ phần đối tác hoặc đầu tư vào công nghệ. Tuy vậy, vẫn duy trì phần đáng kể trong đầu tư ngắn hạn giúp đảm bảo thanh khoản và linh hoạt dòng tiền trong ngắn hạn.

Trực quan hóa data FPT

Đồ thị xu hướng lợi nhuận sau thuế (2015-2024)

ggplot(
  data_taichinh,
  aes(x = Nam, y = `Lợi nhuận sau thuế thu nhập doanh nghiệp`)
) +
  geom_line(color = "#0072B2", size = 1.2) +
  geom_point(color = "#D55E00", size = 3, shape = 21, fill = "white", stroke = 1.5) +
  scale_y_continuous(labels = scales::comma) +
  scale_x_continuous(breaks = data_taichinh$Nam) +
  labs(
    title = "Xu hướng lợi nhuận sau thuế (2015–2024)",
    x = "Năm",
    y = "Lợi nhuận (Đơn vị: ngàn VND)"
  ) +
  theme_minimal(base_size = 14, base_family = "roboto") +
  theme(
    plot.title = element_text(face = "bold", color = "#333333", hjust = 0.5),
    axis.text.x = element_text(angle = 45, hjust = 1)
  )

Kỹ thuật:

1. data_taichinh %>% — gọi dữ liệu chính để vẽ biểu đồ.

3. aes(x = Nam, y = ‘Lợi nhuận sau thuế thu nhập doanh nghiệp’) — trục hoành là năm, trục tung là lợi nhuận sau thuế.

5. geom_line() — vẽ đường nối liên tục biểu diễn xu hướng lợi nhuận qua các năm, màu xanh dương #0072B2.

6. geom_point() — đánh dấu các điểm dữ liệu trên đường bằng chấm tròn màu cam #D55E00, viền trắng để nổi bật.

7. scale_y_continuous(labels = scales::comma) — định dạng trục tung có dấu phẩy ngăn cách hàng nghìn.

9. labs() — đặt tiêu đề, tên trục X và Y.

14. theme_minimal() — áp dụng giao diện gọn nhẹ, dễ đọc.

15. theme() — tùy chỉnh lại tiêu đề in đậm, căn giữa, và xoay nhãn năm nghiêng 45° để tránh chồng chữ.

Ý nghĩa thống kê:

Biểu đồ cho thấy lợi nhuận sau thuế của FPT tăng đều qua từng năm từ 2015 đến 2024, phản ánh hiệu quả hoạt động kinh doanh tăng trưởng bền vững. Giai đoạn đầu (2015–2018) có mức lợi nhuận tăng chậm, song từ 2019 trở đi tốc độ tăng mạnh, đặc biệt giai đoạn 2021–2024 FPT ghi nhận mức bứt phá rõ rệt, đạt đỉnh hơn 9.427 tỷ đồng vào năm 2024. Xu hướng này cho thấy doanh nghiệp đã tận dụng tốt lợi thế công nghệ, mở rộng thị trường và nâng cao năng suất hoạt động, đưa hiệu quả tài chính lên mức cao nhất trong 10 năm qua.

Đồ thị lợi nhuận sau thuế theo từng năm (2015-2024)

ggplot(
  data_taichinh,
  aes(
    x = factor(Nam),
    y = `Lợi nhuận sau thuế thu nhập doanh nghiệp`
  )
) +
  geom_col(
    aes(fill = GiaiDoan),
    width = 0.6
  ) +
  scale_y_continuous(
    labels = scales::comma
  ) +
  scale_fill_manual(
    values = c(
      "Trước 2020" = "#E69F00",
      "Từ 2020"   = "#56B4E9"
    )
  ) +
  labs(
    title = "Lợi nhuận sau thuế theo từng năm (2015–2024)",
    x = "Năm",
    y = "Lợi nhuận (Đơn vị: ngàn VNĐ)",
    fill = "Giai đoạn"
  ) +
  theme_light(
    base_size = 14
  ) +
  theme(
    plot.title     = element_text(face = "bold"),
    legend.position = "top"
  )

Kỹ thuật:

1. thiết lập trục hoành là năm, trục tung là lợi nhuận sau thuế, với năm được chuyển thành factor để hiển thị dạng cột rời.

8. geom_col(aes(fill = GiaiDoan), width = 0.7) — vẽ các cột biểu thị lợi nhuận từng năm, tô màu theo giai đoạn (biến GiaiDoan).

12. scale_y_continuous(labels = scales::comma) — định dạng trục tung bằng dấu phẩy ngăn cách hàng nghìn.

15 scale_fill_manual() — chỉ định màu riêng cho từng giai đoạn

21. labs() — đặt tiêu đề biểu đồ, tên trục và chú thích phần legend.

27. theme_light() — dùng giao diện sáng, rõ nét.

30. theme() — làm tiêu đề in đậm và đưa chú thích (legend) lên phía trên biểu

Ý nghĩa thống kê:

Biểu đồ cho thấy lợi nhuận sau thuế của FPT tăng mạnh và ổn định qua từng năm trong giai đoạn 2015–2024, từ khoảng 1.380 tỷ đồng năm 2015 lên đến hơn 9.427 tỷ đồng năm 2024. Ngoại trừ giai đoạn 2018 có sự giảm nhẹ, xu hướng chung là tăng liên tục, phản ánh năng lực sinh lời bền vững và khả năng mở rộng quy mô kinh doanh hiệu quả. Đặc biệt, từ năm 2020 trở đi, tốc độ tăng lợi nhuận rõ rệt hơn, cho thấy FPT bước vào giai đoạn tăng trưởng cao, hưởng lợi từ chuyển đổi số, xuất khẩu phần mềm và mảng dịch vụ công nghệ toàn cầu.

Đồ thị xu hướng ROA và ROE (2015-2024)

data_roa_roe_long <- data_taichinh %>%
  select(Nam, ROA, ROE) %>%
  pivot_longer(
    cols = -Nam,
    names_to = "ChiSo",
    values_to = "GiaTri"
  )
ggplot(data_roa_roe_long, aes(x = Nam, y = GiaTri, color = ChiSo, group = ChiSo)) +
  geom_line(size = 1.2) +
  geom_point(size = 3, shape = 21, fill = "white", stroke = 1.5) +
  geom_text(aes(label = round(GiaTri, 1)), vjust = -1.5, size = 3.5) +
  scale_x_continuous(breaks = data_taichinh$Nam) +
  scale_color_manual(values = c("ROA" = "#009E73", "ROE" = "#CC79A7")) +
  expand_limits(y = max(data_roa_roe_long$GiaTri) * 1.1) +   # 👈 mở rộng trục Y
  labs(
    title = "Xu hướng ROA và ROE của FPT (2015-2024)",
    x = "Năm",
    y = "Tỷ suất (%)",
    color = "Chỉ số"
  ) +
  theme_classic(base_size = 14) +
  theme(
    plot.title = element_text(face = "bold", hjust = 0.5),
    legend.position = "bottom"
  )

Kỹ thuật:

2. select(Nam, ROA, RDE) - Chọn các chỉ số ROA, RDE theo từng năm để phân tích

3. pivot_longer(cols = -Nam, names_to = “ChiSo”, values_to = “Giafri”) - Chuyển đổi dữ liệu từ wide sang long format, tạo cột chỉ số và giá trị

8. Khởi tạo biểu đồ với mapping dữ liệu cơ bản

9. geom_line(size = 1.2) - Vẽ đường đồ thị thể hiện xu hướng qua các năm

10. geom_point(size = 3, shape = 21, fill = “white”, stroke = 1.5) - Thêm điểm dữ liệu với style viền đậm, nền trắng

11. geom_text(aes(label = round(GiaTri, 1)), vjust = -1.5, size = 3.5) - Hiển thị giá trị số phía trên các điểm dữ liệu

12. scale_x_continuous(breaks = data_taichinh$Nam) - Thiết lập các điểm break trên trục X theo năm

13. scale_color_manual(values = c(“ROA” = “#009E73”, “ROE” = “#CCT9A7”)) - Tùy chỉnh màu sắc cho từng chỉ số

14. expand_limits(y = max(data_roa_roe_long$Giafri) * 1.1) - Mở rộng trục Y để tạo khoảng trống hiển thị nhãn

15. labs() - Thiết lập tiêu đề, nhãn trục và chú thích cho biểu đồ

21. theme_classic(base_size = 14) - Áp dụng theme cổ điển với cỡ chữ cơ bản 14

22. theme() - Tùy chỉnh thêm: tiêu đề in đậm, căn giữa, vị trí legend

Ý nghĩa thống kê:

Biểu đồ cho thấy ROA và ROE của FPT đều duy trì xu hướng tăng ổn định trong giai đoạn 2015–2024. ROA dao động trong khoảng 8,6% – 14,1%, thể hiện khả năng sử dụng tài sản sinh lời ngày càng hiệu quả, đặc biệt tăng mạnh từ 2022 đến 2024. ROE cao vượt trội hơn, dao động từ 21,9% đến 26,7%, chứng minh doanh nghiệp tận dụng tốt nguồn vốn chủ sở hữu để tối đa hóa lợi nhuận. Sự song hành tăng trưởng của cả hai chỉ tiêu phản ánh cấu trúc tài chính lành mạnh và hiệu quả sinh lợi bền vững của FPT trong dài hạn.

Đồ thị xu hướng tổng tài sản FPT (2015-2024)

ggplot(data_taichinh, aes(x = Nam, y = `TỔNG CỘNG TÀI SẢN`)) +
  geom_line(color = "#56B4E9", size = 1) +
  geom_point(color = "#56B4E9", size = 3) +
  geom_text(aes(label = round(`TỔNG CỘNG TÀI SẢN` / 1e6, 1)),   
            vjust = -1, size = 3, color = "black") +
  scale_y_continuous(labels = scales::comma) +
  scale_x_continuous(breaks = data_taichinh$Nam) +
  expand_limits(y = max(data_taichinh$`TỔNG CỘNG TÀI SẢN`) * 1.1) +
  labs(
    title = "Xu hướng tổng tài sản FPT (2015-2024)",
    x = "Năm",
    y = "Tổng tài sản (Đơn vị: ngàn VNĐ)"
  ) +
  theme_minimal(base_size = 14) +
  theme(
    plot.title = element_text(face = "bold", hjust = 0.5, size = 13),
    axis.text.x = element_text(angle = 45, hjust = 1)
  )

Kỹ thuật:

1. ggplot(data_taichinh, aes(x = Nam, y = “TÔNG CÔNG TÀI SẢN”) - Khởi tạo biểu đồ với trục X là năm, trục Y là tổng tài sản

2. geom_line(color = “#56BAE9”, size = 1) - Vẽ đường đồ thị màu xanh với độ dày 1

3. geom_point(color = “#56BAE9”, size = 3) -Thêm điểm dữ liệu cùng màu, kích thước 3

4. geom_text(aes(label = round(‘TÔNG CÔNG TÀI SẢN’ / 1e6, 1)), vjust = -1, size = 3, color = “black”) - Hiển thị giá trị tổng tài sản đã chia 1 triệu và làm tròn 1 số thập phân

6. scale_y_continuous(labels = scales::comma) - Định dạng trục Y với dấu phân cách hàng nghìn

7. scale_x_continuous(breaks = data_taichinh$Nam) - Thiết lập các điểm break trên trục X theo năm

8. expand_limits(y = max(data_taichinh$“TÔNG CÔNG TÀI SẢN”) * 1.1) - Mở rộng trục Y thêm 10% để tạo khoảng trống

9. labs() - Thiết lập tiêu đề biểu đồ và nhãn các trục tọa độ

14. theme_minimal(base_size = 14) - Áp dụng theme minimal với cỡ chữ cơ bản 14

15. theme() - Tùy chỉnh tiêu đề in đậm, căn giữa và xoay nhãn trục X 45 độ

Ý nghĩa thống kê:

Biểu đồ này thể hiện xu hướng tổng tài sản của FPT từ 2015 đến 2024. Tổng tài sản tăng mạnh qua các năm, đặc biệt từ 2020 đến 2024, cho thấy một sự tăng trưởng vượt bậc trong quy mô của công ty. Các con số được thể hiện trên biểu đồ cho thấy tăng trưởng tài sản ổn định và dự đoán một sự tiếp tục phát triển mạnh mẽ trong các năm tiếp theo.

Đồ thị xu hướng tỷ lệ nợ trên tổng tài sản (2015-2024)

ggplot(data_taichinh, aes(x = Nam, y = `Tỷ lệ Nợ trên TTS`)) +
  geom_line(color = "#D55E00", size = 1.2) +
  geom_point(size = 3) +
  geom_text(aes(label = round(after_stat(y), 1)), vjust = -1.5, size = 3.5) +
  geom_hline(yintercept = 50, linetype = "dashed", color = "blue") +
  scale_x_continuous(breaks = data_taichinh$Nam) +
  scale_y_continuous(limits = c(0, 100)) + 
  labs(
    title = "Xu hướng tỷ lệ nợ trên tổng tài sản (2015-2024)",
    x = "Năm",
    y = "Tỷ lệ Nợ (%)"
  ) +
  theme_bw(base_size = 14) +
  theme(plot.title = element_text(face = "bold", hjust = 0.5))

Kỹ thuật:

1. aes(x = Nam, y = Tỷ lệ Nợ trên TTS) - Mapping dữ liệu với trục X là năm, trục Y là tỷ lệ nợ trên tổng tài sản

2. geom_line(color = “#D55E00”, size = 1.2) - Vẽ đường trend màu cam, độ dày 1.2

3. geom_point(size = 3) - Thêm điểm dữ liệu kích thước 3

4. geom_text(aes(label = round(after_stat(y), 1)), vjust = -1.5, size = 3.5) - Hiển thị giá trị phần trăm trên các điểm

5. geom_hline(yintercept = 50, linetype = “dashed”, color = “blue”) - Đường tham chiếu ngang 50%

6. scale_x_continuous(breaks = data_taichinh$Nam) - Hiển thị tất cả năm trên trục X

7. scale_y_continuous(limits = c(0, 100)) - Giới hạn trục Y từ 0-100%

8. labs() - Thiết lập tiêu đề và nhãn trục (bị thiếu nội dung trong code)

13. theme() - Tùy chỉnh giao diện biểu đồ

Ý nghĩa thống kê:

Biểu đồ cho thấy tỷ lệ nợ trên tổng tài sản của FPT trong giai đoạn 2015-2024. Tỷ lệ nợ có sự biến động trong giai đoạn này, đặc biệt vào năm 2016 với mức tỷ lệ nợ cao 61.6%, sau đó giảm xuống dưới 50% trong các năm tiếp theo và duy trì ổn định. Mức tỷ lệ nợ chuẩn 50% được thể hiện bằng đường chấm màu xanh, cho thấy sự điều chỉnh về chiến lược tài chính của công ty trong việc quản lý nợ và tài sản.

So sánh tăng trưởng lợi nhuận sau thuế

ggplot(data_taichinh %>% 
         mutate(LoaiTangTruong = case_when(
           `Tăng trưởng LNST (%)` > 0 ~ "Tăng", 
           `Tăng trưởng LNST (%)` < 0 ~ "Giảm", 
           TRUE ~ "Không đổi"
         )), 
       aes(x = factor(Nam), y = `Tăng trưởng LNST (%)`, fill = LoaiTangTruong)) +
  geom_col(width = 0.7) +
  geom_text(
    aes(label = paste0(round(`Tăng trưởng LNST (%)`, 1), "%"), 
        vjust = ifelse(`Tăng trưởng LNST (%)` >= 0, -0.8, 1.5)), 
    size = 3.5, color = "black"
  ) +
  scale_fill_manual(values = c("Tăng" = "#009E73", "Giảm" = "#D55E00")) +
  
  geom_hline(yintercept = 0, linetype = "solid", color = "black") +
  
  expand_limits(y = max(data_taichinh$`Tăng trưởng LNST (%)`, na.rm = TRUE) * 1.15) +
  labs(
    title = "Tăng trưởng lợi nhuận sau thuế", 
    x = "Năm", 
    y = "Tăng trưởng (%)", 
    fill = "Trạng thái"
  ) +
  
  theme_minimal(base_size = 14) +
  theme(
    plot.title = element_text(face = "bold", hjust = 0.5), 
    legend.position = "none"
  )

Kỹ thuật:

1.mutate(LoaiTangTruong = case_when(…)) - Tạo biến phân loại tăng/giảm dựa vào tăng trưởng LNST

7. aes(x = factor(Nam), y = ‘Tăng trưởng LNST (%)’, fill = LoaiTangTruong) - Mapping dữ liệu với trục X là năm dạng factor, trục Y là tỷ lệ %, fill theo loại tăng trưởng

9. geom_col(width = 0.7) - Vẽ biểu đồ cột với độ rộng 0.7

11. geom_text(aes(label = paste0(round(‘Tăng trưởng LNST (%)’, 1), “%”))) - Hiển thị giá trị phần trăm trên các cột

17. scale_fill_manual(values = c(“Tăng” = “#009E73”, “Giảm” = “#D55E00”)) - Tùy chỉnh màu cho cột tăng (xanh) và giảm (cam)

19. geom_hline(yintercept = 0) - Đường tham chiếu ngang tại mức 0%

21. expand_limits(y = … * 1.15) - Mở rộng trục Y thêm 15%

23. labs() - Thiết lập tiêu đề và nhãn trục

30. theme_minimal(base_size = 14) - Áp dụng theme minimal

32. theme() - Tùy chỉnh tiêu đề in đậm, căn giữa và ẩn chú thích

Ý nghĩa thống kê:

Biểu đồ cho thấy tỷ lệ tăng trưởng lợi nhuận sau thuế của FPT trong giai đoạn 2015-2024, so với năm trước. Có sự biến động rõ rệt vào năm 2017, khi tỷ lệ tăng trưởng đạt mức cao kỷ lục 37%, trong khi năm 2018 có sự suy giảm đáng kể -8.3%. Các năm tiếp theo (2019–2024) duy trì tỷ lệ tăng trưởng ổn định, dao động từ 13.1% đến 21%, với mức tăng trưởng ổn định qua các năm, giúp khẳng định sự bền vững trong chiến lược phát triển của FPT.

Đồ thị cơ cấu tài sản FPT qua các năm (2015-2024)

data_taisan_long <- data_taichinh %>%
  select(Nam, `TÀI SẢN NGẮN HẠN`, `TÀI SẢN DÀI HẠN`) %>%
  pivot_longer(
    cols = -Nam,
    names_to = "LoaiTaiSan",
    values_to = "GiaTri"
  ) %>%
  group_by(Nam) %>%
  mutate(TongNam = sum(GiaTri),
         TyLe = GiaTri / TongNam * 100) %>%
  ungroup()

ggplot(data_taisan_long, aes(x = factor(Nam), y = GiaTri, fill = LoaiTaiSan)) +
  geom_col(position = "stack") +
  geom_text(aes(label = paste0(round(TyLe, 1), "%")),
            position = position_stack(vjust = 0.5),
            color = "black", size = 3.5) +
  scale_y_continuous(labels = scales::comma) +
  scale_fill_brewer(palette = "Pastel1") +
  labs(
    title = "Cơ cấu tài sản FPT qua các năm (2015-2024)",
    x = "Năm",
    y = "Tổng Tài sản (Đơn vị: ngàn VNĐ)",
    fill = "Loại Tài sản"
  ) +
  theme_light(base_size = 14) +
  theme(
    plot.title = element_text(face = "bold", hjust = 0.5),
    legend.position = "bottom"
  )

Kỹ thuật:

1. select() %>% pivot_longer() - Chọn và chuyển dữ liệu sang dạng dài

8. group_by() %>% mutate() %>% ungroup() - Tính tổng và tỷ lệ % theo năm

13. aes(x = factor(Nan), y = GiaTri, fill = LoaiTaiSan) - Mapping dữ liệu biểu đồ stacked

14. geom_col(position = “stack”) - Vẽ biểu đồ cột xếp chồng

15. geom_text(aes(label = paste0(round(Tyle, 1), “%”)) - Hiển thị tỷ lệ % trên các phần cột

18. scale_y_continuous(labels = scales::comma) - Định dạng số trục Y

19. scale_fill_brewer(palette = “Pastel1”) - Palette màu Pastel1

20. labs() - Thiết lập tiêu đề và nhãn trục

26. theme_light(base_size = 14) - Theme light cỡ chữ 14

27. theme() - Tùy chỉnh tiêu đề in đậm, căn giữa, legend dưới cùng

Ý nghĩa thống kê:

Biểu đồ thể hiện sự biến động cơ cấu tài sản của FPT từ năm 2015 đến 2024. Tỷ lệ tài sản ngắn hạn chiếm phần lớn tổng tài sản trong những năm đầu, nhưng bắt đầu giảm dần từ năm 2019, trong khi tỷ lệ tài sản dài hạn tăng lên rõ rệt. Cụ thể, trong năm 2015, tài sản ngắn hạn chiếm 72.8%, đến năm 2024 chỉ còn 36.8%, trong khi tài sản dài hạn tăng từ 27.2% lên 63.2%. Điều này cho thấy FPT đã thay đổi chiến lược tài chính, chuyển từ việc giữ nhiều tài sản ngắn hạn sang tập trung vào các khoản đầu tư dài hạn, phản ánh xu hướng gia tăng ổn định và bền vững trong cơ cấu tài sản của công ty qua các năm.

Đồ thị cơ cấu nguồn vốn

# Tạo dữ liệu dài + tính tỷ lệ
data_nguonvon_long <- data_taichinh %>%
  select(Nam, `NỢ PHẢI TRẢ`, `VỐN CHỦ SỞ HỮU`) %>%
  pivot_longer(
    cols = -Nam,
    names_to = "LoaiNguonVon",
    values_to = "GiaTri"
  ) %>%
  group_by(Nam) %>%
  mutate(TongNam = sum(GiaTri, na.rm = TRUE),
         TyLe    = 100 * GiaTri / TongNam) %>%
  ungroup() %>%
  # Khóa chặt tên level để khớp với scale_fill_manual
  mutate(LoaiNguonVon = factor(
    LoaiNguonVon,
    levels = c("NỢ PHẢI TRẢ", "VỐN CHỦ SỞ HỮU")
  ))

# Vẽ biểu đồ: cột chồng theo %
ggplot(data_nguonvon_long, aes(x = factor(Nam), y = TyLe, fill = LoaiNguonVon)) +
  geom_col(position = "stack") +
  # In % gọn trong từng ô
  geom_text(
    aes(label = paste0(round(TyLe, 1), "%")),
    position = position_stack(vjust = 0.5),
    color = "black", size = 3.5
  ) +
  scale_y_continuous(labels = function(x) paste0(x, "%"), expand = c(0, 0)) +
  scale_fill_manual(values = c("NỢ PHẢI TRẢ" = "#F8766D", "VỐN CHỦ SỞ HỮU" = "#00BFC4")) +
  labs(
    title = "Cơ cấu nguồn vốn FPT qua các năm (2015-2024)",
    x = "Năm",
    y = "Tỷ trọng (%)",
    fill = "Loại Nguồn vốn"
  ) +
  theme_minimal(base_size = 14) +
  theme(
    plot.title = element_text(face = "bold", hjust = 0.5),
    legend.position = "bottom"
  )

Kỹ thuật:

2. select() %>% pivot_longer() - Chọn cột và chuyển dữ liệu sang dạng dài

9. group_by() %>% mutate() %>% ungroup() - Tính tổng và tỷ lệ % theo năm

14. mutate(LoaiNguonVon = factor(…)) - Chuyển loại nguồn vốn thành factor với levels cố định

20. aes(x = factor(Nan), y = TyLe, fill = LoaiNguonVon) - Mapping dữ liệu biểu đồ stacked

21. geom_col(position = “stack”) - Vẽ biểu đồ cột xếp chồng

23. geom_text(aes(label = paste0(round(TyLe, 1), “%”)) - Hiển thị tỷ lệ % ở giữa các phần cột

28. scale_y_continuous(labels = function(x) paste0(x, “%”)) - Định dạng trục Y thêm ký hiệu %

29. scale_fill_manual(values = c(…)) - Tùy chỉnh màu cho từng loại nguồn vốn

30. labs() - Thiết lập tiêu đề và nhãn trục

36. theme_minimal(base_size = 14) - Theme minimal cỡ chữ 14

37. theme() - Tùy chỉnh tiêu đề in đậm, căn giữa, legend dưới cùng

Ý nghĩa thống kê:

Biểu đồ cho thấy sự thay đổi tỷ lệ của các nguồn vốn của FPT qua các năm. Tỷ lệ nợ phải trả chiếm phần lớn trong các năm 2015, 2016, 2017, nhưng tỷ lệ này đã giảm dần từ năm 2018 và tiếp tục giảm trong các năm tiếp theo. Trong khi đó, tỷ lệ vốn chủ sở hữu tăng dần từ năm 2015 đến 2024, từ 39.1% (2015) lên 63.2% (2024). Điều này cho thấy FPT đã cải thiện sự ổn định tài chính và giảm phụ thuộc vào nợ, qua đó tăng cường khả năng tự chủ tài chính trong suốt giai đoạn từ 2015 đến 2024.

Đồ thị tỷ suất sinh lời trên vốn CSH (ROE)

ggplot(data_taichinh, aes(x = factor(Nam), y = ROE)) +
  geom_segment(aes(xend = factor(Nam), yend = 0), color = "grey") +
  geom_point(aes(color = GiaiDoan), size = 5) +
  geom_text(aes(label = round(ROE, 1)),
            vjust = -0.4, size = 3.8, fontface = "bold") +
  scale_color_manual(values = c("Trước 2020" = "#E69F00", "Từ 2020" = "#56B4E9")) +
  expand_limits(y = max(data_taichinh$ROE) * 1.1) +  # mở rộng trục y để không bị cắt
  labs(
    title = "Tỷ suất sinh lời trên vốn CSH (ROE) qua các năm",
    x = "Năm",
    y = "ROE (%)",
    color = "Giai đoạn"
  ) +
  theme_light(base_size = 14) +
  theme(
    plot.title = element_text(face = "bold", hjust = 0.5),
    legend.position = "bottom"
  )

Kỹ thuật:

1. aes(x = factor(Nam), y = R0E) - Mapping dữ liệu với trục X là năm dạng factor, trục Y là ROE

2. geom_segment(aes(xend = factor(Nam), yend = 0)) - Vẽ đoạn thẳng từ điểm dữ liệu xuống trục X

3. geom_point(aes(color = GiaiDoan), size = 5) - Vẽ điểm dữ liệu lớn kích thước 5, màu theo giai đoạn

4. geom_text(aes(label = round(R0E, 1)) - Hiển thị giá trị ROE làm tròn 1 số thập phân

6. scale_color_manual(values = c(…)) - Tùy chỉnh màu cho 2 giai đoạn

7. expand_limits(y = max(data_taichinh$ROE) * 1.1) - Mở rộng trục Y thêm 10%

8. labs() - Thiết lập tiêu đề và nhãn trục

14. theme_light(base_size = 14) - Theme light cỡ chữ 14

15. theme() - Tùy chỉnh tiêu đề in đậm, căn giữa, legend dưới cùng

Ý nghĩa thống kê:

Biểu đồ này thể hiện sự thay đổi tỷ suất sinh lời trên vốn chủ sở hữu (ROE) của FPT từ 2015 đến 2024. Tỷ lệ ROE có xu hướng ổn định và tăng trưởng nhẹ qua các năm. Đặc biệt, từ năm 2020, ROE duy trì ở mức cao và ổn định, phản ánh sự hiệu quả trong việc sử dụng vốn chủ sở hữu của FPT. ROE năm 2020 có mức tăng trưởng đáng chú ý, đạt 26.7%, sau đó duy trì ổn định xung quanh mức 25-26%.

Đồ thị tỷ suất sinh lời trên tài sản (ROA)

ggplot(data_taichinh, aes(x = factor(Nam), y = ROA)) +
  geom_segment(aes(xend = factor(Nam), yend = 0), color = "grey") +
  geom_point(color = "#009E73", size = 5) +
  geom_text(aes(label = round(ROA, 1)),
            vjust = -0.4, size = 3.8, fontface = "bold") +
  expand_limits(y = max(data_taichinh$ROA) * 1.1) +  # mở rộng trục Y để không bị cắt nhãn
  labs(
    title = "Tỷ suất sinh lời trên tài sản (ROA) qua các năm",
    x = "Năm",
    y = "ROA (%)"
  ) +
  theme_bw(base_size = 14) +
  theme(
    plot.title = element_text(face = "bold", hjust = 0.5)
  )

Kỹ thuật:

1. aes(x = factor(Nam), y = ROA) - Mapping dữ liệu với trục X là năm dạng factor, trục Y là ROA

2. geom_segment(aes(xend = factor(Nam), yend = 0), color = “grey”) - Vẽ đoạn thẳng từ điểm dữ liệu xuống trục X

3. geom_point(color = “#009E73”, size = 5)-Vẽ điểm dữ liệu màu xanh lá, kích thước 5

4.geom_text(aes(label = round(ROA, 1)) - Hiển thị giá trị ROA làm tròn 1 số thập phân

6. expand_limits(y = max(data_taichinh$ROA) * 1.1) - Mở rộng trục Y thêm 10%

7. labs() - Thiết lập tiêu đề và nhãn trục

12. theme_bw(base_size = 14) - Theme black and white cỡ chữ 14

13. theme() - Tùy chỉnh tiêu đề in đậm, căn giữa

Ý nghĩa thống kê:

Biểu đồ thể hiện sự thay đổi của tỷ suất sinh lời trên tài sản (ROA) của FPT từ năm 2015 đến 2024. Trong suốt giai đoạn này, tỷ suất ROA có sự tăng trưởng ổn định, đặc biệt từ năm 2017 đến 2024, khi ROA tăng từ 8.6% lên 13.1%.

Phân phối của ROA (Histogram)

ggplot(data_taichinh, aes(x = ROA)) +
  geom_histogram(aes(y = ..density..), bins = 5, fill = "#009E73", color = "white") +
  geom_density(color = "red", size = 1, linetype = "dashed") +
  geom_rug(color = "black") +
  labs(
    title = "Phân phối của Tỷ suất sinh lời trên Tài sản (ROA)",
    x = "ROA (%)",
    y = "Mật độ (Density)"
  ) +
  theme_minimal(base_size = 14) +
  theme(plot.title = element_text(face = "bold", hjust = 0.5))

Kỹ thuật:

1. aes(x = ROA) - Mapping trục X với biến ROA

2. geom_histogram(aes(y = ..density..), bins = 5, fill = “#009E73”, color = “white”) - Vẽ histogram 5 bins, màu xanh lá, hiển thị density

3. geom_density(color = “red”, size = 1, linetype = “dashed”) - Đường density màu đỏ, nét đứt, độ dày 1

4. geom_rug(color = “black”) - Hiển thị rug plot màu đen dưới đáy

5. labs() - Thiết lập tiêu đề và nhãn trục X 10. them - Định dạng

Ý nghĩa thống kê:

Biểu đồ trên thể hiện phân phối của tỷ suất sinh lời trên tài sản (ROA) từ 2015 đến 2024. Tỷ lệ ROA có sự phân phối gần như đồng đều với nhiều giá trị tập trung trong khoảng từ 10% đến 12%. Đặc biệt, có một mức cao nhất đạt khoảng 37%, xuất hiện trong năm 2017. Đường mật độ phân phối (red dashed line) cho thấy dữ liệu có xu hướng tập trung nhiều hơn ở các giá trị trung bình (khoảng 10–12%), trong khi các giá trị ROA ở các mức cao hơn (12% trở lên) ít phổ biến hơn.

Đồ thị Density Plot thể hiện ROE

ggplot(data_taichinh, aes(x = ROE)) +
  geom_density(fill = "#CC79A7", color = "black", alpha = 0.7) +
  geom_vline(aes(xintercept = mean(ROE)), color = "blue", linetype = "dashed", size = 1) +
  geom_label(aes(x = mean(ROE), y = 0.01, label = paste("Trung bình:", round(mean(ROE),1))), 
             color = "blue") +
  labs(
    title = "Phân phối của Tỷ suất sinh lời trên Vốn CSH (ROE)",
    x = "ROE (%)",
    y = "Mật độ (Density)"
  ) +
  theme_classic(base_size = 14) +
  theme(plot.title = element_text(face = "bold", hjust = 0.5))

Kỹ thuật:

1. aes(x = R0E) - Mapping trục X với biến ROE

2. geom_density(fill = “#CCT9A7”, color = “black”, alpha = 0.7) - Vẽ đường phân phối màu xanh nhạt, viền đen, độ trong suốt 0.7

3. geom_vline(aes(xintercept = mean(R0E))) - Đường thẳng đứng tại giá trị trung bình ROE

4. geom_label(aes(x = mean(R0E), y = 0.01, label = paste(“Trung bình:”, round(mean(R0E),1)))) - Nhãn hiển thị giá trị trung bình

6. labs() - Thiết lập tiêu đề và nhãn trục

11. theme_classic(base_size = 14) - Theme classic cỡ chữ 14

12. theme(plot.title = element_text(face = “bold”, hjust = 0.5)) - Tiêu đề in đậm, căn giữa

Ý nghĩa thống kê:

Biểu đồ trên thể hiện sự phân phối của tỷ suất sinh lời trên vốn chủ sở hữu (ROE) từ 2015 đến 2024. Các giá trị ROE phân bố tương đối đồng đều với một phần lớn dữ liệu tập trung trong khoảng từ 22% đến 26%. Trung bình ROE trong suốt giai đoạn này là 24.5%, điều này cho thấy FPT duy trì mức lợi nhuận khá ổn định trên vốn chủ sở hữu qua các năm. Biểu đồ mật độ thể hiện sự tập trung của dữ liệu xung quanh mức trung bình này, đồng thời đường vẽ cho thấy sự phân bổ có xu hướng đều và ổn định.

So sánh ROA theo giai đoạn

ggplot(data_taichinh, aes(x = GiaiDoan, y = ROA, fill = GiaiDoan)) +
  geom_boxplot(alpha = 0.8) +
  geom_jitter(width = 0.1, color = "black", alpha = 0.5) +
  scale_fill_manual(values = c("Trước 2020" = "#E69F00", "Từ 2020" = "#56B4E9")) +
  labs(
    title = "So sánh phân phối ROA theo giai đoạn",
    x = "Giai đoạn",
    y = "ROA (%)"
  ) +
  theme_minimal(base_size = 14) +
  theme(
    plot.title = element_text(face = "bold", hjust = 0.5),
    legend.position = "none"
  )

Kỹ thuật:

1. aes(x = GiaiDoan, y = R0A, fill = GiaiDoan) - Mapping dữ liệu theo giai đoạn

2. geom_boxplot(alpha = 0.8) - Vẽ boxplot với độ trong suốt 0.8

3. geom_jitter(width = 0.1, color = “black”, alpha = 0.5) - Hiển thị điểm dữ liệu với độ phân tán 0.1

4. scale_fill_manual(values = c(…)) - Tùy chỉnh màu cho 2 giai đoạn

5.labs() - Thiết lập tiêu đề và nhãn trục

10. theme_minimal(base_size = 14) - Theme minimal cỡ chữ 14

11. theme() - Tiêu đề in đậm, căn giữa, ẩn legend

Ý nghĩa thống kê:

Biểu đồ này so sánh sự phân bố của tỷ suất sinh lời trên tài sản (ROA) giữa hai giai đoạn: trước năm 2020 (2015-2019) và từ 2020 trở đi. Nhìn chung, ROA trong giai đoạn sau 2020 có sự ổn định cao hơn với giá trị trung vị dao động trong khoảng từ 10% đến 13%, trong khi đó giai đoạn trước 2020 có sự dao động mạnh hơn, với mức ROA thấp hơn ở các năm đầu và có một số giá trị ngoại lệ đáng chú ý vào năm 2017. Biểu đồ cho thấy sự cải thiện đáng kể trong hiệu quả sử dụng tài sản của FPT từ giai đoạn trước 2020 sang giai đoạn sau 2020.

So sánh ROE theo giai đoạn

ggplot(data_taichinh, aes(x = GiaiDoan, y = ROE, fill = GiaiDoan)) +
  geom_violin(alpha = 0.7, trim = FALSE) +
  geom_boxplot(width = 0.1, fill = "white", outlier.shape = NA) +
  geom_jitter(width = 0.1, color = "black", alpha = 0.5) +
  scale_fill_manual(values = c("Trước 2020" = "#009E73", "Từ 2020" = "#CC79A7")) +
  labs(
    title = "So sánh phân phối ROE theo giai đoạn",
    x = "Giai đoạn",
    y = "ROE (%)"
  ) +
  theme_light(base_size = 14) +
  theme(
    plot.title = element_text(face = "bold", hjust = 0.5),
    legend.position = "none"
  )

Kỹ thuật:

1. aes(x = GiaiDoan, y = ROE, fill = GiaiDoan) - Mapping dữ liệu theo giai đoạn

2. geom_violin(alpha = 0.7, trim = FALSE) - Vẽ violin plot với độ trong suốt 0.7, không trim

3. geom_boxplot(width = 0.1, fill = “white”, outlier.shape = NA) - Boxplot nhỏ màu trắng, ẩn outlier

4. geom_jitter(width = 0.1, color = “black”, alpha = 0.5) - Hiển thị điểm dữ liệu phân tán

5. scale_fill_manual(values = c(…)) - Tùy chỉnh màu cho 2 giai đoạn

6. labs() - Thiết lập tiêu đề và nhãn trục

11. theme_light(base_size = 14) - Theme light cỡ chữ 14

12. theme() - Tiêu đề in đậm, căn giữa, ẩn legend

Ý nghĩa thống kê:

Biểu đồ này cho thấy sự phân bố của tỷ suất sinh lời trên vốn chủ sở hữu (ROE) của FPT trong hai giai đoạn (2015-2019 và 2020-2024). Giai đoạn trước 2020 (2015-2019) có sự phân bố rộng hơn với mức ROE dao động từ khoảng 8.6% đến 14.1%, cho thấy sự biến động trong hiệu quả sử dụng vốn chủ sở hữu. Trong khi đó, giai đoạn sau 2020 (2020-2024) cho thấy sự ổn định hơn với ROE dao động trong khoảng từ 10% đến 13%, với mức trung bình cao hơn và ít dao động hơn, phản ánh hiệu quả cao và ổn định trong việc sử dụng vốn của FPT.

Đồ thị hàng tồn kho

ggplot(data_taichinh, aes(x = factor(Nam), y = `Hàng tồn kho` / 1e6)) +  
  geom_col(aes(fill = GiaiDoan), width = 0.7) +
  geom_text(aes(label = round(`Hàng tồn kho` / 1e6, 1)),  
            vjust = -0.5,
            size = 3,
            color = "black") +
  scale_y_continuous(labels = scales::comma) +
  scale_fill_manual(values = c("Trước 2020" = "#E69F00", "Từ 2020" = "#56B4E9")) +
  labs(
    title = "Xu hướng hàng tồn kho của FPT (2015-2024)",
    x = "Năm",
    y = "Hàng tồn kho (Đơn vị: tỷ VNĐ)",  
    fill = "Giai đoạn"
  ) +
  theme_minimal(base_size = 14) +
  theme(
    plot.title = element_text(face = "bold", hjust = 0.5),
    axis.text.x = element_text(angle = 45, hjust = 1),
    legend.position = "top"
  )

Kỹ thuật:

1. aes(x = factor(Nam), y = “Hang tôn kho” / 1e6) - Mapping dữ liệu, chia 1e6 để đổi sang tỷ VND

2. geom_col(aes(fill = GiaiDoan), width = 0.7) - Vẽ cột màu theo giai đoạn, độ rộng 0.7

3. geom_text(aes(label = round(“Hàng tôn kho” / 1e6, 1))) - Hiển thị giá trị làm tròn 1 số thập phân

7. scale_y_continuous(labels = scales::comma) - Định dạng số có dấu phân cách

8. scale_fill_manual(values = c(…)) - Tùy chỉnh màu cho 2 giai đoạn

9.labs() - Thiết lập tiêu đề và nhãn trục

15. theme_minimal(base_size = 14) - Theme minimal cỡ chữ 14

16. theme() - Tiêu đề in đậm, căn giữa, chữ trục X nghiêng 45 độ, legend trên top

Ý nghĩa thống kê:

Biểu đồ này phản ánh sự biến động trong giá trị Hàng tồn kho của FPT từ năm 2015 đến năm 2024. Đặc biệt, năm 2015 và 2016 ghi nhận mức hàng tồn kho cao (5268 tỷ VNĐ và 4553 tỷ VNĐ), sau đó giảm mạnh trong những năm tiếp theo xuống dưới 1400 tỷ VNĐ từ 2017 đến 2020. Tuy nhiên, từ năm 2021 trở đi, Hàng tồn kho có xu hướng tăng lại, đạt 1966 tỷ VNĐ vào năm 2022 và duy trì ở mức trên 1500 tỷ VNĐ cho các năm sau. Điều này có thể phản ánh sự gia tăng hoạt động sản xuất và tồn trữ hàng hóa trong bối cảnh công ty mở rộng các hoạt động kinh doanh.

Đồ thị xu hướng đầu tư tài chính

# Chuẩn bị dữ liệu
data_dautu_long <- data_taichinh %>%
  select(Nam, `Đầu tư tài chính ngắn hạn`, `Đầu tư tài chính dài hạn`) %>%
  pivot_longer(
    cols = -Nam,
    names_to = "LoaiDauTu",
    values_to = "GiaTri"
  ) %>%
  group_by(Nam) %>%
  mutate(TongNam = sum(GiaTri),
         TyLe = GiaTri / TongNam * 100) %>%
  ungroup()

# Vẽ biểu đồ: Đường có màu riêng, nhãn màu khác
ggplot(data_dautu_long, aes(x = Nam, y = GiaTri, color = LoaiDauTu, group = LoaiDauTu)) +
  geom_line(size = 1.2) +
  geom_point(size = 3) +
  geom_text(aes(label = paste0(round(TyLe, 1), "%")),  
            vjust = -0.8, size = 3.5, color = "black", fontface = "bold", show.legend = FALSE) +
  scale_x_continuous(breaks = data_taichinh$Nam) +
  scale_y_continuous(labels = scales::comma) +
  scale_color_manual(
    values = c("Đầu tư tài chính ngắn hạn" = "#0072B2",  
               "Đầu tư tài chính dài hạn" = "#D55E00")  
  ) +
  expand_limits(y = max(data_dautu_long$GiaTri) * 1.15) +
  labs(
    title = "Xu hướng đầu tư tài chính (2015-2024)",
    x = "Năm",
    y = "Giá trị Đầu tư (Đơn vị: ngàn VNĐ)",
    color = "Loại Đầu tư"
  ) +
  theme_classic(base_size = 14) +
  theme(
    plot.title = element_text(face = "bold", hjust = 0.5),
    legend.position = "bottom"
  )

Kỹ thuật:

1.Chuẩn bị dữ liệu dạng long và tính toán tỷ lệ

15. aes(x = Nam, y = GiaTri, color = LoaiDauTu, group = LoaiDauTu) - Mapping dữ liệu cho biểu đồ đường

16. geom_line(size = 1.2) - Vẽ đường kết nối các điểm

17. geom_point(size = 3) - Thêm điểm dữ liệu kích thước 3

18. geom_text(aes(label = paste0(round(Tyle, 1), “%”)) - Hiển thị tỷ lệ % trên biểu đồ

20. scale_x_continuous(breaks = data_taichinh$Nam) - Thiết lập breaks trục X theo năm

21. scale_y_continuous(labels = scales::comma) - Định dạng số trục Y

22. scale_color_manual(values = c(…)) - Tùy chỉnh màu cho từng loại đầu tư

26. expand_limits(y = max(data_dautu_long$GiaTri) * 1.15) - Mở rộng trục Y thêm 15%

27. labs() - Thiết lập tiêu đề và nhãn trục

33. theme_classic(base_size = 14) - Áp dụng theme classic

34. theme() - Tùy chỉnh tiêu đề in đậm, căn giữa, legend dưới cùng

Ý nghĩa thống kê:

Biểu đồ thể hiện sự thay đổi tỷ lệ giữa “Đầu tư tài chính ngắn hạn” và “Đầu tư tài chính dài hạn” của FPT từ năm 2015 đến 2024. Trong giai đoạn đầu, “Đầu tư tài chính dài hạn” chiếm ưu thế rõ rệt, đặc biệt năm 2015 (78.2%) và giảm dần trong các năm sau. Đến năm 2021, tỷ lệ đầu tư ngắn hạn bắt đầu tăng mạnh, đạt mức 86.8% vào năm 2024, trong khi đầu tư dài hạn giảm xuống còn 13.2%. Điều này phản ánh sự thay đổi chiến lược đầu tư của FPT, tập trung vào các khoản đầu tư ngắn hạn, có khả năng thu hồi vốn nhanh, trong khi giảm sự phụ thuộc vào các khoản đầu tư dài hạn.

Biểu đồ tròn cơ cấu nguồn vốn (Năm 2024)

data_nv_2024 <- data_taichinh %>%
  filter(Nam == "2024") %>%
  select(`NỢ PHẢI TRẢ`, `VỐN CHỦ SỞ HỮU`) %>%
  pivot_longer(
    cols = everything(),
    names_to = "LoaiNguonVon",
    values_to = "GiaTri"
  ) %>%
  mutate(TyTrong = GiaTri / sum(GiaTri))

ggplot(data_nv_2024, aes(x = "", y = TyTrong, fill = LoaiNguonVon)) +
  geom_col(width = 1, color = "white") +
  coord_polar(theta = "y") +
  geom_text(aes(label = scales::percent(TyTrong, accuracy = 0.01)),
            position = position_stack(vjust = 0.5),
            size = 5) +
  scale_fill_manual(values = c(`NỢ PHẢI TRẢ` = "#F8766D", `VỐN CHỦ SỞ HỮU` = "#00BFC4")) +
  labs(
    title = "Cơ cấu nguồn vốn FPT (Năm 2024)",
    fill = "Loại Nguồn vốn",
    x = NULL, y = NULL
  ) +
  theme_void(base_size = 14) +
  theme(
    plot.title = element_text(face = "bold", hjust = 0.5),
    legend.position = "bottom"
  )

Kỹ thuật:

1. Lọc dữ liệu 2024, chuyển dạng long và tính tỷ trọng

11. aes(x = ““, y = TyTrong, fill = LoaiNguonVon) - Mapping dữ liệu biểu đồ tròn

12. geom_col(width = 1, color = “white”) - Vẽ cột với viền trắng

13. coord_polar(theta = “y”) - Chuyển thành biểu đồ tròn

14. geom_text(aes(label = scales::percent(TyTrong))) - Hiển thị tỷ lệ % ở giữa các phần

17. scale_fill_manual(values = c(…)) - Tùy chỉnh màu cho nguồn vốn

18. labs() - Thiết lập tiêu đề, ẩn nhãn trục

23. theme_void(base_size = 14) - Theme rỗng để ẩn trục

24. theme() - Tiêu đề in đậm, căn giữa, legend dưới cùng

Ý nghĩa thống kê:

Biểu đồ này thể hiện cơ cấu nguồn vốn của FPT trong năm 2024. Cơ cấu vốn chia thành hai phần: “NỢ PHẢI TRẢ” chiếm 50.38% và “VỐN CHỦ SỞ HỮU” chiếm 49.62%. Mặc dù tỷ lệ của hai loại nguồn vốn gần như bằng nhau, với sự chênh lệch rất nhỏ (0.76%), điều này cho thấy sự cân đối giữa nguồn vốn vay và vốn chủ sở hữu trong cấu trúc tài chính của FPT.

Biểu đồ tròn cơ cấu tài sản (Năm 2024)

data_ts_2024 <- data_taichinh %>%
  filter(Nam == "2024") %>%
  select(`TÀI SẢN NGẮN HẠN`, `TÀI SẢN DÀI HẠN`) %>%
  pivot_longer(
    cols = everything(),
    names_to = "LoaiTaiSan",
    values_to = "GiaTri"
  ) %>%
  mutate(TyTrong = GiaTri / sum(GiaTri))

ggplot(data_ts_2024, aes(x = "", y = TyTrong, fill = LoaiTaiSan)) +
  geom_col(width = 1, color = "white") +
  coord_polar(theta = "y") +
  geom_text(aes(label = scales::percent(TyTrong, accuracy = 0.01)),
            position = position_stack(vjust = 0.5),
            size = 5) +
  scale_fill_brewer(palette = "Pastel1") +
  labs(
    title = "Cơ cấu Tài sản FPT (Năm 2024)",
    fill = "Loại Tài sản",
    x = NULL, y = NULL
  ) +
  theme_void(base_size = 14) +
  theme(
    plot.title = element_text(face = "bold", hjust = 0.5),
    legend.position = "bottom"
  )

Kỹ thuật:

1. Lọc dữ liệu 2024, chuyển dạng long và tính tỷ trọng tài sản

11. aes(x = ““, y = TyTrong, fill = LoaiTaiSan) - Mapping dữ liệu biểu đồ tròn

12. geom_col(width = 1, color = “white”) - Vẽ cột với viền trắng

13. coord_polar(theta = “y”) - Chuyển thành biểu đồ tròn

14. geom_text(aes(label = scales::percent(TyTrong))) - Hiển thị tỷ lệ % ở giữa các phần

17. scale_fill_brewer(palette = “Pastel1”) - Sử dụng palette màu Pastel1

18. labs() - Thiết lập tiêu đề, ẩn nhãn trục

23. theme_void(base_size = 14) - Theme rỗng để ẩn trục

24. theme() - Tiêu đề in đậm, căn giữa, legend dưới cùng

Ý nghĩa thống kê:

Biểu đồ này thể hiện cơ cấu tài sản của FPT trong năm 2024. Cơ cấu tài sản của FPT chủ yếu được phân bổ vào tài sản ngắn hạn, chiếm 63.24%, trong khi tài sản dài hạn chiếm 36.76%. Tỷ lệ tài sản ngắn hạn lớn hơn tài sản dài hạn, cho thấy FPT có xu hướng duy trì một phần lớn tài sản của mình dưới dạng tài sản có tính thanh khoản cao hơn, phản ánh chiến lược sử dụng nguồn vốn linh hoạt và dễ dàng chuyển đổi thành tiền mặt trong ngắn hạn.

Đồ thị tổng tài sản và ROA qua các năm

he_so_chuyen_doi <- max(data_taichinh$`TỔNG CỘNG TÀI SẢN`) / max(data_taichinh$ROA)

ggplot(data_taichinh, aes(x = factor(Nam))) +
  # Cột thể hiện Tổng tài sản
  geom_col(aes(y = `TỔNG CỘNG TÀI SẢN`, fill = "Tổng Tài sản"), alpha = 0.7) +

  # Đường ROA
  geom_line(aes(y = ROA * he_so_chuyen_doi, color = "ROA (%)", group = 1), size = 1.5) +
  geom_point(aes(y = ROA * he_so_chuyen_doi), color = "#D55E00", size = 3) +

  # Thêm nhãn ROA
  geom_text(aes(
    y = ROA * he_so_chuyen_doi,
    label = paste0(round(ROA, 1), "%")
  ),
  vjust = -0.6,                # 👈 nâng nhãn lên cao hơn (giúp không bị che)
  size = 3.8,
  color = "#D55E00",
  fontface = "bold"
  ) +

  # Mở rộng giới hạn trục Y để nhãn không bị cắt
  expand_limits(y = max(data_taichinh$`TỔNG CỘNG TÀI SẢN`) * 1.15) +

  # Trục chính và trục phụ
  scale_y_continuous(
    name = "Tổng Tài sản (ngàn VNĐ)",
    labels = scales::comma,
    sec.axis = sec_axis(~ . / he_so_chuyen_doi,
                        name = "ROA (%)",
                        labels = function(x) paste0(round(x, 1), "%"))
  ) +

  scale_fill_manual(values = c("Tổng Tài sản" = "#56B4E9")) +
  scale_color_manual(values = c("ROA (%)" = "#D55E00")) +

  labs(
    title = "Tổng tài sản và ROA qua các năm",
    x = "Năm",
    y = "Tổng Tài sản (ngàn VNĐ)",
    color = NULL,
    fill = NULL
  ) +
  theme_light(base_size = 14) +
  theme(
    plot.title = element_text(face = "bold", hjust = 0.5),
    legend.position = "bottom"
  )

Kỹ thuật:

1. he_so_chuyen_doi <- … - Tính hệ số chuyển đổi giữa tổng tài sản và ROA

3. aes(x = factor(Nam)) - Trục X là năm dạng factor

5. geom_col(aes(y = “TÔNG CÔNG TÀI SẢN”, fill = “Tổng Tài sản”)) - Vẽ cột tổng tài sản

8. geom_line(aes(y = ROA * he_so_chuyen_doi, color = “ROA (%)”)) - Vẽ đường ROA sau khi nhân hệ số

9. geom_point(aes(y = ROA * he_so_chuyen_doi)) - Thêm điểm cho đường ROA

12. geom_text(aes(y = ROA * he_so_chuyen_doi, label = paste0(round(ROA, 1), “%”))) - Hiển thị giá trị ROA

23. expand_limits(y = max(…) * 1.15) - Mở rộng trục Y

26. scale_y_continuous(sec.axis = sec_axis(~ . / he_so_chuyen_doi)) - Tạo trục Y phụ cho ROA

34. scale_fill_manual() - Màu cho tổng tài sản

35. scale_color_manual() - Màu cho ROA

37. labs() - Thiết lập tiêu đề và nhãn

44. theme_light(base_size = 14) - Theme light

45. theme() - Tiêu đề in đậm, căn giữa, legend dưới cùng

Ý nghĩa thống kê:

Biểu đồ thể hiện sự tăng trưởng rõ rệt của Tổng Tài sản và ROA của FPT từ 2015 đến 2024. Tổng tài sản có xu hướng tăng trưởng ổn định, đặc biệt từ năm 2020 đến 2024, cho thấy sự mở rộng và tích lũy tài sản của FPT. ROA duy trì mức ổn định, dao động từ 9-13% trong suốt giai đoạn, phản ánh khả năng sinh lời hiệu quả từ tài sản. Mối quan hệ giữa tổng tài sản và ROA cho thấy FPT đã sử dụng tài sản của mình một cách hiệu quả, với mức sinh lời duy trì ổn định dù tài sản tăng trưởng.

Đồ thị lợi nhuận và tăng trưởng qua các năm

# Chuẩn hóa dữ liệu
data_taichinh <- data_taichinh %>%
  mutate(
    `Tăng trưởng LNST (%)` = as.numeric(`Tăng trưởng LNST (%)`),
    `Lợi nhuận sau thuế thu nhập doanh nghiệp` = as.numeric(`Lợi nhuận sau thuế thu nhập doanh nghiệp`)
  )

# Tính hệ số chuyển đổi cho trục phụ
he_so_chuyen_doi_2 <- max(data_taichinh$`Lợi nhuận sau thuế thu nhập doanh nghiệp`, na.rm = TRUE) /
                      max(data_taichinh$`Tăng trưởng LNST (%)`, na.rm = TRUE)

# Vẽ biểu đồ
ggplot(data_taichinh, aes(x = factor(Nam))) +
  # Cột lợi nhuận
  geom_col(aes(y = `Lợi nhuận sau thuế thu nhập doanh nghiệp`, fill = "Lợi nhuận"), 
           width = 0.65, alpha = 0.85) +

  # Đường tăng trưởng
  geom_line(aes(y = `Tăng trưởng LNST (%)` * he_so_chuyen_doi_2, 
                color = "Tăng trưởng (%)", group = 1), 
            size = 1.3, lineend = "round") +
  geom_point(aes(y = `Tăng trưởng LNST (%)` * he_so_chuyen_doi_2), 
             color = "#0072B2", size = 3) +

  # Nhãn % tăng trưởng
  geom_text(aes(y = `Tăng trưởng LNST (%)` * he_so_chuyen_doi_2,
                label = paste0(round(`Tăng trưởng LNST (%)`, 1), "%")),
            vjust = -1.1, size = 3.8, color = "#0072B2", fontface = "bold") +

  # Mở rộng trục Y để không mất nhãn
  expand_limits(y = max(data_taichinh$`Lợi nhuận sau thuế thu nhập doanh nghiệp`, na.rm = TRUE) * 1.15) +

  # Hai trục Y: bên trái = lợi nhuận, bên phải = tăng trưởng
  scale_y_continuous(
    name = "Lợi nhuận (tỷ VNĐ)",
    labels = function(x) paste0(round(x / 1e6, 1)),  # ⚡ chỉ chia 1e6 vì dữ liệu là NGÀN VNĐ
    sec.axis = sec_axis(~ . / he_so_chuyen_doi_2,
                        name = "Tăng trưởng (%)",
                        labels = function(x) paste0(round(x, 1), "%"))
  ) +

  # Màu sắc
  scale_fill_manual(values = c("Lợi nhuận" = "#FDB515")) +
  scale_color_manual(values = c("Tăng trưởng (%)" = "#0072B2")) +

  # Tiêu đề & theme
  labs(
    title = "Lợi nhuận (cột) và Tăng trưởng (đường) qua các năm",
    x = "Năm",
    y = "Lợi nhuận (tỷ VNĐ)",
    color = NULL,
    fill = NULL
  ) +
  theme_light(base_size = 14) +
  theme(
    plot.title = element_text(face = "bold", hjust = 0.5, size = 16),
    legend.position = "bottom",
    axis.title.y.right = element_text(color = "#0072B2", face = "bold"),
    axis.title.y.left  = element_text(color = "#E69F00", face = "bold")
  )

Kỹ thuật:

1. mutate() - Chuẩn hóa dữ liệu sang numeric, tách dòng để tránh tràn

9. he_so_chuyen_doi_2 <- … - Tính hệ số chuyển đổi, tách thành nhiều dòng

15. aes(x = factor(Nam)) - Trục X là năm dạng factor

17. geom_col(aes(y = Lợi nhuận…, fill = “Lợi nhuận”)) - Vẽ cột lợi nhuận

22. geom_line(aes(y = Tăng trưởng… * he_so_chuyen_doi_2)) - Vẽ đường tăng trưởng

29. geom_point(aes(y = Tăng trưởng… * he_so_chuyen_doi_2)) - Thêm điểm tăng trưởng

34. geom_text(aes(y = Tăng trưởng… * he_so_chuyen_doi_2, label = paste0(…))) - Hiển thị giá trị tăng trưởng

42. expand_limits(y = max(…) * 1.2) - Mở rộng trục Y thêm 20%

48. scale_y_continuous(sec.axis = sec_axis(…)) - Tạo trục Y phụ cho tăng trưởng

58. scale_fill_manual() - Màu vàng cho lợi nhuận

59. scale_color_manual() - Màu xanh cho tăng trưởng

61. labs() - Thiết lập tiêu đề và nhãn

65. theme_light(base_size = 14) - Theme light cỡ chữ 14

66. theme() - Tùy chỉnh tiêu đề, legend, màu nhãn trục và margin

Ý nghĩa thống kê:

Biểu đồ này phản ánh sự thay đổi của lợi nhuận sau thuế và tăng trưởng lợi nhuận của FPT trong giai đoạn từ 2015 đến 2024. Lợi nhuận (cột vàng) có sự biến động mạnh vào năm 2017, với mức tăng đột biến (37%) và sau đó giảm mạnh vào năm 2018 (mức giảm -8.3%). Từ năm 2019 đến 2024, lợi nhuận có xu hướng tăng trưởng ổn định và đạt mức cao vào năm 2024, ước tính gần 8700 tỷ VNĐ.

Tăng trưởng lợi nhuận (đường xanh) cho thấy sự thay đổi ổn định với các tỷ lệ tăng trưởng duy trì quanh mức 20%, cho thấy hiệu quả duy trì đà tăng trưởng lợi nhuận của FPT trong suốt giai đoạn này, với các giá trị tăng trưởng từ 13.1% (2020) lên tới 21% (2024). Mối quan hệ giữa lợi nhuận và tăng trưởng này cho thấy rằng dù lợi nhuận có sự biến động lớn, FPT vẫn duy trì được tỷ lệ tăng trưởng ổn định qua các năm.