CHƯƠNG 1. TỔNG QUAN BỘ DỮ LIỆU

Công ty Cổ phần CokyVina (CKV) là một tổ chức có lịch sử phát triển từ năm 1990, khởi điểm là một doanh nghiệp nhà nước trực thuộc Tổng cục Bưu điện. Sau quá trình chuyển đổi mô hình hoạt động, CKV đã được tái cấu trúc thành công ty cổ phần, trong đó vốn Nhà nước chiếm 49%. Lĩnh vực hoạt động chính của CKV bao gồm: viễn thông (phát triển và quản lý hạ tầng mạng, truyền dẫn), công nghệ thông tin (cung cấp các dịch vụ như EKYC, xác thực khuôn mặt) và hoạt động xuất nhập khẩu vật tư, thiết bị chuyên ngành.

1.1. Giới thiệu bộ dữ liệu

a. Chi tiết bộ dữ liệu

data_ckv <- read.csv("C:/Users/Admin/Documents/DataR/Data_ckv.csv")
 # Xóa các cột lỗi (từ X đến X.7)
data_ckv <- data_ckv %>%
  select(-starts_with("X")) 
# GIỮ LẠI 40 DÒNG ĐẦU TIÊN
data_ckv <- data_ckv[1:40, ]

# --- KIỂM TRA SAU KHI CẮT ---
cat("- Số dòng:", nrow(data_ckv), "\n")
## - Số dòng: 40
cat("- Số cột:", ncol(data_ckv), "\n")
## - Số cột: 13
dim(data_ckv)
## [1] 40 13
str(data_ckv)
## 'data.frame':    40 obs. of  13 variables:
##  $ Quarter           : chr  "Q1/2015" "Q2/2015" "Q3/2015" "Q4/2015" ...
##  $ TongTaiSan        : num  2.14e+11 1.88e+11 1.98e+11 2.13e+11 2.20e+11 ...
##  $ Tongno            : num  1.29e+11 1.12e+11 1.15e+11 1.28e+11 1.34e+11 ...
##  $ QuyMo             : num  26.1 26 26 26.1 26.1 ...
##  $ TangTruongTTS...  : num  NA -0.1203 0.0509 0.0772 0.0311 ...
##  $ TySoNo.TTS.DR.    : num  60.1 59.7 58.2 60.2 61 ...
##  $ TSNH              : num  1.33e+11 1.33e+11 1.52e+11 1.69e+11 1.27e+11 ...
##  $ NoNganHan         : num  1.00e+11 1.10e+11 1.14e+11 1.26e+11 1.31e+11 ...
##  $ VCSH              : num  7.76e+10 7.58e+10 8.27e+10 8.49e+10 8.57e+10 ...
##  $ TSNH.TTS          : num  0.62 0.706 0.769 0.792 0.579 ...
##  $ HeSoDBTC.TTS.VCSH.: num  2.76 2.48 2.39 2.51 2.56 ...
##  $ TysoVCSH.TTS      : num  0.363 0.403 0.418 0.398 0.39 ...
##  $ NoNganHan.TongNo  : num  0.778 0.981 0.988 0.98 0.981 ...

Giới thiệu code: Đoạn code trên thực hiện các bước tiền xử lý dữ liệu cơ bản trước khi tiến hành phân tích:

  • Dòng read.csv() dùng để đọc dữ liệu từ file CSV “Data_ckv.csv” được lưu trong máy tính cá nhân.
  • Lệnh select(-starts_with(“X”)) trong gói dplyr có chức năng loại bỏ các cột có tên bắt đầu bằng ký tự “X”, cụ thể là từ “X tới X7” — đây là các cột phát sinh do lỗi trong quá trình xuất file từ Excel, chứa toàn giá trị NA.
  • Dòng data_ckv <- data_ckv[1:40, ] có chức năng giữ lại 40 dòng đầu tiên, loại bỏ các quan sát bị khuyết từ hàng 41 trở đi.
  • Hai lệnh cat(“- Số dòng:”, nrow(data_ckv), “”) và cat(“- Số cột:”, ncol(data_ckv), “”) in ra số lượng dòng và cột hiện tại sau khi xử lý. Trong đó, Hàm nrow() đếm số dòng (quan sát), ncol() đếm số cột (biến) trong bảng data_ckv
  • Cuối cùng, dim(data_ckv) trả về kích thước của bảng dữ liệu, còn str(data_ckv) hiển thị cấu trúc chi tiết gồm kiểu dữ liệu (numeric, character, factor…) và ví dụ một vài giá trị đầu tiên của mỗi biến.

Giới thiệu bộ dữ liệu: Bộ dữ liệu được sử dụng trong phân tích này được thu thập từ Báo cáo tài chính theo quý của Công ty Cổ phần CokyVina trong giai đoạn từ quý I năm 2015 đến quý IV năm 2024, gồm 40 quan sát tương ứng với 40 quý và 13 biến số tài chính chủ yếu. Trong đó, các biến phản ánh các khía cạnh khác nhau của tình hình tài chính doanh nghiệp như sau:

  • Tổng tài sản (TongTaiSan), Tổng nợ (Tongno) và Vốn chủ sở hữu (VCSH) thể hiện quy mô và cơ cấu tài chính của doanh nghiệp.
  • Tăng trưởng tổng tài sản (TangTruongTTS…) giúp theo dõi mức độ mở rộng hoạt động và hiệu quả sử dụng vốn qua thời gian.
  • Các tỷ số tài chính như Tỷ số nợ/Tổng tài sản (TySoNo.TTS.DR.), Tỷ lệ tài sản ngắn hạn/Tổng tài sản (TSNH.TTS), hay Tỷ lệ vốn chủ sở hữu/Tổng tài sản (TysoVCSH.TTS) phản ánh mức độ an toàn tài chính và khả năng thanh khoản.

b. Hiển thị 10 dòng đầu

head(data_ckv,10)
##    Quarter   TongTaiSan       Tongno   QuyMo TangTruongTTS... TySoNo.TTS.DR.
## 1  Q1/2015 214042197072 128626558166 26.0894               NA          60.09
## 2  Q2/2015 188283218987 112468623209 25.9612          -0.1203          59.73
## 3  Q3/2015 197872379506 115146229314 26.0109           0.0509          58.19
## 4  Q4/2015 213147896266 128276641196 26.0853           0.0772          60.18
## 5  Q1/2016 219783960176 134058235710 26.1159           0.0311          61.00
## 6  Q2/2016 230748108527 148634770669 26.1646           0.0499          64.41
## 7  Q3/2016 219402048429 135615211333 26.1142          -0.0492          61.81
## 8  Q4/2016 198243566957  23514990456 26.0128          -0.0964          11.86
## 9  Q1/2017 182493817080  96624713482 25.9300          -0.0794          52.95
## 10 Q2/2017 177278170496  94630594222 25.9010          -0.0286          53.38
##            TSNH    NoNganHan        VCSH TSNH.TTS HeSoDBTC.TTS.VCSH.
## 1  132727112434 100054839994 77612285106   0.6201             2.7578
## 2  132824453803 110368623209 75814595778   0.7055             2.4835
## 3  152110186350 113761295979 82726150192   0.7687             2.3919
## 4  168814373995 125703974027 84871228070   0.7920             2.5114
## 5  127348368660 131453862365 85725724446   0.5794             2.5638
## 6  127171356165 146030397324 82113337858   0.5511             2.8101
## 7  118252158383  93995786810 83786837096   0.5390             2.6186
## 8  111122743129    303132423 85419851209   0.5605             2.3208
## 9   95533409248  73412855449 85869103598   0.5235             2.1253
## 10  92598075484  72923736189 82647576274   0.5223             2.1450
##    TysoVCSH.TTS NoNganHan.TongNo
## 1        0.3626           0.7779
## 2        0.4027           0.9813
## 3        0.4181           0.9880
## 4        0.3982           0.9799
## 5        0.3900           0.9806
## 6        0.3559           0.9825
## 7        0.3819           0.6931
## 8        0.4309           0.0129
## 9        0.4705           0.7598
## 10       0.4662           0.7706

Lệnh head(data_ckv, 10) được sử dụng để hiển thị 10 dòng đầu tiên của bộ dữ liệu data_ckv, cụ thể:

  • Hàm head() dùng để xem nhanh cấu trúc và giá trị mẫu của dữ liệu.
  • Tham số thứ hai (10) cho biết số lượng dòng muốn hiển thị, mặc định nếu không ghi thì sẽ là 6 dòng đầu tiên.

1.2.Xử lý dữ liệu

a. Kiểm tra dữ liệu khuyết NA

# --- KIỂM TRA GIÁ TRỊ NA  ---
colSums(is.na(data_ckv))
##            Quarter         TongTaiSan             Tongno              QuyMo 
##                  0                  0                  0                  0 
##   TangTruongTTS...     TySoNo.TTS.DR.               TSNH          NoNganHan 
##                  1                  0                  0                  0 
##               VCSH           TSNH.TTS HeSoDBTC.TTS.VCSH.       TysoVCSH.TTS 
##                  0                  0                  0                  0 
##   NoNganHan.TongNo 
##                  0

Giải thích code: Để kiểm tra các giá trị khuyết, nhóm chúng em đã thực hiện lệnh sau:

  • Hàm is.na(data_ckv) tạo ra một ma trận logic có cùng kích thước với bộ dữ liệu “data_ckv”. Trong đó, mỗi ô có giá trị “TRUE” nếu phần tử đó bị thiếu dữ liệu (NA), và FALSE nếu có giá trị hợp lệ.
  • Hàm colSums() sau đó được sử dụng để tính tổng số giá trị TRUE (tức là số lượng NA) trong từng cột. Cụ thể, colSums() cộng tất cả các giá trị trong mỗi cột, với quy ước TRUE = 1, FALSE = 0.
  • Kết quả trả về là một vector, trong đó tên mỗi phần tử là tên biến, và giá trị tương ứng là số lượng NA của biến đó.

Kết quả: Từ bảng kết quả trên, ta thấy chỉ có một giá trị bị thiếu (NA) ở biến TangTruongTTS do biến “tăng trưởng tổng tài sản” được tính theo tỷ lệ thay đổi qua các quý, nên quý đầu tiên (Q1/2015) không có dữ liệu của quý trước để so sánh từ đó dẫn đến giá trị bị thiếu.

b. Xử lý dữ liệu bị khuyết(NA)

# --- THAY THẾ GIÁ TRỊ NA BẰNG TRUNG BÌNH CỘNG ---

# Tính giá trị trung bình của cột (bỏ qua NA)
mean_tts <- mean(data_ckv$TangTruongTTS..., na.rm = TRUE)

# Thay thế NA bằng giá trị trung bình
data_ckv$TangTruongTTS...[is.na(data_ckv$TangTruongTTS...)] <- mean_tts

# --- KIỂM TRA LẠI ---
cat("Số lượng NA còn lại trong từng cột:\n")
## Số lượng NA còn lại trong từng cột:
print(colSums(is.na(data_ckv)))
##            Quarter         TongTaiSan             Tongno              QuyMo 
##                  0                  0                  0                  0 
##   TangTruongTTS...     TySoNo.TTS.DR.               TSNH          NoNganHan 
##                  0                  0                  0                  0 
##               VCSH           TSNH.TTS HeSoDBTC.TTS.VCSH.       TysoVCSH.TTS 
##                  0                  0                  0                  0 
##   NoNganHan.TongNo 
##                  0

Giải thích code:

  • Lệnh mean(data_ckv$TangTruongTTS…, na.rm = TRUE) dùng để tính giá trị trung bình của biến TangTruongTTS…, trong đó tham số “na.rm = TRUE” giúp bỏ qua giá trị bị thiếu (NA) khi tính trung bình.
  • Câu lệnh data_ckv$TangTruongTTS…[is.na(…)] <- mean_tts có chức năng thay thế giá trị NA bằng trung bình vừa tính được, đảm bảo cột này không còn thiếu dữ liệu.
  • Cuối cùng, colSums(is.na(data_ckv)) kết hợp với print() được dùng để kiểm tra lại toàn bộ bộ dữ liệu xem còn giá trị NA nào không và in bảng kết quả giúp xác nhận bước xử lý đã hoàn tất.

Kết quả:

  • Biến Tăng trưởng tổng tài sản (%) có duy nhất một giá trị bị khuyết tại quý 1/2015. Do đây là quý đầu tiên trong chuỗi thời gian, giá trị NA được xử lý bằng phương pháp thay thế trung bình cộng, với giá trị thay thế là 0.003487179. Sau xử lý, toàn bộ bộ dữ liệu không còn giá trị bị khuyết.

c. Kiểm tra trùng lặp

# --- KIỂM TRA TRÙNG LẶP ---
duplicated_rows <- sum(duplicated(data_ckv))
cat("Số dòng trùng lặp:", duplicated_rows, "\n")
## Số dòng trùng lặp: 0

Nhóm chúng em sử dụng lệnh “um(duplicated(data_ckv))” để kiểm tra dữ liệu trùng lặp và kết quả đạt được là bộ dữ liệu không có xuất hiện trùng lặp.

d. Chuẩn hóa tên biến

# --- CHUẨN HÓA TÊN BIẾN ---

# Hiển thị tên biến gốc

names(data_ckv)
##  [1] "Quarter"            "TongTaiSan"         "Tongno"            
##  [4] "QuyMo"              "TangTruongTTS..."   "TySoNo.TTS.DR."    
##  [7] "TSNH"               "NoNganHan"          "VCSH"              
## [10] "TSNH.TTS"           "HeSoDBTC.TTS.VCSH." "TysoVCSH.TTS"      
## [13] "NoNganHan.TongNo"
# Dùng gsub() để loại bỏ ký tự đặc biệt, khoảng trắng, thay bằng dấu gạch dưới

names(data_ckv) <- gsub("[^[:alnum:]]+", "_", names(data_ckv))

# Đưa tên về chữ thường cho đồng nhất

names(data_ckv) <- tolower(names(data_ckv))

# Kiểm tra lại danh sách tên biến sau khi chuẩn hóa

names(data_ckv)
##  [1] "quarter"            "tongtaisan"         "tongno"            
##  [4] "quymo"              "tangtruongtts_"     "tysono_tts_dr_"    
##  [7] "tsnh"               "nonganhan"          "vcsh"              
## [10] "tsnh_tts"           "hesodbtc_tts_vcsh_" "tysovcsh_tts"      
## [13] "nonganhan_tongno"

Giải thích code:

  • Lệnh names(data_ckv) hiển thị danh sách tên biến gốc trong bộ dữ liệu.
  • Lệnh gsub(“[1]+”, “”, names(data_ckv)) dùng hàm thay thế ký tự đặc biệt. Trong đó, ”[2]+” nghĩa là mọi ký tự không phải chữ cái hoặc số (ví dụ: dấu chấm, khoảng trắng, ký tự đặc biệt) sẽ được thay thế bằng dấu gạch dưới “” để giúp tên biến dễ đọc hơn và phù hợp với chuẩn R.
  • Lệnh tolower(names(data_ckv)) chuyển toàn bộ tên biến sang chữ thường, giúp đồng nhất định dạng, tránh lỗi khi gọi tên biến.

Kết quả: Kết quả cho thấy tên biến đã được chuẩn hóa thành dạng nhất quán ví dụ như:

  • Biến “TongTaiSan” đổi thành “tongtaisan”
  • Biến “TySoNo.TTS.DR.” đổi thành “tysono_tts_dr_”
  • Biến “HeSoDBTC.TTS.VCSH.” đổi thành “hesodbtc_tts_vcsh_”

e. Chuyển đổi kiểu dữ liệu và kiểm tra kiểu dữ liệu của biến “Quarter”

# liệt kê dữ liệu cột quarter
unique(data_ckv$quarter)
##  [1] "Q1/2015" "Q2/2015" "Q3/2015" "Q4/2015" "Q1/2016" "Q2/2016" "Q3/2016"
##  [8] "Q4/2016" "Q1/2017" "Q2/2017" "Q3/2017" "Q4/2017" "Q1/2018" "Q2/2018"
## [15] "Q3/2018" "Q4/2018" "Q1/2019" "Q2/2019" "Q3/2019" "Q4/2019" "Q1/2020"
## [22] "Q2/2020" "Q3/2020" "Q4/2020" "Q1/2021" "Q2/2021" "Q3/2021" "Q4/2021"
## [29] "Q1/2022" "Q2/2022" "Q3/2022" "Q4/2022" "Q1/2023" "Q2/2023" "Q3/2023"
## [36] "Q4/2023" "Q1/2024" "Q2/2024" "Q3/2024" "Q4/2024"

Để xem dữ liệu cột “Quarter”, nhóm chúng em dùng lệnh “unique(data_ckv$quarter)” để liệt kê chi tiết dữ liệu lấy từ cột “Quarter” ở trong bảng có tên “data_ckv”.

# --- TÁCH QUÝ VÀ NĂM TỪ CỘT QUARTER ---
library(stringr)

data_ckv <- data_ckv %>%
  mutate(
    quarter = as.character(quarter),              # ép kiểu để xử lý regex
    quarter = str_trim(quarter),                  # xóa khoảng trắng thừa nếu có
    Quarter = str_replace_all(quarter, "⁄", "/"), # đổi ký tự chia đặc biệt thành '/'
    qtr  = as.integer(str_extract(quarter, "(?<=Q)\\d")),   # lấy số quý
    year = as.integer(str_extract(quarter, "(?<=/)\\d{4}")) # lấy năm
  )

# Kiểm tra kết quả
data_ckv %>% select(quarter, qtr, year) %>% head(10)
##    quarter qtr year
## 1  Q1/2015   1 2015
## 2  Q2/2015   2 2015
## 3  Q3/2015   3 2015
## 4  Q4/2015   4 2015
## 5  Q1/2016   1 2016
## 6  Q2/2016   2 2016
## 7  Q3/2016   3 2016
## 8  Q4/2016   4 2016
## 9  Q1/2017   1 2017
## 10 Q2/2017   2 2017

Ở phần này, mục đích nhằm tách cột Quarter thành 2 cột riêng thể hiện Quý và Năm tương ứng, nhóm chúng em đã thực hiện các thao tác sau đây:

  • as.character(quarter): Ép kiểu về character giúp dễ xử lý chuỗi.
  • str_trim(quarter): Xóa khoảng trắng dư thừa ở đầu hoặc cuối chuỗi,tránh lỗi khi trích xuất thông tin.
  • str_replace_all(quarter, “⁄”, “/”): Thay các ký tự chia lạ (⁄) bằng ký tự / chuẩn để regex nhận diện chính xác.
  • str_extract(quarter, “(?<=Q)\d”): trong đó (?<=Q)\d có nghĩa là “lấy chữ số xuất hiện ngay sau chữ Q”. Kết quả là số quý (1–4).
  • str_extract(quarter, “(?<=/)\d{4}”): trong đó (?<=/)\d{4} có nghĩa là “lấy 4 chữ số xuất hiện ngay sau dấu /”.
  • data_ckv %>% select(quarter, qtr, year) %>% head(10): ở đây nhóm em kết hợp chọn bảng data_ckv và chỉ lấy quarter, qtr, year bằng lệnh select kết hợp hiển thị 10 dòng đầu bằng lệnh head.

1.3. Tổng kết

mo_ta_bien <- data.frame(
  Bien = c("quarter", "tongtaisan", "tongno", "quymo", 
           "tangtruongtts_", "tysono_tts_dr_", "tsnh", "nonganhan", 
           "vcsh", "tsnh_tts", "hesodbtc_tts_vcsh_", 
           "tysovcsh_tts", "nonganhan_tongno"),
  
  Kieu_Du_Lieu = c("character", "numeric", "numeric", "numeric",
                   "numeric", "numeric", "numeric", "numeric",
                   "numeric", "numeric", "numeric",
                   "numeric", "numeric"),
  
  Y_Nghia = c(
    "Quý quan sát (theo dạng thời gian Q1, Q2, Q3, Q4 hằng năm)",
    "Tổng tài sản của doanh nghiệp trong kỳ",
    "Tổng nợ phải trả trong kỳ",
    "Quy mô doanh nghiệp (ước tính qua tổng tài sản log hoặc gốc)",
    "Tốc độ tăng trưởng tổng tài sản so với kỳ trước",
    "Tỷ số nợ trên tổng tài sản (Debt Ratio)",
    "Tài sản ngắn hạn của doanh nghiệp",
    "Nợ ngắn hạn (phải trả trong vòng 1 năm)",
    "Vốn chủ sở hữu (Equity)",
    "Tỷ lệ tài sản ngắn hạn trên tổng tài sản",
    "Hệ số đảm bảo tài chính giữa tổng tài sản và vốn chủ sở hữu",
    "Tỷ số vốn chủ sở hữu trên tổng tài sản",
    "Tỷ lệ nợ ngắn hạn trên tổng nợ"
  )
)

# Hiển thị bảng 
mo_ta_bien %>%
  kbl(caption = "Bảng 1.1: Mô tả các biến trong bộ dữ liệu CKV", 
      align = c('c', 'c', 'l'),
      col.names = c("Biến", "Kiểu dữ liệu", "Ý nghĩa")) %>%
  kable_paper(full_width = F, lightable_options = "striped") %>%
  column_spec(1, bold = TRUE, width = "5em") %>%
  column_spec(2, width = "6em") %>%
  column_spec(3, width = "30em") %>%
  row_spec(0, bold = TRUE, background = "#BFD3E6")
Bảng 1.1: Mô tả các biến trong bộ dữ liệu CKV
Biến Kiểu dữ liệu Ý nghĩa
quarter character Quý quan sát (theo dạng thời gian Q1, Q2, Q3, Q4 hằng năm)
tongtaisan numeric Tổng tài sản của doanh nghiệp trong kỳ
tongno numeric Tổng nợ phải trả trong kỳ
quymo numeric Quy mô doanh nghiệp (ước tính qua tổng tài sản log hoặc gốc)
tangtruongtts_ numeric Tốc độ tăng trưởng tổng tài sản so với kỳ trước
tysono_tts_dr_ numeric Tỷ số nợ trên tổng tài sản (Debt Ratio)
tsnh numeric Tài sản ngắn hạn của doanh nghiệp
nonganhan numeric Nợ ngắn hạn (phải trả trong vòng 1 năm)
vcsh numeric Vốn chủ sở hữu (Equity)
tsnh_tts numeric Tỷ lệ tài sản ngắn hạn trên tổng tài sản
hesodbtc_tts_vcsh_ numeric Hệ số đảm bảo tài chính giữa tổng tài sản và vốn chủ sở hữu
tysovcsh_tts numeric Tỷ số vốn chủ sở hữu trên tổng tài sản
nonganhan_tongno numeric Tỷ lệ nợ ngắn hạn trên tổng nợ

Sau khi tiền xử lý dữ liệu, chúng em tạo bảng tổng hợp kết quả và mô tả ý nghĩa các biến, cụ thể:

  • Chúng em sử dụng data.frame() để liệt kê tên biến (Bien), kiểu dữ liệu (Kieu_Du_Lieu) và ý nghĩa từng biến (Y_Nghia).
    • Thư viện kableExtra được dùng để trình bày bảng đẹp mắt: kbl() tạo bảng cơ bản với tiêu đề và căn chỉnh cột, kable_paper() thêm style dạng “striped”, column_spec() điều chỉnh độ rộng và in đậm cột, row_spec() định dạng hàng tiêu đề với màu nền và chữ đậm.
    • Kết quả là một bảng tổng hợp trực quan, giúp người đọc dễ dàng nắm được cấu trúc và nội dung các biến trong bộ dữ liệu CKV.

CHƯƠNG 2. PHÂN TÍCH DỮ LIỆU

2.1. Thống kê mô tả

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


  1. :alnum:↩︎

  2. :alnum:↩︎