PHẦN 1: PHÂN TÍCH TỘI PHẠM USA

CHƯƠNG 1: GIỚI THIỆU BỘ DỮ LIỆU

1. Đọc dữ liệu từ file Excel

1. crime <- read_xlsx("D:/ngongulaptrinh/Crime_Data_from_2020_to_Present.xlsx")

Giải thích
Kỹ thuật:
- read_excel() là hàm từ gói readxl dùng để đọc dữ liệu Excel (.xls hoặc .xlsx).
- “D:/ngongulaptrinh/Crime_Data_from_2020_to_Present.xlsx” là đường dẫn tuyệt đối tới file dữ liệu của bạn.
Ý nghĩa: để nạp dữ liệu dùng để phân tích.

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

1. nrow(crime)  
## [1] 944235
1. ncol(crime)  
## [1] 28

Giải thích
Kỹ thuật: hàm dim(crime) trả về số hàng và số cột của bảng dữ liệu.
Ý nghĩa: có 944235 số vụ và 28 biến.

3. Xem 6 dòng đầu

1. head(crime)

Giải thích
Kỹ thuật: hàm head(crime) để xem 6 dòng đầu của bộ dữ liệu
Ý nghĩa: xem tổng quan để biết cấu trúc dữ liệu, tên các cột, kiểu dữ liệu từng cột, và dữ liệu trông như thế nào ở phần đầu.

4. Xem 6 dòng cuối

1. tail(crime)

Giải thích
Kỹ thuật: hàm tail(crime) để xem 6 dòng cuối của bộ dữ liệu
Ý nghĩa: xem tổng qua để phát hiện có bị thiếu dữ liệu, lỗi nhập liệu, hay dòng trống ở cuối hay không.

5. Xem tên các biến

1. names(crime)
##  [1] "DR_NO"          "Date Rptd"      "DATE OCC"       "TIME OCC"      
##  [5] "AREA"           "AREA NAME"      "Rpt Dist No"    "Part 1-2"      
##  [9] "Crm Cd"         "Crm Cd Desc"    "Mocodes"        "Vict Age"      
## [13] "Vict Sex"       "Vict Descent"   "Premis Cd"      "Premis Desc"   
## [17] "Weapon Used Cd" "Weapon Desc"    "Status"         "Status Desc"   
## [21] "Crm Cd 1"       "Crm Cd 2"       "Crm Cd 3"       "Crm Cd 4"      
## [25] "LOCATION"       "Cross Street"   "LAT"            "LON"

Giải thích
Kỹ thuật: hàm names() dùng để xem tên các cột có trong bộ dữ liệu.
Ý nghĩa: xem tên các biến có trong dữ liệu

5.1 Mô tả các biến trong bộ dữ liệu

Bộ dữ liệu Crime_Data_from_2020_to_Present gồm 28 biến (cột) và 944235 quan sát (dòng).
Mỗi dòng tương ứng với một vụ phạm tội được ghi nhận bởi Sở Cảnh sát Los Angeles (LAPD).
Bảng dưới đây mô tả ý nghĩa của từng biến:

Tên biến Tên tiếng Việt Giải thích / Ý nghĩa
DR_NO Mã vụ án Mã định danh duy nhất cho mỗi vụ phạm tội.
Date Rptd Ngày báo cáo Ngày vụ việc được báo cáo cho cảnh sát.
DATE OCC Ngày xảy ra vụ việc Ngày thực tế xảy ra tội phạm.
TIME OCC Giờ xảy ra vụ việc Thời gian trong ngày (định dạng 24h).
AREA Mã khu vực Mã số nội bộ cho khu vực tuần tra.
AREA NAME Tên khu vực Tên khu vực cảnh sát phụ trách (ví dụ: Central, Hollywood, SouthWest…).
Rpt Dist No Mã quận báo cáo Mã quận hoặc phường nơi vụ việc được báo cáo.
Part 1-2 Nhóm tội phạm Phân loại tội phạm: Part 1 (nghiêm trọng), Part 2 (nhẹ).
Crm Cd Mã tội phạm Mã số cho loại tội phạm cụ thể.
Crm Cd Desc Mô tả tội phạm Tên mô tả loại tội phạm (vd: BURGLARY, ROBBERY…).
Mocodes Mã thủ đoạn phạm tội “Modus Operandi” – mô tả hoặc mã hóa cách thức gây án.
Vict Age Tuổi nạn nhân Tuổi của nạn nhân.
Vict Sex Giới tính nạn nhân M = Nam, F = Nữ, X = Khác/Không xác định.
Vict Descent Dân tộc nạn nhân Mã dân tộc/nền gốc (H = Hispanic, W = White, B = Black, A = Asian, …).
Premis Cd Mã địa điểm Mã loại địa điểm xảy ra tội phạm.
Premis Desc Mô tả địa điểm Mô tả chi tiết địa điểm (vd: STREET, RESIDENCE, PARKING LOT).
Weapon Used Cd Mã vũ khí Mã loại vũ khí được sử dụng (nếu có).
Weapon Desc Mô tả vũ khí Mô tả cụ thể loại vũ khí (vd: HAND GUN, KNIFE, NONE).
Status Mã trạng thái vụ án Mã trạng thái (IC = Đang điều tra, AO = Bắt người trưởng thành, JO = Bắt trẻ vị thành niên…).
Status Desc Mô tả trạng thái vụ án Diễn giải chi tiết trạng thái điều tra.
Crm Cd 1 Mã tội bổ sung 1 Tội phụ thứ nhất (nếu vụ án có nhiều hành vi).
Crm Cd 2 Mã tội bổ sung 2 Tội phụ thứ hai.
Crm Cd 3 Mã tội bổ sung 3 Tội phụ thứ ba.
Crm Cd 4 Mã tội bổ sung 4 Tội phụ thứ tư.
LOCATION Địa chỉ Địa điểm xảy ra vụ việc (mô tả ngắn hoặc địa chỉ).
Cross Street Đường cắt Tên đường giao nhau gần vị trí xảy ra vụ việc.
LAT Vĩ độ Tọa độ địa lý (latitude).
LON Kinh độ Tọa độ địa lý (longitude).

Nhận xét:
Một số biến có tỷ lệ giá trị bị thiếu khá cao (như Weapon Used Cd, Crm Cd 3, Cross Street, …).
Điều này cần được xem xét khi làm sạch dữ liệu trước khi phân tích.

6. Xem bộ dữ liệu

1. View(crime)

Giải thích Để xem nhanh toàn bộ và giúp hiểu tổng quan về dữ liệu.

7. Kiểm tra kiểu dữ liệu từng cột

1. table(map_chr(crime, ~ class(.x)[1]))
## 
## character   logical   numeric   POSIXct 
##        13         1        12         2

Giải thích
Kỹ thuật: hàm sapply trong R để kiểm tra loại dữ liệu của từng cột trong một bộ dữ liệu, giúp tổng quan về cấu trúc dữ liệu của bộ dữ liệu.
Kết quả:
- Các biến kiểu số (numeric): DR_NO, TIME OCC, AREA, Rpt Dist No, Part 1-2, Crm Cd, Vict Age, Premis Cd, Weapon Used Cd, Crm Cd 1, Crm Cd 2, Crm Cd 3.
- Các biến kiểu ngày giờ (POSIXct, POSIXt): Date Rptd, DATE OCC.
- Các biến kiểu chuỗi ký tự (character): AREA NAME, Crm Cd Desc, Mocodes, Vict Sex, Vict Descent, Premis Desc, Weapon Desc, Status, Status Desc, LOCATION, Cross Street, LAT, LON. - Một biến kiểu logic (logical): Crm Cd 4.

8. Xem giá trị thiếu của từng cột

1. colSums(is.na(crime))
##          DR_NO      Date Rptd       DATE OCC       TIME OCC           AREA 
##              0              0              0              0              0 
##      AREA NAME    Rpt Dist No       Part 1-2         Crm Cd    Crm Cd Desc 
##              0              0              0              0              0 
##        Mocodes       Vict Age       Vict Sex   Vict Descent      Premis Cd 
##         133099              0         126595         126605             10 
##    Premis Desc Weapon Used Cd    Weapon Desc         Status    Status Desc 
##            567         619758         619758              0              0 
##       Crm Cd 1       Crm Cd 2       Crm Cd 3       Crm Cd 4       LOCATION 
##             11         875977         941954         944171              0 
##   Cross Street            LAT            LON 
##         796643              0              0

Giải thích
Kỹ thuật:
- Hàm is.na() trả về TRUE/FALSE cho giá trị bị thiếu trong dataframe.
- Đếm số giá trị thiếu toàn bộ dữ liệu: sum(is.na(df))
- Đếm số giá trị thiếu theo cột: colSums(is.na(df))
Ý nghĩa:
- Giá trị bị thiếu (NA) trong các cột dữ liệu có thể phát sinh do nhiều nguyên nhân và mang ý nghĩa quan trọng như sau:
- Thiếu dữ liệu gốc: Một số thông tin không được ghi nhận hoặc không có tại thời điểm thu thập dữ liệu, ví dụ như “Mocodes”, “Vict Sex” hoặc “Weapon Used Cd” có nhiều giá trị thiếu do chưa được khai báo hoặc không áp dụng trong trường hợp đó.
- Không có hoặc không xác định: Có thể một số trường hợp không có giá trị phù hợp, ví dụ như nạn nhân không cung cấp thông tin giới tính hoặc loại vũ khí không được ghi nhận.
- Lỗi hoặc thiếu sót trong quá trình nhập liệu, thu thập hoặc truyền file dữ liệu.
- Kiểu dữ liệu đặc thù: Một số cột (như “Premis Cd”) có ít giá trị thiếu có thể là do đặc điểm của bộ dữ liệu hoặc yêu cầu cụ thể trong xử lý.

9. Xem các dữ liệu bị trùng lặp

1. sum(duplicated(crime))     
## [1] 0

Giải thích
Kỹ thuật:
-Hàm duplicated() trả về TRUE cho những dòng dữ liệu bị trùng
-Xem tổng số bản ghi trùng lặp: sum(duplicated(crime))
-Lấy các dòng trùng lặp: df\[duplicated(crime), \]
Kết quả: cho thấy không có bản ghi vụ án nào bị trùng.

10. Kiểm tra kiểu dữ liệu các cột năm

1. table(crime$`Status`) 
## 
##     AA     AO     CC     IC     JA     JO 
##  82182 102928      5 754264   3102   1754

CHƯƠNG 2: XỬ LÝ DỮ LIỆU THÔ VÀ MÃ HÓA

1. Chọn dữ liệu để phân tích

1. crime_selected <- crime %>%   select(`Crm Cd Desc`, `Premis Desc`, `Date Rptd`, `Part 1-2`,`Vict Sex`, `Vict Age`, AREA, Status, `Rpt Dist No`, `Crm Cd 1`, `Crm Cd 2`, `Crm Cd 3`, `Crm Cd 4`)
2. names(crime_selected)
##  [1] "Crm Cd Desc" "Premis Desc" "Date Rptd"   "Part 1-2"    "Vict Sex"   
##  [6] "Vict Age"    "AREA"        "Status"      "Rpt Dist No" "Crm Cd 1"   
## [11] "Crm Cd 2"    "Crm Cd 3"    "Crm Cd 4"

Giải thích
Kỹ thuật:
- Dòng 1: Cho phép chọn chính xác các cột cần thiết.
- Dòng 1-3: Các tên cột chứa khoảng trắng hoặc ký tự đặc biệt (như Crm Cd 1) cần được đặt trong dấu `.
Ý nghĩa:
Việc lọc các cột này giúp tập trung vào thông tin mô tả tội phạm, nạn nhân và khu vực báo cáo, đồng thời thêm các mã tội phạm (Crm Cd 1–4) và trạng thái xử lý vụ án (Status). Điều này hữu ích khi bạn muốn phân tích mức độ nghiêm trọng, đặc điểm nạn nhân, hoặc sự phân bố địa lý của tội phạm.

2. Đổi tên cột sang Tiếng Việt

1. crime_renamed <- crime_selected %>%
2.   rename( Mo_ta_Toi_Pham = `Crm Cd Desc`, Mo_ta_Dia_Diem = `Premis Desc`,
3.     Ngay_Bao_Cao = `Date Rptd`, Phan_Loai = `Part 1-2`,
4.     Gioi_Tinh_Nan_Nhan = `Vict Sex`, Tuoi_Nan_Nhan = `Vict Age`,
5.     Ma_Khu_Vuc = AREA, Trang_Thai = Status,
6.     So_Don_Vi_Bao_Cao = `Rpt Dist No`, Ma_Toi_Pham_1 = `Crm Cd 1`,  
7.     Ma_Toi_Pham_2 = `Crm Cd 2`, Ma_Toi_Pham_3 = `Crm Cd 3`, 
8.     Ma_Toi_Pham_4 = `Crm Cd 4`)
9. head(crime_renamed)

Giải thích
Kỹ thuât:
- Dòng 1: Tạo bản sao mới của dữ liệu có tên là crime_renamed — điều này đảm bảo bạn không ghi đè dữ liệu gốc (crime_selected).
- Dòng 2: Hàm này thuộc gói dplyr, dùng để đặt lại tên cột.
Cú pháp: tên_mới = tên_cũ (đảo ngược so với select()).
Dấu `: Bắt buộc khi tên cột chứa khoảng trắng hoặc ký tự đặc biệt (Crm Cd 1, Part 1-2, v.v.) — nếu không R sẽ báo lỗi cú pháp.
- Dòng 10: Hiển thị 6 dòng đầu của bảng đã đổi tên để kiểm tra nhanh.
Ý nghĩa:
Đây là bước quan trọng trong giai đoạn tiền xử lý dữ liệu (data preprocessing). Việc đổi tên cột giúp:
+ Chuẩn hóa ngôn ngữ cho phù hợp với ngữ cảnh phân tích xã hội học, tội phạm học.
+ Dễ dàng gọi biến trong phân tích mô hình (hồi quy, tương quan, phân cụm,…).
+ Giúp người đọc báo cáo hiểu rõ hơn mà không cần đối chiếu với mô tả tiếng Anh gốc.

3. Làm sạch và chuẩn hóa biến “Gioi_Tinh_Nan_Nhan” và “Ma_Toi_Pham”

1. crime_cleaned <- crime_renamed %>%
2.   mutate( Gioi_Tinh_Nan_Nhan = ifelse(Gioi_Tinh_Nan_Nhan == "-" | is.na(Gioi_Tinh_Nan_Nhan), "X", Gioi_Tinh_Nan_Nhan)  ,
3.     Ma_Toi_Pham_1 = ifelse(is.na(Ma_Toi_Pham_1), 0, Ma_Toi_Pham_1),
4.     Ma_Toi_Pham_2 = ifelse(is.na(Ma_Toi_Pham_2), 0, Ma_Toi_Pham_2),
5.     Ma_Toi_Pham_3 = ifelse(is.na(Ma_Toi_Pham_3), 0, Ma_Toi_Pham_3),
6.     Ma_Toi_Pham_4 = ifelse(is.na(Ma_Toi_Pham_4), 0, Ma_Toi_Pham_4)  )
7. head(crime_cleaned)

Giải thích
Kỹ thuật:
- Dòng 2: (Giá_trị_mới, giữ_nguyên): thay giá trị bị thiếu.
+ Gioi_Tinh_Nan_Nhan: Chuẩn hóa dữ liệu, thay “-” hoặc NA thành “X” (giới tính không xác định).
+ Ma_Toi_Pham_1–4: nếu NA → 0 (không có tội bổ sung).
- Dòng 8: xem 6 dòng đầu để kiểm tra.
Ý nghĩa:
Trong phân tích tội phạm học hoặc xã hội học, việc thay thế NA bằng ký hiệu định danh:
+ Giúp duy trì độ toàn vẹn dữ liệu — không mất mẫu do NA.
+ Cho phép phân tích định tính hoặc phân nhóm dễ dàng hơn (ví dụ: nhóm “không xác định giới tính” vẫn được thống kê riêng).
+ Với các mã tội phạm phụ (Ma_Toi_Pham_2–4), giá trị “0” phản ánh chính xác bản chất “không có tội bổ sung”, chứ không phải dữ liệu bị thiếu.

4. Tạo thêm cột khu vực

1. crime_cleaned <- crime_cleaned %>%   mutate(
2.     Khu_Vuc = case_when(
3.       Ma_Khu_Vuc == 1  ~ "Central", Ma_Khu_Vuc == 2  ~ "Rampart",
4.       Ma_Khu_Vuc == 3  ~ "Southwest", Ma_Khu_Vuc == 4  ~ "Hollenbeck",
5.       Ma_Khu_Vuc == 5  ~ "Harbor", Ma_Khu_Vuc == 6  ~ "Hollywood",
6.       Ma_Khu_Vuc == 7  ~ "Wilshire", Ma_Khu_Vuc == 8  ~ "West LA",
7.       Ma_Khu_Vuc == 9  ~ "Van Nuys", Ma_Khu_Vuc == 10 ~ "West Valley",
8.       Ma_Khu_Vuc == 11 ~ "Northeast", Ma_Khu_Vuc == 12 ~ "77th Street",
9.       Ma_Khu_Vuc == 13 ~ "Newton", Ma_Khu_Vuc == 14 ~ "Pacific",
10.       Ma_Khu_Vuc == 15 ~ "N Hollywood", Ma_Khu_Vuc == 16 ~ "Foothill",
11.       Ma_Khu_Vuc == 17 ~ "Devonshire", Ma_Khu_Vuc == 18 ~ "Southeast",
12.       Ma_Khu_Vuc == 19 ~ "Mission", Ma_Khu_Vuc == 20 ~ "Olympic",
13.       Ma_Khu_Vuc == 21 ~ "Topanga", TRUE ~ "Không xác định"    )  )
14. head(crime_cleaned %>% select(Ma_Khu_Vuc, Khu_Vuc))

Giải thích
Kỹ thuật:
- Dòng 1: thêm hoặc cập nhật biến mới.
- Dòng 2: thay thế nhiều điều kiện kiểu “nếu… thì…”.
- Dòng 3-13: Mỗi dòng ánh xạ (Ma_Khu_Vuc == 1 ~ “Central”) nghĩa là:
+ Nếu mã khu vực bằng 1 → điền “Central”.
+ TRUE ~ “Không xác định” là mặc định nếu mã không khớp với danh sách. Ý nghĩa:
- Biến Khu_Vuc giúp chuyển mã định danh thành tên địa lý dễ hiểu.
- Dùng trong phân tích không gian (crime mapping), mô tả khu vực có tỷ lệ tội phạm cao.
- Giúp trực quan hóa dữ liệu (ví dụ: biểu đồ tội phạm theo khu vực).

5. Chuẩn hóa và mở rộng thông tin mô tả tội bổ sung (2–4)

1. map_crime <- crime_cleaned %>%
2.   select(Ma_Toi_Pham_1, Mo_ta_Toi_Pham) %>%
3.   filter(!is.na(Ma_Toi_Pham_1)) %>%
4.   distinct()
5. map_vec <- map_crime$Mo_ta_Toi_Pham
6. names(map_vec) <- as.character(map_crime$Ma_Toi_Pham_1)
7. crime_extended <- crime_cleaned %>%
8.   mutate( `Toi Bo Sung 2` = ifelse( Ma_Toi_Pham_2 == 0, 
9.       "Không có tội bổ sung", map_vec[as.character(Ma_Toi_Pham_2)]    ),
10.     `Toi Bo Sung 3` = ifelse( Ma_Toi_Pham_3 == 0, "Không có tội bổ sung",
11.       map_vec[as.character(Ma_Toi_Pham_3)]    ),
12.     `Toi Bo Sung 4` = ifelse( Ma_Toi_Pham_4 == 0, "Không có tội bổ sung",
13.       map_vec[as.character(Ma_Toi_Pham_4)]    )  ) %>%
14.   mutate( `Toi Bo Sung 2` = ifelse(is.na(`Toi Bo Sung 2`) & Ma_Toi_Pham_2 != 0, "Không xác định", `Toi Bo Sung 2`),
15.     `Toi Bo Sung 3` = ifelse(is.na(`Toi Bo Sung 3`) & Ma_Toi_Pham_3 != 0, "Không xác định", `Toi Bo Sung 3`),
16.     `Toi Bo Sung 4` = ifelse(is.na(`Toi Bo Sung 4`) & Ma_Toi_Pham_4 != 0, "Không xác định", `Toi Bo Sung 4`)  )
17. crime_extended %>%   select(Ma_Toi_Pham_1:Ma_Toi_Pham_4,
18.          Mo_ta_Toi_Pham, `Toi Bo Sung 2`, `Toi Bo Sung 3`, `Toi Bo Sung 4`) %>%
19.   head()

Ghi chú

Mô tả Ghi chú
999 Non-Criminal (Other) Ghi nhận sự kiện phi tội phạm khác, không có đối tượng cụ thể
998 Non-Criminal (Subject Specified) Có liên quan đến một người cụ thể (subject specified)

Vì vậy được liệt kê vô nhóm “không xác định”.

Giải thích
1. Tạo bảng ánh xạ (mapping table):
Dùng select() và distinct() để lấy danh sách duy nhất giữa mã (Ma_Toi_Pham_1) và mô tả (Mo_ta_Toi_Pham).
→ Đây là “từ điển nội bộ” giúp dịch mã số thành mô tả có nghĩa.

  1. Tạo vector tra cứu:
    Dùng kỹ thuật named vector — đặt names() là mã tội, giá trị là mô tả.
    Khi gọi map_vec\["420"\], R sẽ trả về mô tả của tội có mã 420.
    → Cách này nhanh và tiết kiệm bộ nhớ hơn so với left_join() nhiều lần.

  2. Tạo cột mới “Tội bổ sung 2–4”:
    Với mutate():

  • Nếu mã tội phụ = 0 → “Không có tội bổ sung” (đã được chuẩn hóa ở bước trước).
  • Nếu mã ≠ 0 → tra mô tả tương ứng từ map_vec.
  1. Gán nhãn cho giá trị không khớp:
    Nếu mã ≠ 0 mà không tìm được mô tả, gán nhãn “Không xác định” để tránh mất thông tin và giúp phát hiện lỗi mã hóa.

  2. Kiểm tra kết quả:
    Dùng select() + head() để xem nhanh 6 dòng đầu, đảm bảo việc ánh xạ hoạt động chính xác.

Ý nghĩa:

Nội dung Ý nghĩa
Chuẩn hóa dữ liệu định tính Giúp mô tả tội danh rõ ràng, dễ hiểu, thay vì chỉ dựa vào mã số.
Tạo biến mở rộng Các cột “Tội bổ sung 2–4” giúp phân tích đa tội danh trong cùng một vụ việc.
Duy trì toàn vẹn dữ liệu Không mất dữ liệu do NA, mà quy ước rõ ràng: “Không có tội bổ sung” hoặc “Không xác định”.
Tối ưu hiệu năng xử lý Cách ánh xạ bằng vector nhanh hơn nhiều so với phép nối (join) dữ liệu lớn.
Hỗ trợ phân tích nâng cao Dễ dàng thống kê, mô hình hóa hoặc trực quan hóa mối quan hệ giữa tội chính và tội phụ.

6. Phân tổ nhóm tuổi

1. crime_extended <- crime_extended %>%
2.   mutate(
3.     Nhom_Tuoi = case_when(
4.       Tuoi_Nan_Nhan < 10                    ~ "Dưới 10 tuổi",
5.       Tuoi_Nan_Nhan >= 10 & Tuoi_Nan_Nhan < 18 ~ "Vị thành niên (10–17)",
6.       Tuoi_Nan_Nhan >= 18 & Tuoi_Nan_Nhan < 30 ~ "Thanh niên (18–29)",
7.       Tuoi_Nan_Nhan >= 30 & Tuoi_Nan_Nhan < 45 ~ "Trưởng thành trẻ (30–44)",
8.       Tuoi_Nan_Nhan >= 45 & Tuoi_Nan_Nhan < 60 ~ "Trung niên (45–59)",
9.       Tuoi_Nan_Nhan >= 60 & Tuoi_Nan_Nhan < 75 ~ "Cao niên (60–74)",
10.       Tuoi_Nan_Nhan >= 75                     ~ "Già (75+)",
11.       TRUE ~ "Không xác định"    )  )
12. print(crime_extended)
## # A tibble: 944,235 × 18
##    Mo_ta_Toi_Pham                   Mo_ta_Dia_Diem Ngay_Bao_Cao        Phan_Loai
##    <chr>                            <chr>          <dttm>                  <dbl>
##  1 VEHICLE - STOLEN                 STREET         2020-01-03 00:00:00         1
##  2 BURGLARY FROM VEHICLE            BUS STOP/LAYO… 2020-09-02 00:00:00         1
##  3 BIKE - STOLEN                    MULTI-UNIT DW… 2020-11-11 00:00:00         1
##  4 SHOPLIFTING-GRAND THEFT ($950.0… CLOTHING STORE 2023-10-05 00:00:00         1
##  5 THEFT OF IDENTITY                SIDEWALK       2022-08-18 00:00:00         2
##  6 THEFT OF IDENTITY                SINGLE FAMILY… 2023-04-04 00:00:00         2
##  7 THEFT OF IDENTITY                MULTI-UNIT DW… 2023-04-04 00:00:00         2
##  8 THEFT OF IDENTITY                CELL PHONE ST… 2022-07-22 00:00:00         2
##  9 THEFT OF IDENTITY                CYBERSPACE     2023-04-28 00:00:00         2
## 10 BATTERY - SIMPLE ASSAULT         MULTI-UNIT DW… 2020-12-31 00:00:00         2
## # ℹ 944,225 more rows
## # ℹ 14 more variables: Gioi_Tinh_Nan_Nhan <chr>, Tuoi_Nan_Nhan <dbl>,
## #   Ma_Khu_Vuc <dbl>, Trang_Thai <chr>, So_Don_Vi_Bao_Cao <dbl>,
## #   Ma_Toi_Pham_1 <dbl>, Ma_Toi_Pham_2 <dbl>, Ma_Toi_Pham_3 <dbl>,
## #   Ma_Toi_Pham_4 <dbl>, Khu_Vuc <chr>, `Toi Bo Sung 2` <chr>,
## #   `Toi Bo Sung 3` <chr>, `Toi Bo Sung 4` <chr>, Nhom_Tuoi <chr>

Giải thích
Kỹ thuật
- Dòng 2: tạo biến mới Nhom_Tuoi trong bảng crime_extended.
- Dòng 3: cho phép gán nhãn theo điều kiện logic phức tạp.   - Điều kiện phân loại:
+ < 10: trẻ em nhỏ.
+ 10–17: vị thành niên (tuổi chưa đủ trách nhiệm hình sự đầy đủ).
+ 18–29: thanh niên (tuổi lao động, hoạt động xã hội cao).
+ 30–44: trưởng thành trẻ.
+ 45–59: trung niên.
+ 60–74: cao niên.
+ ≥75: người già.
+ NA hoặc giá trị bất thường → “Không xác định”.
- Dòng 12: xem kết quả vừa tạo. Ý nghĩa:

Mục tiêu Ý nghĩa
Chuẩn hóa dữ liệu nhân khẩu học Biến tuổi liên tục thành nhóm giúp dễ phân tích mô hình hoặc thống kê tần suất.
Phân tích xã hội học Có thể xác định nhóm tuổi nào thường là nạn nhân nhiều nhất (ví dụ: thanh niên, trung niên…).
Trực quan hóa Dễ tạo biểu đồ cột, biểu đồ phân bố nạn nhân theo nhóm tuổi.
Chuẩn bị cho mô hình hóa Biến Nhom_Tuoi có thể được dùng trong mô hình hồi quy logistic hoặc cây quyết định (decision tree).

7. Kiểm tra biến mô tả địa điểm

7.1. Xử lý dữ liệu bị thiếu ở cột ” Mo_Ta_Dia_Diem”

1. crime_extended$Mo_ta_Dia_Diem <- ifelse(is.na(crime_extended$Mo_ta_Dia_Diem),
2.                  "Không xác định", crime_extended$Mo_ta_Dia_Diem)

Giải thích
Kỹ thuật:
- is.na() → kiểm tra từng dòng xem giá trị có bị thiếu (NA) không.
- ifelse(điều_kiện, giá_trị_nếu_đúng, giá_trị_nếu_sai) → gán giá trị mới tùy theo điều kiện.
- “Không xác định” → thay thế cho những dòng bị NA.
- Còn lại (crime_extended$Mo_ta_Dia_Diem) → giữ nguyên giá trị có sẵn.

Kết quả: cột Mo_ta_Dia_Diem không còn NA, mà các ô trống được thay bằng “Không xác định”.

8. Mô tả trạng thái bắt giữ

1. crime_extended <- crime_extended %>% mutate(
2.     Tinh_Trang_Bat_Giu = case_when(
3.         Trang_Thai == "AA" ~ "Đã bắt – Người trưởng thành",
4.         Trang_Thai == "AO" ~ "Đã bắt – Người chưa trưởng thành",
5.         Trang_Thai == "CC" ~ "Chưa bắt – Hồ sơ đang điều tra",
6.         Trang_Thai == "IC" ~ "Đang điều tra – Chưa xác định nghi phạm",
7.         Trang_Thai == "JA" ~ "Nghi phạm trưởng thành – Đang giam giữ",
8.         Trang_Thai == "JO" ~ "Nghi phạm chưa trưởng thành – Đang giam giữ",
9.         TRUE ~ "Không xác định"     )  )
10. print(crime_extended)
## # A tibble: 944,235 × 19
##    Mo_ta_Toi_Pham                   Mo_ta_Dia_Diem Ngay_Bao_Cao        Phan_Loai
##    <chr>                            <chr>          <dttm>                  <dbl>
##  1 VEHICLE - STOLEN                 STREET         2020-01-03 00:00:00         1
##  2 BURGLARY FROM VEHICLE            BUS STOP/LAYO… 2020-09-02 00:00:00         1
##  3 BIKE - STOLEN                    MULTI-UNIT DW… 2020-11-11 00:00:00         1
##  4 SHOPLIFTING-GRAND THEFT ($950.0… CLOTHING STORE 2023-10-05 00:00:00         1
##  5 THEFT OF IDENTITY                SIDEWALK       2022-08-18 00:00:00         2
##  6 THEFT OF IDENTITY                SINGLE FAMILY… 2023-04-04 00:00:00         2
##  7 THEFT OF IDENTITY                MULTI-UNIT DW… 2023-04-04 00:00:00         2
##  8 THEFT OF IDENTITY                CELL PHONE ST… 2022-07-22 00:00:00         2
##  9 THEFT OF IDENTITY                CYBERSPACE     2023-04-28 00:00:00         2
## 10 BATTERY - SIMPLE ASSAULT         MULTI-UNIT DW… 2020-12-31 00:00:00         2
## # ℹ 944,225 more rows
## # ℹ 15 more variables: Gioi_Tinh_Nan_Nhan <chr>, Tuoi_Nan_Nhan <dbl>,
## #   Ma_Khu_Vuc <dbl>, Trang_Thai <chr>, So_Don_Vi_Bao_Cao <dbl>,
## #   Ma_Toi_Pham_1 <dbl>, Ma_Toi_Pham_2 <dbl>, Ma_Toi_Pham_3 <dbl>,
## #   Ma_Toi_Pham_4 <dbl>, Khu_Vuc <chr>, `Toi Bo Sung 2` <chr>,
## #   `Toi Bo Sung 3` <chr>, `Toi Bo Sung 4` <chr>, Nhom_Tuoi <chr>,
## #   Tinh_Trang_Bat_Giu <chr>

Giải thích
Kỹ thuật:
- Dòng 1: thêm cột mới Tinh_Trang_Bat_Giu.
- Dòng 2: cho phép ánh xạ từng mã (Trang_Thai) sang mô tả đầy đủ.
+ TRUE ~ “Không xác định”: xử lý dự phòng nếu có mã lạ ngoài danh sách.
Ý nghĩa:
- Giúp phân tích tình trạng xử lý vụ án, xem tỷ lệ vụ đã bắt giữ – chưa bắt giữ.
- Cho phép nghiên cứu hiệu quả thực thi pháp luật theo khu vực, loại tội phạm, hoặc nhóm tuổi.
- Có thể sử dụng trong mô hình dự đoán khả năng phá án (clearance rate modeling).

9. Tổng số tội trong một vụ

1. crime_extended <- crime_extended %>%
2.   mutate( 
3.     So_Toi_Trong_Vu = rowSums(across(Ma_Toi_Pham_1:Ma_Toi_Pham_4, ~ . != 0), na.rm = TRUE)  )
4. crime_extended %>%
5.   select(Ma_Toi_Pham_1:Ma_Toi_Pham_4, So_Toi_Trong_Vu) %>%
6.   head()

Giải thích
Kỹ thuật:
- Dòng 3: tạo ma trận logic 4 cột (TRUE/FALSE) một lần cho toàn bộ dữ liệu.
+ rowSums(…) cộng TRUE (=1) theo hàng cực nhanh ở C.
+ na.rm = TRUE đề phòng có NA (dù bạn đã chuẩn hóa về 0).
Ý nghĩa:

Khía cạnh Giải thích
Khái niệm So_Toi_Trong_Vu là số lượng tội danh cùng xảy ra trong một vụ án.
Giá trị nghiên cứu Giúp xác định vụ án đơn tội (1 tội) hay đa tội (≥2 tội).
Ứng dụng phân tích - So sánh tính chất vụ án theo mức độ phức tạp.
- Đánh giá khả năng bắt giữ theo số lượng tội.
- Mô hình hóa rủi ro hoặc tần suất phạm pháp.
Ví dụ mô tả Trung bình mỗi vụ có mean(So_Toi_Trong_Vu) tội; tỷ lệ vụ đa tội là mean(So_Toi_Trong_Vu > 1) * 100.

10. Tách cột Ngay_Bao_Cao để tạo cột” Nam

1. crime_extended <- crime_extended %>%
2.   mutate( Nam = year(ymd(Ngay_Bao_Cao)) )
3. crime_extended %>%  select(Ngay_Bao_Cao, Nam) %>%   head()

Giải thích
Kỹ thuật:
- Dòng 1-2: đổi chuỗi ngày thành dạng ngày tháng chuẩn.
+ year(…): trích năm từ ngày.
+ mutate(…): thêm cột Nam vào bảng.
Ý nghĩa:
Giúp dễ dàng phân tích, lọc, thống kê hoặc vẽ biểu đồ theo năm (ví dụ: số vụ án từng năm).

11. Sắp xếp vị trí các biến cho hợp lí

1. crime_final <- crime_extended %>%
2.   select(  Ngay_Bao_Cao, Nam, Phan_Loai, Trang_Thai, Tinh_Trang_Bat_Giu,
3.     Mo_ta_Toi_Pham, Ma_Toi_Pham_1, `Toi Bo Sung 2`, Ma_Toi_Pham_2,
4.   `Toi Bo Sung 3`, Ma_Toi_Pham_3, `Toi Bo Sung 4`, Ma_Toi_Pham_4,
5.   So_Toi_Trong_Vu, Mo_ta_Dia_Diem, Ma_Khu_Vuc, Khu_Vuc, So_Don_Vi_Bao_Cao,
6.   Gioi_Tinh_Nan_Nhan, Tuoi_Nan_Nhan, Nhom_Tuoi  )
7. colnames(crime_final)
##  [1] "Ngay_Bao_Cao"       "Nam"                "Phan_Loai"         
##  [4] "Trang_Thai"         "Tinh_Trang_Bat_Giu" "Mo_ta_Toi_Pham"    
##  [7] "Ma_Toi_Pham_1"      "Toi Bo Sung 2"      "Ma_Toi_Pham_2"     
## [10] "Toi Bo Sung 3"      "Ma_Toi_Pham_3"      "Toi Bo Sung 4"     
## [13] "Ma_Toi_Pham_4"      "So_Toi_Trong_Vu"    "Mo_ta_Dia_Diem"    
## [16] "Ma_Khu_Vuc"         "Khu_Vuc"            "So_Don_Vi_Bao_Cao" 
## [19] "Gioi_Tinh_Nan_Nhan" "Tuoi_Nan_Nhan"      "Nhom_Tuoi"

Giải thích
Kỹ thuật:
- Dòng 2: chọn ra các cột quan trọng như ngày báo cáo, năm, loại tội phạm, tình trạng, địa điểm, thông tin nạn nhân,…
- Dòng 7: colnames(crime_final): hiển thị tên các cột của bảng mới để kiểm tra.
Ý nghĩa:
Tạo cấu trúc logic – mạch lạc – thân thiện báo cáo, phản ánh đúng quy trình phân tích tội phạm học và giảm sai sót trong thao tác và diễn giải.

CHƯƠNG 3: THỐNG KÊ CƠ BẢN

1. Thống kê số vụ theo năm

1.1 Chuẩn bị dữ liệu thời gian

1. crime_final <- crime_final %>%
2.   mutate( Ngay_Bao_Cao = ymd(Ngay_Bao_Cao),
3.     Nam = year(Ngay_Bao_Cao),
4.     Thang = month(Ngay_Bao_Cao, label = TRUE, abbr = TRUE),
5.     Quy = quarter(Ngay_Bao_Cao)  )

Giải thích
Kỹ thuật:
- Dòng 2-5:
+ ymd(Ngay_Bao_Cao): chuyển cột ngày thành dạng Date chuẩn.
+ year(…): tạo cột Nam (năm).
+ month(…, label=TRUE, abbr=TRUE): tạo cột Thang (tên tháng viết tắt, ví dụ Jan, Feb).
+ quarter(…): tạo cột Quy (quý 1–4).
Ý nghĩa:
Giúp dữ liệu có thể phân tích theo thời gian linh hoạt hơn — như thống kê theo tháng, quý, năm, hoặc vẽ biểu đồ xu hướng tội phạm theo thời gian.

1.2. Tổng số vụ theo năm

1. crime_by_year <- crime_final %>%
2.   group_by(Nam) %>% 
3.   summarise(So_Vu = n()) %>%  arrange(Nam) 
4. crime_by_year

Giải thích
Kỹ thuật:
- Dòng 2: gom dữ liệu theo từng năm.
- Dòng 3:
+ summarise(n()) → đếm tổng số bản ghi (vụ tội phạm) trong từng nhóm.
+ arrange(Nam) → sắp xếp theo thứ tự tăng dần của năm.
Ý nghĩa:
Giúp thống kê xu hướng tội phạm theo từng năm, hỗ trợ phân tích sự thay đổi hoặc vẽ biểu đồ xu hướng thời gian.

1.3. Tỷ lệ thay đổi (%) qua từng năm

1. crime_by_year <- crime_final %>%
2. filter(Nam != 2024) %>%              
3. group_by(Nam) %>% summarise(So_Vu = n()) %>% arrange(Nam)
4. crime_by_year <- crime_by_year %>% 
5. mutate( Ty_le_thay_doi = round((So_Vu - lag(So_Vu)) / lag(So_Vu) * 100, 2))
6. crime_by_year

Giải thích
Kỹ thuật:
- Dòng 2: loại bỏ dữ liệu năm 2024 (chưa đủ hoặc chưa hoàn chỉnh).
- Dòng 3:
+ group_by(Nam) %>% summarise(So_Vu = n()): đếm số vụ (So_Vu) cho từng năm.
+ arrange(Nam): sắp xếp theo thứ tự năm tăng dần.
- Dòng 5 mutate(Ty_le_thay_doi = round((So_Vu - lag(So_Vu)) / lag(So_Vu) * 100, 2)):
+ lag(So_Vu): lấy giá trị số vụ của năm trước.
+ Công thức tính tỷ lệ thay đổi (%) so với năm trước.
+ round(…, 2): làm tròn đến 2 chữ số thập phân. Ý nghĩa:
- 2021 tăng 8.08% so với 2020 → xu hướng gia tăng tội phạm rõ rệt.
- 2022 tăng tiếp 12.86% so với 2021 → đỉnh cao trong giai đoạn.
- 2023 giảm nhẹ 0.18% → mức ổn định, không giảm đáng kể.

1.4. Thống kê mô tả số vụ mỗi năm

1. mean(crime_by_year$So_Vu)                    
## [1] 217676
1. median(crime_by_year$So_Vu)                  
## [1] 221466
1. sd(crime_by_year$So_Vu)                      
## [1] 20833.1
1. var(crime_by_year$So_Vu)                     
## [1] 434018249
1. min(crime_by_year$So_Vu)                     
## [1] 192708
1. max(crime_by_year$So_Vu)                     
## [1] 235064
1. quantile(crime_by_year$So_Vu, probs=c(0.25, 0.5, 0.75))  
##      25%      50%      75% 
## 204389.2 221466.0 234752.8

Giải thích
Kỹ thuật:
- Dòng 1: giá trị trung bình số vụ/năm.
- Dòng 2: trung vị – giá trị nằm giữa khi sắp xếp dữ liệu.
- Dòng 3: độ lệch chuẩn, đo mức phân tán quanh giá trị trung bình.
- Dòng 4: phương sai, thể hiện mức độ biến động (bình phương của độ lệch chuẩn).
- Dòng 5-6: giá trị nhỏ nhất và lớn nhất của số vụ.
- Dòng 7: các phân vị:
+ 0.25: Q1 (25%)
+ 0.5: median (50%)
+ 0.75: Q3 (75%)
Ý nghĩa
- Trong giai đoạn 2020–2023, trung bình mỗi năm xảy ra khoảng 217,676 vụ phạm tội, dao động ±20,833 vụ. Số vụ thấp nhất năm 2020 (192,708) và cao nhất năm 2022 (235,064). Phân phối tương đối đối xứng, không có năm bất thường.
- Sau giai đoạn giảm mạnh do đại dịch, số vụ tội phạm tăng trở lại trong 2021–2022 và ổn định ở mức cao năm 2023, phản ánh sự phục hồi xã hội và kinh tế kèm hệ quả tội phạm gia tăng.

1.5. Thống kê số vụ theo tháng mỗi năm

1. crime_by_month <- crime_final %>%
2.   group_by(Nam, Thang) %>%   summarise(So_Vu = n(), .groups = "drop")
3. crime_by_month <- crime_by_month %>%  group_by(Nam) %>% 
4.   mutate( Tong_Nam = sum(So_Vu), Ty_le = round(So_Vu / Tong_Nam * 100, 2)  )
5. crime_by_month <- crime_by_month %>%   filter(Nam != 2024) 
6. crime_by_quarter <- crime_final %>% 
7.   group_by(Nam, Quy) %>%  summarise(So_Vu = n(), .group = "drop") 
8. crime_by_month

Giải thích:
Kỹ thuật
- Dòng 1-4: nhóm theo năm – tháng, đếm số vụ mỗi tháng → tạo cột So_Vu.
- Dòng 5-8:
+ group_by(Nam) %>% mutate(Tong_Nam = sum(So_Vu), Ty_le = round(So_Vu / Tong_Nam * 100, 2)): tính tổng vụ/năm và tỷ lệ % mỗi tháng trong năm.
+ filter(Nam != 2024): bỏ năm 2024 (chưa đủ dữ liệu).
Ý nghĩa:
- Phân bố tội phạm theo tháng trong giai đoạn 2020–2023 nhìn chung khá ổn định, không có biến động đột ngột.
- Trung bình mỗi tháng chiếm khoảng 7,8–8,8% tổng số vụ trong năm, tương đương 17.000–20.000 vụ/tháng. Các tháng có tần suất cao hơn trung bình thường rơi vào:
+ Tháng 1 (8.3–8.7%), liên quan đến giai đoạn trước và sau Tết Nguyên đán, hoạt động xã hội, đi lại, tiêu dùng tăng cao.
+ Tháng 6–8 và Tháng 10 cũng ghi nhận tỷ trọng cao hơn, có thể liên quan đến mùa du lịch, học sinh – sinh viên nghỉ hè, và thời điểm cuối quý III – đầu quý IV khi hoạt động kinh tế – xã hội sôi động.
- Ngược lại, các tháng có tỷ lệ thấp hơn thường là Tháng 3, 11, 12, dao động quanh 7,8–8,0%, cho thấy thời kỳ ổn định hoặc giảm nhẹ của tội phạm trước giai đoạn lễ – Tết.
- Mức chênh lệch giữa tháng cao nhất và thấp nhất chỉ khoảng 1 điểm phần trăm, chứng tỏ tình hình tội phạm phân bố khá đều, không có tháng “bùng phát” bất thường.
- Phân tích theo tháng giai đoạn 2020–2023 phản ánh tính ổn định cao và quy luật mùa vụ nhẹ trong hoạt động tội phạm, chủ yếu dao động theo chu kỳ kinh tế – xã hội (Tết, du lịch, tiêu dùng, nghỉ hè…).

2. Thống keo theo nhóm biến tôi phạm

2.1. Tần số và tần suất của biến phân loại

1. crime_by_type <- crime_final %>% group_by(Phan_Loai) %>%
2.   summarise(So_Vu = n(), .groups = "drop") %>%
3.   mutate( Tong_Vu = sum(So_Vu), Ty_le = round(So_Vu / Tong_Vu * 100, 2)  ) %>%
4.   ungroup() %>% arrange(desc(So_Vu))
5. crime_by_type

Giải thích
Kỹ thuật:
- Dòng 1: nhóm dữ liệu theo loại tội phạm.
- Dòng 2: đếm số vụ trong mỗi nhóm.
- Dòng 3: thêm tổng số vụ (Tong_Vu) và tính tỷ lệ phần trăm (Ty_le).
+ arrange(desc(So_Vu)) sắp xếp theo số vụ giảm dần để dễ quan sát.
Ý nghĩa:
Loại tội phạm thứ nhất xuất hiện nhiều hơn và là dạng chiếm tỷ trọng lớn nhất trong tổng số vụ án (944,235 vụ).

2.2. Thống kê theo trạng thái

1. crime_by_status <- crime_final %>% group_by(Trang_Thai) %>%
2.   summarise(So_Vu = n(), .groups = "drop") %>% 
3.   mutate( Tong_Vu = sum(So_Vu), Ty_le = round(So_Vu / Tong_Vu * 100, 2) ) %>%
4.   ungroup() %>% arrange(desc(So_Vu)) 
5. crime_by_status

Giải thích
Kỹ thuật:
- Dòng 1: nhóm dữ liệu theo từng trạng thái vụ án.
- Dòng 2: đếm số vụ trong mỗi nhóm.
- Dòng 3: tính tổng số vụ (Tong_Vu) và tỷ lệ phần trăm (Ty_le) của từng trạng thái.
- Dòng 4: sắp xếp kết quả theo số vụ giảm dần.
Ý nghĩa:
IC chiếm đa số (79.88%) – đây có thể là trạng thái vụ đang trong quá trình điều tra hoặc chưa xử lý xong.
AO và AA chiếm lần lượt 10.90% và 8.70%, phản ánh các vụ đã có tiến triển hoặc kết luận khác nhau.
Các trạng thái còn lại (JA, JO, CC) chiếm tỷ lệ rất nhỏ (<1%).

2.3. Thống kê theo mô tả tội phạm

1. crime_by_desc <- crime_final %>%   group_by(Mo_ta_Toi_Pham) %>%
2.   summarise(So_Vu = n(), .groups = "drop") %>%   mutate(
3.     Tong_Vu = sum(So_Vu), Ty_le = round(So_Vu / Tong_Vu * 100, 2)  ) %>%
4.   ungroup() %>% arrange(desc(So_Vu))
5. head(crime_by_desc, 10)

Giải thích
Kỹ thuật:
- Dòng 1: nhóm dữ liệu theo từng loại tội phạm cụ thể.
- Dòng 2:
+ summarise(So_Vu = n()) → đếm số vụ trong mỗi nhóm.
+ mutate() → thêm tổng số vụ (Tong_Vu) và tính tỷ lệ phần trăm (Ty_le) của từng loại tội.
+ arrange(desc(So_Vu)) → sắp xếp theo số vụ giảm dần.
- Dòng 5: chỉ lấy 10 loại tội phạm phổ biến nhất.
Ý nghĩa:
Trộm xe (VEHICLE - STOLEN) chiếm 10.81%, là loại tội phạm nhiều nhất.
Tiếp theo là hành hung đơn giản (BATTERY - SIMPLE ASSAULT) chiếm 7.89%, và trộm cắp từ xe (BURGLARY FROM VEHICLE) chiếm 6.18%.
10 loại tội phạm hàng đầu chiếm trên 60% tổng số vụ án, cho thấy mức độ tập trung cao ở một số nhóm tội chính.

2.4. Trong mỗi năm, loại tội phạm nào xảy ra nhiều nhất

2.4.1. Đếm số vụ theo năm & mô tả tội phạm
1. crime_by_year_type <- crime_final %>% filter(Nam != 2024) %>%
2.   group_by(Nam, Mo_ta_Toi_Pham) %>% summarise(So_Vu = n(), .groups = "drop") %>% group_by(Nam) %>%
3.   mutate( Tong_Nam = sum(So_Vu), Ty_le = round(So_Vu / Tong_Nam * 100, 2)  )
4. View(crime_by_year_type)

Ggiải thích
Đoạn code thống kê số vụ án theo từng năm và loại tội phạm (Mo_ta_Toi_Pham), tính tổng số vụ và tỷ lệ phần trăm của từng loại trong năm.
Kết quả cho thấy mỗi năm có khoảng 235.000 vụ án, với các tội phổ biến như trộm xe, trộm cắp, hành hung, phá hoại tài sản chiếm tỷ trọng cao nhất.
Điều này phản ánh mô hình tội phạm ổn định qua các năm, trong đó các hành vi liên quan đến trộm cắp tài sản vẫn chiếm ưu thế.

2.4.2. Xác định tội phạm nhiều nhất mỗi năm (Top 1)
1. top_crime_each_year <- crime_by_year_type %>%
2.   group_by(Nam) %>% slice_max(order_by = So_Vu, n = 1)
3. top_crime_each_year

Ggiải thích
- Dòng 1-3:
+ group_by(Nam) → nhóm dữ liệu theo năm.
+ slice_max(order_by = So_Vu, n = 1) → lấy dòng có số vụ (So_Vu) lớn nhất trong từng năm.
Kết quả: Trong giai đoạn 2020–2023, tội “VEHICLE - STOLEN” (trộm xe) luôn đứng đầu mỗi năm, chiếm khoảng 10–11% tổng số vụ án hàng năm.

2.4.3. Xác định tội phạm nhiều top 3 mỗi năm
1. top3_crime_each_year <- crime_by_year_type %>%
2.   group_by(Nam) %>% slice_max(order_by = So_Vu, n = 3)
3. top3_crime_each_year

Giải thích
Kỹ thuật: nhóm dữ liệu theo năm (Nam) và chọn 3 loại tội phạm có số vụ cao nhất mỗi năm bằng slice_max(order_by = So_Vu, n = 3).
Ý nghĩa:
Kết quả cho thấy “VEHICLE - STOLEN”, “BATTERY - SIMPLE ASSAULT” và “THEFT OF IDENTITY” là 3 tội phạm phổ biến nhất hằng năm, chiếm tỷ lệ lớn trong tổng số vụ án.

2.5. Phân bố tần suất số tội trong vụ qua các năm

1. crime_freq <- crime_by_year %>%
2.   mutate(Tan_suat = round(So_Vu / sum(So_Vu) * 100, 2))
3. crime_freq

Giải thích
Kỹ thuật:
+ So_Vu: là tần số – tổng số vụ trong từng năm.
+ Tan_suat: là tần suất (%) – tỷ lệ số vụ của năm đó so với toàn bộ các năm.
Ý nghĩa: Tội phạm có xu hướng tăng dần từ 2020–2022 rồi ổn định vào 2023, cho thấy sự leo thang trước khi chững lại.

3. Thống kê theo nhóm nhân khẩu học

3.1. Thống kê theo giới tính

1. crime_by_gender <- crime_extended %>%
2.   count(Gioi_Tinh_Nan_Nhan) %>%
3.   mutate(Tan_suat = round(n / sum(n) * 100, 2))
4. crime_by_gender

Giải thích
Kỹ thuật:
Đoạn code trên nhóm dữ liệu theo giới tính nạn nhân (Gioi_Tinh_Nan_Nhan), đếm số vụ (n) và tính tần suất (%) của từng giới tính trong tổng số vụ.
Ý nghĩa:
Nạn nhân nam và nữ có tỷ lệ gần tương đương, nhưng vẫn thấy nam là nhóm bị ảnh hưởng nhiều nhất, trong khi giới tính không xác định chiếm tỷ lệ đáng kể trong dữ liệu.

3.2. Thống kê theo khu vực

1. crime_by_area <- crime_extended %>%
2.   group_by(Khu_Vuc) %>%   summarise(So_Vu = n(), .groups = "drop") %>%
3.   mutate(Tan_suat = round(So_Vu / sum(So_Vu) * 100, 2)) %>% arrange(desc(So_Vu))
4. head(crime_by_area,10)

Giải thích
Kỹ thuật:  + count() thay cho group_by() + summarise(), giúp đếm nhanh số vụ theo khu vực.
+ Tính tần suất (%), sắp xếp giảm dần và lấy top 10 khu có nhiều vụ nhất.
Ý nghĩa:
Các khu Central, 77th Street, Pacific có số vụ cao nhất (~6–7%), cho thấy phân bố tội phạm tập trung ở khu trung tâm và phía nam thành phố.

3.3. Thống kê giới tính theo phân loại qua từng năm

1. crime_by_gender_type_year <- crime_final %>%
2.   filter(Nam != 2024) %>%                               
3.   group_by(Nam, Phan_Loai, Gioi_Tinh_Nan_Nhan) %>%    
4.   summarise(So_Vu = n(), .groups = "drop_last") %>%     
5.   mutate( Tong_Phan_Loai_Nam = sum(So_Vu),                    
6.     Ty_le = round(So_Vu / Tong_Phan_Loai_Nam * 100, 2)  ) %>%
7.   ungroup() %>% arrange(Nam, Phan_Loai, desc(So_Vu))
8. View(crime_by_gender_type_year)

Giải thích
Kỹ thuật:
+ filter(Nam != 2024): loại dữ liệu năm 2024.
+ group_by(Nam, Phan_Loai, Gioi_Tinh_Nan_Nhan): nhóm theo năm, loại tội, giới tính.
+ summarise(So_Vu = n()): đếm số vụ trong mỗi nhóm.
+ mutate(…): tính tổng vụ trong từng loại-năm và tỷ lệ (%) từng giới
+ arrange(…): sắp xếp theo năm, loại, số vụ giảm dần.
Ý nghĩa:
Bảng cho biết số vụ và tỷ lệ theo giới tính nạn nhân trong mỗi loại tội phạm và từng năm, giúp so sánh mức độ ảnh hưởng giữa nam – nữ theo thời gian và loại tội.

3.4. Thống kê theo nhóm tuổi của nạn nhân

1. crime_by_age <- crime_final %>%
2.   filter(Nam != 2024) %>%  group_by(Nhom_Tuoi) %>%                              summarise(So_Vu = n(), .groups = "drop") %>%          
3.   mutate( Tong_Vu = sum(So_Vu), Ty_le = round(So_Vu / Tong_Vu * 100, 2) ) %>%
4.   ungroup() %>% arrange(desc(So_Vu))
5. crime_by_age

Giải thích
Kỹ thuật:
count() đếm tần số theo nhóm tuổi; mutate() tính tổng và tỷ lệ %; arrange() sắp xếp giảm dần.
Ý nghĩa: nhóm Trưởng thành (30–44) nhiều nhất 27.12%, Dưới 10 tuổi bất ngờ đứng thứ hai 25.40%, tiếp theo là Thanh niên (18–29) 19.84%; tổng mẫu dùng để tính là 870,704 vụ (không gồm 2024).

3.5. Thống kê kết hợp nhóm tuổi và giới tính nạn nhân

1. crime_by_age_gender <- crime_final %>%
2.   filter(Nam != 2024) %>% group_by(Nhom_Tuoi, Gioi_Tinh_Nan_Nhan) %>%             summarise(So_Vu = n(), .groups = "drop_last") %>%         
3.   mutate( Tong_Theo_Gioi = sum(So_Vu),             
4.     Ty_le_Trong_Gioi = round(So_Vu / Tong_Theo_Gioi * 100, 2) ) %>% ungroup() %>% arrange(Gioi_Tinh_Nan_Nhan, desc(So_Vu))
5. View(crime_by_age_gender)

Giải thích
Kỹ thuật:
- Dòng 1: Lọc bỏ năm 2024.
- Dòng 2: Đếm số vụ theo nhóm tuổi và giới tính.
- Dòng 4: Tính tổng số vụ trong từng giới và tỷ lệ (%) của mỗi nhóm tuổi trong giới đó.
- Dòng 6: Sắp xếp theo giới tính và số vụ giảm dần → giúp thấy nhóm tuổi nào chiếm tỷ lệ cao nhất trong từng giới.
Ý nghĩa:
phân bố tội phạm theo giới và tuổi tương đối cân bằng, nhưng cần rà soát giá trị “X” để đảm bảo độ chính xác.

3.6. Thống kê nhóm tuổi nạn nhân qua các năm

1. crime_by_age_year <- crime_final %>%
2.   filter(Nam != 2024) %>% group_by(Nam, Nhom_Tuoi) %>%               
3.   summarise(So_Vu = n(), .groups = "drop_last") %>% 
4.   mutate( Tong_Nam = sum(So_Vu), Ty_le = round(So_Vu / Tong_Nam * 100, 2)  
5.   ) %>% ungroup() %>% arrange(Nam, desc(So_Vu))
6. crime_by_age_year

Giải thích
Kỹ thuật:
- Dòng 1–2: Lọc bỏ năm 2024, nhóm dữ liệu theo năm và nhóm tuổi.
- Dòng 3: Tính số vụ phạm tội (So_Vu) cho từng nhóm, giữ cấu trúc nhóm theo năm.
- Dòng 4–5: Tính tổng số vụ trong năm và tỷ lệ phần trăm từng nhóm tuổi; sắp xếp giảm dần theo số vụ.
- Dòng 6: Hiển thị bảng kết quả hoàn chỉnh, dễ đọc và so sánh theo năm.
Ý nghĩa:
Cấu trúc chung: Các nhóm tuổi Trưởng thành trẻ (30–44 tuổi) và Dưới 10 tuổi chiếm tỷ trọng lớn nhất trong toàn bộ giai đoạn, lần lượt khoảng 25–28% mỗi năm.
Nhóm Thanh niên (18–29 tuổi) chiếm khoảng 20%, trong khi Trung niên (45–59) dao động từ 15–17%. Các nhóm cao niên (60–74) và già (75+) có tỷ lệ thấp (7–8% và ~2%).
Xu hướng theo thời gian:
+ Giai đoạn 2020 → 2022, tỷ lệ nạn nhân Trưởng thành trẻ (30–44) tăng nhẹ từ 26.7% lên 28.1%, cho thấy tăng cường tiếp xúc xã hội và kinh tế của nhóm này sau đại dịch.
+ Nhóm Dưới 10 tuổi duy trì mức cao (~25%), đặc biệt tăng mạnh năm 2023 (27.5%), phản ánh xu hướng đáng lo ngại về các vụ xâm hại, bạo lực, hoặc vi phạm liên quan trẻ nhỏ.
+ Nhóm Thanh niên (18–29) tương đối ổn định quanh mức 19–20%, còn nhóm Trung niên (45–59) có xu hướng giảm nhẹ.
Đặc điểm nổi bật năm 2023: Năm 2023 ghi nhận sự đảo chiều nhẹ: nhóm Dưới 10 tuổi vượt Trưởng thành trẻ, trở thành nhóm chiếm tỷ lệ cao nhất (27.6%). Điều này có thể liên quan đến tăng cường báo cáo tội phạm trẻ em hoặc số vụ bạo lực gia đình và học đường được ghi nhận nhiều hơn.
Tổng thể: Trong cả giai đoạn 2020–2023, cơ cấu nạn nhân theo độ tuổi ổn định, nhưng hai xu hướng đáng chú ý là:
+ Sự duy trì tỷ lệ cao của nhóm 30–44 tuổi → phản ánh nhóm lao động năng động, rủi ro xã hội cao.
+ Sự tăng nhẹ nhóm Dưới 10 tuổi → tín hiệu cảnh báo về an toàn trẻ em và chất lượng môi trường xã hội.

3.7. Thống kê phân loại tội phạm theo khu vực

1. crime_by_area_type <- crime_final %>% filter(Nam != 2024) %>%
2.   group_by(Khu_Vuc, Phan_Loai) %>%                  
3.   summarise(So_Vu = n(), .groups = "drop_last") %>%   
4.   mutate( Tong_Vu_Khu_Vuc = sum(So_Vu),                     
5.     Ty_le = round(So_Vu / Tong_Vu_Khu_Vuc * 100, 2)     ) %>%
6.   ungroup() %>% arrange(desc(So_Vu))
7. View(crime_by_area_type)

Giải thích
Kỹ thuật:
- Dòng 1-6: Lọc năm ≠ 2024 → nhóm theo năm và tuổi → đếm số vụ → tính tổng và tỷ lệ theo năm → sắp xếp giảm dần số vụ.
- Dòng 7: Xem loại tội phạm theo khu vực.
Ý nghĩa:
loại tội 1 chiếm tỉ lệ cao hơn (khoảng 55–65%) ở hầu hết khu vực, cho thấy các tội nghiêm trọng vẫn chiếm ưu thế trong cơ cấu tội phạm toàn thành phố.

3.8. Thống kê tình trạng bắt giữ theo khu vực

1. crime_by_area_status <- crime_final %>%
2.   filter(Nam != 2024) %>% group_by(Khu_Vuc, Trang_Thai) %>% 
3.   summarise(So_Vu = n(), .groups = "drop_last") %>%      
4.   mutate( Tong_Vu_Khu_Vuc = sum(So_Vu),                        
5.     Ty_le = round(So_Vu / Tong_Vu_Khu_Vuc * 100, 2) ) %>% ungroup() %>%
6.   arrange(Khu_Vuc, desc(So_Vu))
7. View(crime_by_area_status)

Giải thích
Kỹ thuật:
- Dòng 1-6:
+ filter(Nam != 2024): loại dữ liệu năm 2024.
+ group_by(Khu_Vuc, Trang_Thai): nhóm theo khu vực và trạng thái vụ án.
+ summarise(So_Vu = n()): đếm số vụ từng trạng thái trong mỗi khu.
+ mutate(Tong_Vu_Khu_Vuc = sum(So_Vu), Ty_le = So_Vu / Tong_Vu_Khu_Vuc * 100): tính tổng vụ trong khu và tỷ lệ từng trạng thái.
+ arrange(Khu_Vuc, desc(So_Vu)): sắp xếp theo khu và giảm dần số vụ.
Ý nghĩa:
Mức độ giải quyết tội phạm còn thấp, tập trung chủ yếu ở các vụ đang trong quá trình điều tra.

CHƯƠNG 4: TRỰC QUAN HÓA

1. Biểu đồ phân phối tuổi của nạn nhân (Tuoi_Nan_Nhan) theo nhóm tuổi (Nhom_Tuoi):

1. crime_per_year <- crime_extended %>%
2.   filter(Nam != 2024) %>% 
3.   group_by(Nam) %>%
4.   summarise(So_Vu = n())
5. ggplot(crime_per_year, aes(x = as.factor(Nam), y = So_Vu, fill = as.factor(Nam))) +
6.   geom_bar(stat = "identity", position = "dodge", alpha = 0.6) +
7.   geom_text(aes(label = So_Vu), vjust = 0.5, size = 5, fontface = "bold") +  
8.   labs(title = "Số vụ tội phạm theo năm", 
9.        x = "Năm", y = "Số lượng vụ tội phạm",  caption = "Chú thích: Năm") +
10.   scale_fill_brewer(palette = "Set3", name = "Năm") + theme_minimal() +
11.   theme(axis.text.x = element_text(angle = 0, hjust = 1, size = 14),
12.       plot.title = element_text(face = "bold", size = 16),  
13.       plot.caption = element_text(size = 12, hjust = 1))  

Giải thích
Kỹ thuật
- Dòng 1-4: Dữ liệu được lọc để loại bỏ năm 2024, sau đó nhóm theo năm (Nam) và tính tổng số vụ tội phạm (So_Vu) cho từng năm.
- Dòng 5-6: Biểu đồ cột (geom_bar) được vẽ, sử dụng dodge position để các cột của mỗi năm không bị chồng lên nhau, với độ trong suốt là 60%.
- Dòng 7: Thêm nhãn số vụ tội phạm vào mỗi cột, đảm bảo nhãn được căn chỉnh đúng vị trí và có kích thước chữ rõ ràng.
- Dòng 8-9: Thêm tiêu đề, nhãn trục và chú thích (caption) cho biểu đồ.
- Dòng 10: Tùy chỉnh màu sắc với bảng màu từ RColorBrewer cho các cột theo năm.
- Dòng 11-13: Cải thiện kiểu dáng của biểu đồ: chỉnh sửa kích thước chữ cho trục x và tiêu đề, và căn chỉnh các phần tử đồ họa cho dễ nhìn hơn.
Ý nghĩa
- 2020-2022: Số vụ tội phạm tăng từ 192,708 vụ (2020) lên 235,064 vụ (2022), cho thấy một sự gia tăng rõ rệt trong tình hình tội phạm trong giai đoạn này.
- 2023: Mặc dù vẫn giữ ở mức cao (234,649 vụ), nhưng số vụ tội phạm đã giảm nhẹ so với năm 2022, có thể phản ánh những nỗ lực kiểm soát hoặc sự thay đổi trong các yếu tố xã hội.

2. Tốc độ tăng/giảm qua các năm

1. ggplot(crime_by_year, aes(x = as.factor(Nam), y = Ty_le_thay_doi, fill = as.factor(Nam))) +
2.   geom_bar(stat = "identity", alpha = 0.6) +
3.   geom_text(aes(label = round(Ty_le_thay_doi, 2)), vjust = 0.5, size = 5, fontface = "bold") +
4.   labs(title = "Tỷ lệ tăng trưởng phần trăm\n số vụ tội phạm theo năm", 
5.        x = "Năm", y = "Tỷ lệ tăng trưởng (%)", fill = "Năm báo cáo") +
6.   scale_fill_brewer(palette = "Set3") +
7.   theme_minimal() + theme(plot.title = element_text(size = 18, face = "bold", lineheight = 1.2, hjust = 0.5), axis.text.x = element_text(angle = 0, hjust = 1, size = 14))

r 1. is.text.x = element_text(angle = 45, hjust = 1, size = 12)

Giải thích
Kỹ thuật:
- Dòng 1: Khởi tạo biểu đồ với ggplot, ánh xạ năm lên trục x và tỷ lệ thay đổi lên trục y, đồng thời tô màu theo năm.
- Dòng 2: Dùng geom_bar(stat=“identity”) để vẽ biểu đồ cột, hiển thị trực tiếp giá trị tỷ lệ thay đổi.
- Dòng 3: Thêm nhãn giá trị làm tròn 2 chữ số, căn giữa cột để dễ đọc.
- Dòng 4–5: Đặt tiêu đề và nhãn trục rõ ràng, mô tả ý nghĩa của biểu đồ.
- Dòng 6: Áp dụng bảng màu Set3 giúp phân biệt các năm trực quan.
- Dòng 7: Dùng theme_minimal() tạo phong cách đơn giản, làm nổi bật dữ liệu.
Ý nghĩa:
- 2020-2021: Tỷ lệ tăng trưởng rất thấp (0.08%), cho thấy số vụ tội phạm gần như không thay đổi.
- 2021-2022: Tăng mạnh lên 0.13%, phản ánh sự gia tăng đáng kể trong số vụ tội phạm, có thể do các yếu tố xã hội hoặc kinh tế tác động.
- 2022-2023: Tỷ lệ tăng trưởng bằng 0%, cho thấy sự ổn định trong số vụ tội phạm, có thể là kết quả của các biện pháp kiểm soát hiệu quả.

3. Số vụ phạm tội theo tháng

1. crime_by_month <- crime_final %>%
2.   mutate(Thang = month(ymd(Ngay_Bao_Cao), label = TRUE, abbr = TRUE)) %>%
3.   filter(Nam != 2024) %>% group_by(Nam, Thang) %>%
4.   summarise(So_Vu = n(), .groups = "drop")
5. ggplot(crime_by_month, aes(Thang, So_Vu, color = factor(Nam), group = Nam)) +
6.   geom_line(size = 0.9) + geom_point(size = 1.8) +  stat_summary(aes(group = 1), fun = mean, geom = "line", color = "black", linetype = 2, size = 1.05) +
7.   geom_smooth(method = "loess", se = FALSE, linetype = 3) +
8.   scale_y_continuous(labels = scales::label_number(scale_cut = scales::cut_short_scale())) + labs(
9.     title = "Mùa vụ theo tháng trong từng năm (2020–2023)",
10.     subtitle = "Đường đen nét đứt: trung bình các năm",
11.     x = "Tháng", y = "Số vụ", color = "Năm" ) +
12.   theme_minimal() + theme( axis.text.x = element_text(size = 7), 
13.     plot.title = element_text(face = "bold"),
14.     plot.subtitle = element_text(color = "gray30"),
15.     plot.caption = element_text(color = "gray50"),
16.     panel.grid.minor = element_blank())

Giải thích
Kỹ thuật:
- Dòng 1-4: Tiền xử lý dữ liệu, trích tháng từ Ngay_Bao_Cao, lọc bỏ năm 2024, nhóm theo Nam và Thang, rồi đếm số vụ (So_Vu).
- Dòng 5-6: Vẽ biểu đồ đường cho từng năm, thêm các điểm dữ liệu và đường trung bình (đen, nét đứt) bằng stat_summary.
- Dòng 7-8: Thêm đường xu hướng tổng thể bằng geom_smooth(loess) và định dạng trục y với nhãn rút gọn.
- Dòng 9-16: Thêm tiêu đề, phụ đề, nhãn trục và chỉnh giao diện tối giản với chữ nhỏ, ẩn lưới phụ để biểu đồ rõ hơn.
Ý nghĩa:
- Xu hướng mùa vụ: Số vụ tội phạm cao nhất vào giữa năm (tháng 5-6) và thấp nhất vào cuối năm (tháng 1-2) cho tất cả các năm.
- Sự thay đổi qua các năm:
+ 2020: Số vụ tội phạm dao động nhẹ.
+ 2021: Tăng mạnh vào giữa năm.
+ 2022: Mức tăng cao nhất, đỉnh vào tháng 5-6.
+ 2023: Mức tội phạm giảm vào cuối năm.
- Đường trung bình: Tăng trưởng rõ rệt từ 2020 đến 2022, ổn định vào 2023.

4. Tỷ lệ số vụ theo tháng qua các năm

1. crime_by_month <- crime_final %>%
2.   mutate(Thang = month(ymd(Ngay_Bao_Cao), label = TRUE, abbr = TRUE)) %>%
3.   filter(Nam != 2024) %>% group_by(Nam, Thang) %>%
4.   summarise(So_Vu = n(), .groups = "drop")
5. crime_by_month <- crime_by_month %>%
6.   group_by(Thang) %>%
7.   mutate(Ty_le_So_Vu = So_Vu / sum(So_Vu)) %>%  # Tính tỷ lệ số vụ mỗi tháng
8.   ungroup()
9. ggplot(crime_by_month, aes(x = Thang, y = factor(Nam), fill = Ty_le_So_Vu)) +
10.   geom_tile() +
11.   scale_fill_gradient(low = "white", high = "blue") +  
12.   labs( title = "Tỷ lệ số vụ tội phạm theo tháng qua các năm",
13.     x = "Tháng", y = "Năm", fill = "Tỷ lệ số vụ"   ) +
14.   theme_minimal() + 
15.   theme( axis.text.x = element_text(angle = 45, hjust = 1, size= 10),
16.     plot.title = element_text(face = "bold")   )

Giải thích
Kỹ thuật
- Dòng 1-4: Tạo bảng So_Vu theo năm–tháng chuẩn, bước tiền xử lý gọn và đúng.
- Dòng 5-8: Hiện đang group_by(Thang) rồi chuẩn hóa theo tổng của từng tháng trên tất cả các năm; nếu muốn tỷ lệ theo tháng trong từng năm, nên group_by(Nam) rồi tính So_Vu / sum(So_Vu).
- Dòng 9-11: Heatmap với geom_tile hợp lý; nên cân nhắc thang màu dễ nhìn hơn (vd. scale_fill_viridis_c(option = “C”)) và nhãn tỉ lệ theo phần trăm (labels = scales::label_percent(accuracy = 0.1)).
- Dòng 12-16: Nhãn, theme tối giản ổn; có thể tăng size tiêu đề, thêm guides(fill = guide_colorbar(barheight = …)), và giữ thứ tự tháng đã là factor có thứ tự nên không cần sắp thêm.
Ý nghĩa:
- 2022 có tăng trưởng mạnh trong số vụ tội phạm, đặc biệt là vào tháng 5 và tháng 6, cho thấy mùa vụ tội phạm cao điểm trong năm.
- 2020 và 2021 có tỷ lệ số vụ thấp, phản ánh sự ổn định hoặc giảm tội phạm.
- 2023 có tỷ lệ ổn định, với ít biến động qua các tháng.
- Tổng thể, 2022 nổi bật với số vụ tội phạm cao, trong khi các năm còn lại có xu hướng ổn định hơn.

5. Số vụ theo quý trong từng năm

1. crime_by_quarter <- crime_final %>%
2.   mutate( Ngay_Bao_Cao = ymd(Ngay_Bao_Cao), 
3.     Quater = quarter(Ngay_Bao_Cao, with_year = TRUE), Nam = year(Ngay_Bao_Cao)
4.   ) %>% filter(Nam != 2024) %>% group_by(Nam, Quater) %>%
5.   summarise(So_Vu = n(), .groups = "drop")
6. ggplot(crime_by_quarter, aes(x = factor(Quater), y = So_Vu, group = Nam, color = factor(Nam))) + geom_line(size = 1.2) + geom_point(size = 3) + 
7.   labs( title = "Số vụ tội phạm theo quý trong từng năm", 
8.     x = "Quý", y = "Số vụ tội phạm", color = "Năm"  ) +
9.   scale_x_discrete(labels = c("Q1", "Q2", "Q3", "Q4", "Q1", "Q2", "Q3", "Q4", "Q1", "Q2", "Q3", "Q4", "Q1", "Q2", "Q3", "Q4")) +  theme_minimal() +
10.   theme(     plot.title = element_text(face = "bold", size = 14),
11.     axis.text.x = element_text(size = 10, angle = 0, hjust = 0.5),
12. axis.text.y = element_text(size = 12), legend.title = element_text(size = 12),
13.  legend.text = element_text(size = 10)  )

Giải thích
Kỹ thuật:
- Dòng 1–4: Tiền xử lý đúng, nên sửa tên biến Quater → Quarter, bỏ with_year=TRUE để trục X rõ hơn.
- Dòng 5: Tính tổng hợp hợp lý, có thể thêm complete() để đủ 4 quý mỗi năm.
- Dòng 6–8: Vẽ line chart chuẩn, nên dùng Quarter số thay vì factor có năm.
- Dòng 9–13: Theme ổn, tránh hard-code nhãn X; nên dùng scale_x_continuous(breaks = 1:4, labels = “Q1–Q4”).
Ý nghĩa:
- 2020: Số vụ tội phạm ổn định trong các quý đầu năm, với sự gia tăng rõ rệt trong Q2 (quý 2), sau đó giảm xuống. Điều này có thể phản ánh một số yếu tố tác động (như các biện pháp kiểm soát) trong suốt năm.
- 2021: Tăng trưởng mạnh trong Q2, với số vụ tội phạm đạt đỉnh, sau đó giảm dần. Quý 1 và quý 3 có mức độ thấp.
- 2022: Cũng có đỉnh điểm tăng trưởng mạnh ở Q2, nhưng số vụ tội phạm trong quý 4 lại thấp hơn so với các quý còn lại, có thể là dấu hiệu của các chiến lược kiềm chế hiệu quả vào cuối năm.
- 2023: Đỉnh điểm giảm trong Q2, với số vụ tội phạm không đạt mức cao trong các quý khác, cho thấy sự ổn định hoặc giảm trong năm này.

6. Cơ cấu phân loại tội phạm theo năm

1. crime_by_type <- crime_final %>% filter(Nam != 2024) %>% group_by(Nam, Phan_Loai) %>% summarise(So_Vu = n(), .groups = "drop") %>%
2.   group_by(Nam) %>% mutate(Ty_le = So_Vu / sum(So_Vu)) %>% ungroup()
3. ggplot(crime_by_type, aes(factor(Nam), Ty_le, fill = factor(Phan_Loai))) +
4.   geom_col(position = "fill", color = "white") +                         
5.   geom_text(aes(label = percent(Ty_le, 0.1)),                            
6.   position = position_fill(vjust = 0.5), color = "black", size = 3) +
7.   scale_y_continuous(labels = percent_format(accuracy = 1)) +   
8.   scale_fill_manual(values = c("#e34a33", "#2b8cbe"),                    
9.   labels = c("Tội nghiêm trọng", "Tội không nghiêm trọng")) +
10.   labs( title = "Cơ cấu phân loại tội phạm theo năm\n (2020–2023)",
11.     subtitle = "So sánh tỷ trọng tội nghiêm trọng và\n không nghiêm trọng trong từng năm", x = "Năm", y = "Tỷ trọng (%)", fill = "Phân loại" ) +
12.   theme_minimal(base_size = 13) +
13.   theme( plot.title = element_text(face = "bold"),
14.     plot.subtitle = element_text(color = "gray30"),
15.     plot.caption = element_text(color = "gray50"),
16.     panel.grid.minor = element_blank() )

Giải thích
Kỹ thuật:
- Dòng 1–2: Tiền xử lý chuẩn; cân nhắc tidyr::complete(Nam, Phan_Loai, fill = list(So_Vu=0, Ty_le=0)) để tránh thiếu nhóm; nhớ library(scales) cho percent().
- Dòng 3–6: position=“fill” + geom_text(position_fill(vjust=.5)) hợp lý; có thể làm tròn nhãn percent(Ty_le, accuracy=0.1).
- Dòng 7–9: Nhãn trục Y ok; nên dùng bảng màu thân thiện mù màu (scale_fill_viridis_d() hoặc Brewer) và đảm bảo thứ tự/nhãn của Phan_Loai khớp màu.
- Dòng 10–16: Nhãn/theme ổn; tránh hard-code “2020–2023” trong tiêu đề (dùng range(Nam)), và có thể tăng base_size/legend.position=“top” cho dễ đọc.
Ý nghĩa:
Biểu đồ cho thấy tội nghiêm trọng luôn chiếm tỷ lệ cao (57.6% đến 59.1%) trong các năm 2020-2023, chiếm phần lớn trong tổng số vụ tội phạm. Tội không nghiêm trọng chiếm tỷ lệ thấp hơn (40.2% đến 42.4%), và tỷ lệ này khá ổn định qua các năm. Mặc dù có sự thay đổi nhẹ, xu hướng tội phạm nghiêm trọng vẫn chiếm ưu thế.

7. Top 10 mô tả tội phạm phổ biến nhất (2020–2023)

1. top10_desc <- crime_final %>% filter(Nam != 2024) %>%
2.   count(Mo_ta_Toi_Pham, name = "So_Vu") %>% slice_max(order_by = So_Vu, n = 10) %>% arrange(So_Vu) %>%
3.   mutate( Rank  = row_number(), 
4.     Label = paste0(sprintf("%02d", 11 - Rank), ". ",
5.    str_to_title(str_wrap(Mo_ta_Toi_Pham, width = 35))),
6.     Label = factor(Label, levels = Label) )
7. ggplot(top10_desc, aes(x = So_Vu, y = Label)) +
8.   geom_segment(aes(x = 0, xend = So_Vu, yend = Label),
9.                linewidth = 1.1, color = "gray75", lineend = "round") +
10.   geom_point(aes(color = So_Vu), size = 4) +
11.   geom_text(aes(label = label_number(scale_cut = cut_short_scale())(So_Vu)),
12.   nudge_x = max(top10_desc$So_Vu) * 0.1, size = 3.4, family = "", fontface = "bold") + scale_color_gradient(low = "#9ecae1", high = "#08519c", guide = "none") + scale_x_continuous( labels = label_number(scale_cut = cut_short_scale()), expand = expansion(mult = c(0, 0.15)) ) +
13.   labs( title = "Top 10 mô tả tội phạm phổ biến nhất (2020–2023)",
14.   subtitle = "Lollipop chart — xếp hạng (01–10) bên trái; điểm màu đậm = số vụ lớn", x = "Số vụ phạm tội", y = NULL ) + theme_minimal(base_size = 11) +
15.   theme( plot.title    = element_text(face = "bold"),
16.     plot.subtitle = element_text(color = "gray35"),
17.     plot.caption  = element_text(color = "gray50"),
18.     axis.text.y   = element_text(hjust = 0, lineheight = 1.1),        
19.     panel.grid.major.y = element_blank(), panel.grid.minor   = element_blank())

Giải thích
Kỹ thuật:
- Dòng 1–6: Pipeline ổn; đơn giản hóa bằng rank = dplyr::min_rank(desc(So_Vu)), Label = sprintf(“%02d. %s”, rank, str_to_title(str_wrap(…))), và Label = forcats::fct_reorder(Label, So_Vu) (khỏi cần 11 - Rank).
- Dòng 7–12: Lollipop đẹp; giữ expand, cân nhắc coord_cartesian(clip = “off”) để nhãn không bị cắt và bỏ family = ““; nên tính sẵn nhãn số trong mutate.
- Dòng 8–12: Gradient ổn nhưng nên dùng bảng màu thân thiện mù màu (scale_color_viridis_c(guide =”none”)).
- Dòng 13–19: Nhãn/theme tốt; tránh hard-code “2020–2023” (tạo từ min/max(Nam)), các tùy chỉnh y-label bạn đang dùng là hợp lý.
Ý nghĩa:
Biểu đồ cho thấy trộm cắp xe và các hành vi tấn công đơn giản là các tội phạm phổ biến nhất, trong khi trộm cắp tài sản và các hành vi tấn công khác có số vụ ít hơn nhưng vẫn chiếm phần lớn.

8. Cơ cấu tình trạng bắt giữ theo năm (2020–2023)

1. ggplot(crime_by_status, aes(x = factor(Trang_Thai), y = Ty_le, fill = Trang_Thai)) +
2.   geom_bar(stat = "identity", position = "fill") +  # Biểu đồ tỷ lệ
3.   labs( title = "Cơ cấu tình trạng bắt giữ theo tỷ lệ (2020–2023)",
4.     x = "Tình trạng bắt giữ", y = "Tỷ lệ (%)", fill = "Tình trạng bắt giữ"
5.   ) + scale_y_continuous(labels = scales::percent) +  
6.   theme_minimal() + theme(  plot.title = element_text(face = "bold", size = 14),
7.     axis.text.x = element_text(size = 12, angle = 0, hjust = 0.5),
8.     axis.text.y = element_text(size = 12),
9.     legend.title = element_text(size = 12),
10.     legend.text = element_text(size = 10)  )

Giải thích
Kỹ thuật:
- Dòng 1–2: Cấu trúc đúng cho biểu đồ tỷ lệ; có thể bỏ stat=“identity” nếu dữ liệu đã là tỷ lệ.
- Dòng 3–5: Nhãn rõ; scale_y_continuous(labels = percent_format(accuracy = 1)) cho đẹp hơn.
- Dòng 6–10: Theme ổn; nên sắp Trang_Thai theo tỷ lệ (fct_reorder) và dùng bảng màu dễ phân biệt (scale_fill_brewer(palette=“Set2”)).
Ý nghĩa:
Biểu đồ cho thấy tỷ lệ các tình trạng bắt giữ trong giai đoạn 2020–2023 khá đồng đều và ổn định, với không có tình trạng nào chiếm ưu thế vượt trội, phản ánh một sự phân bố tội phạm đều giữa các tình trạng bắt giữ trong giai đoạn này

9. Biểu đồ tần số tội phạm theo loại tội phạm

1. ggplot(crime_by_type, aes(x = reorder(Phan_Loai, -So_Vu), y = So_Vu, fill = Phan_Loai)) + geom_bar(stat = "identity") +
2.   labs( title = "Tần số tội phạm theo loại",
3.     x = "Loại tội phạm", y = "Số vụ tội phạm",  fill = "Loại tội phạm"
4.   ) + scale_x_discrete(labels = c("1" = "Tội nghiêm trọng", "2" = "Tội nhẹ")) +
5.   theme_minimal() + theme( plot.title = element_text(face = "bold", size = 14),
6.     axis.text.x = element_text(angle = 0, hjust = 1),
7.   axis.text.y = element_text(size = 12), legend.title = element_text(size = 12),
8.     legend.text = element_text(size = 10) )

Giải thích
Kỹ thuật:
- Dòng 1: Biểu đồ đúng; nên dùng fct_reorder(Phan_Loai, So_Vu, .desc=TRUE) thay reorder(…) cho rõ ràng.
- Dòng 2–4: Nhãn đầy đủ; có thể bỏ scale_x_discrete(labels=…) nếu Phan_Loai đã có tên rõ.
- Dòng 5–8: Theme ổn; có thể xoay nhãn X 30° nếu trùng, và dùng scale_fill_brewer(palette=“Set2”) cho màu dễ phân biệt.
Ý nghĩa:
Biểu đồ cho thấy rằng phần lớn các vụ tội phạm là tội nghiêm trọng. Điều này phản ánh một xu hướng trong số liệu về tội phạm, cho thấy các hành vi nghiêm trọng chiếm ưu thế hơn so với các hành vi tội phạm nhẹ.

10. Phân loại tội phạm theo năm

1. crime_by_type_year <- crime_final %>% group_by(Nam, Phan_Loai) %>%
2.   summarise(So_Vu = n(), .groups = "drop")
3. ggplot(crime_by_type_year, aes(x = as.factor(Nam), y = So_Vu, fill = as.factor(Phan_Loai))) +
4.   geom_bar(stat = "identity", position = "dodge", alpha = 0.7) +
5.   labs(  title = "Phân loại tội phạm theo năm", x = "Năm", y = "Số vụ",
6.     fill = "Phân loại") + scale_fill_manual( values = c("#E74C3C", "#3498DB"),
7.     labels = c("1" = "Tội nghiêm trọng", "2" = "Không nghiêm trọng")  ) +
8.   theme_minimal() +  theme( plot.title = element_text(face = "bold", size = 16),
9.  axis.text.x = element_text(size = 12),legend.title = element_text(size = 12),
10.     legend.text = element_text(size = 11)  )

Ggiải thích
Kỹ thuật:
- Dòng 1–2: Tính tổng hợp đúng; có thể gọn hơn với count(Nam, Phan_Loai, name = “So_Vu”) và đảm bảo đủ tổ hợp bằng tidyr::complete(Nam, Phan_Loai, fill = list(So_Vu=0)).
- Dòng 3–4: Nên dùng geom_col(position = position_dodge(width = .8)) thay geom_bar(stat=“identity”); bỏ alpha để màu rõ hơn.
- Dòng 5–7: Nhãn ổn; tránh gắn nhãn theo mã “1/2”, tốt hơn là đặt tên mức của Phan_Loai trước hoặc labels = c(“Tội nghiêm trọng”,“Không nghiêm trọng”).
- Dòng 8–10: Theme ok; cân nhắc legend.position=“top” và scale_y_continuous(labels = scales::label_number(big.mark=“,”)) để dễ đọc.
Ý nghĩa:
Biểu đồ cho thấy số vụ tội nghiêm trọng luôn cao hơn không nghiêm trọng trong các năm. Tỷ lệ tội phạm có xu hướng tăng dần đến năm 2023 rồi giảm nhẹ vào năm 2024.
### 11. Cơ cấu giới tính nạn nhân theo nhóm tuổi (2020–2023)

1. crime_by_area <- crime_extended %>%
2.   group_by(Ma_Khu_Vuc) %>% summarise(So_Vu = n(), .groups = "drop") %>%
3.   arrange(desc(So_Vu))
4. ggplot(crime_by_area, aes(x = reorder(Ma_Khu_Vuc, -So_Vu), y = So_Vu, fill = Ma_Khu_Vuc)) + geom_bar(stat = "identity") +
5.   labs( title = "Tội phạm theo khu vực", x = "Khu vực", y = "Số vụ tội phạm",
6.     fill = "Khu vực" ) + theme_minimal() + theme(  plot.title = element_text(face = "bold", size = 14),
7.     axis.text.x = element_text(angle = 0, hjust = 1, bold= 1),
8.     axis.text.y = element_text(size = 12),
9.     legend.title = element_text(size = 12),
10.     legend.text = element_text(size = 10) )

Giải thích
Kỹ thuật:
- Dòng 1–3: Tiền xử lý đúng; có thể gọn bằng count(Ma_Khu_Vuc, name=“So_Vu”, sort=TRUE).
- Dòng 4: Biểu đồ hợp lý; nếu nhiều khu vực, nên tô một màu (fill=“#3498DB”) thay vì theo khu vực để tránh rối.
- Dòng 5–6: Nhãn rõ ràng, theme ổn. Dòng 7–10: bold=1 không hợp lệ; dùng element_text(face=“bold”) và xoay nhãn X 30° nếu bị chồng.
Ý nghĩa:
Biểu đồ cho thấy khu vực 1 và 12 có tần suất tội phạm cao nhất, trong khi các khu vực khác có sự giảm dần về số vụ. Điều này có thể phản ánh sự phân bố tội phạm không đồng đều giữa các khu vực, có thể do yếu tố dân cư, kinh tế hoặc các yếu tố xã hội khác.

12. Cơ cấu phân loại tội phạm theo giới tính nạn nhân (2020–2023)

1. crime_by_gender <- crime_cleaned %>%
2.   group_by(Gioi_Tinh_Nan_Nhan) %>%
3.   summarise(So_Vu = n(), .groups = "drop")
4. ggplot(crime_by_gender, aes(x = Gioi_Tinh_Nan_Nhan, y = So_Vu, fill = Gioi_Tinh_Nan_Nhan)) + geom_bar(stat = "identity") +
5.   labs( title = "Phân bố tội phạm theo giới tính nạn nhân",
6.     x = "Giới tính nạn nhân", y = "Số vụ tội phạm",
7.     fill = "Giới tính" ) +  theme_minimal() +  theme(
8.     plot.title = element_text(face = "bold", size = 14),
9.     axis.text.x = element_text(angle = 0, hjust = 0.5),
10.     axis.text.y = element_text(size = 12)  )

Giải thích
Kỹ thuật:
- Dòng 1–3: Tổng hợp đúng; có thể gọn hơn với count(Gioi_Tinh_Nan_Nhan, name=“So_Vu”).
- Dòng 4: Biểu đồ rõ; nếu chỉ 2 giới, nên tô màu thủ công (scale_fill_manual(values=c(“#e74c3c”,“#3498db”))).
- Dòng 5–7: Nhãn rõ ràng, theme tối giản phù hợp.
- Dòng 8–10: Trình bày ổn; có thể thêm legend.position=“none” để tránh trùng thông tin với trục X.
Ý nghĩa:
Biểu đồ này cho thấy sự chênh lệch rõ rệt trong số vụ tội phạm giữa các giới tính, với nữ và nam chiếm phần lớn, còn giới tính khác có tỷ lệ thấp hơn nhiều.

13. Biểu đồ tròn (Pie chart) cho từng khu vực

1. crime_by_area_status %>%
2.   filter(Khu_Vuc %in% c("Central", "77th Street")) %>%  
3.   group_by(Khu_Vuc, Trang_Thai) %>%
4.   summarise(Ty_le = sum(Ty_le), .groups = "drop") %>%
5.   mutate(Percent = Ty_le / sum(Ty_le) * 100) %>%  
6.   ggplot(aes(x = "", y = Ty_le, fill = Trang_Thai)) +
7.   geom_col(width = 1) + coord_polar("y", start = 0) +  facet_wrap(~ Khu_Vuc) +
8.   geom_text(aes(label = ifelse(Percent > 3, paste0(round(Percent, 1), "%"), "")), position = position_stack(vjust = 0.5), size = 4, 
9.    check_overlap = TRUE, angle = 0) +   labs( title = "Cơ cấu tình trạng vụ án\n trong từng khu vực (2020–2023)", 
10.     fill = "Tình trạng vụ án" ) +  theme_void() +
11.   theme( plot.title = element_text(hjust = 0.5, face = "bold", size = 18, lineheight = 1.2), strip.text = element_text(size = 12, face = "bold"),
12.     legend.title = element_text(size = 12),
13.     legend.text = element_text(size = 10)  )

Giải thích Kỹ thuật:
- Dòng 1–5: Tiền xử lý đúng; nhưng Percent = Ty_le / sum(Ty_le) nên tính theo từng Khu_Vuc (group_by(Khu_Vuc) trước mutate).
- Dòng 6–7: Dạng pie chart hợp lý; có thể thêm color = “white” trong geom_col() cho ranh giới rõ hơn.
- Dòng 8–10: Nhãn rõ, điều kiện Percent > 3 hợp lý; có thể tăng vjust nhẹ để cân giữa lát.
- Dòng 11–13: Theme đẹp; có thể đặt legend.position=“bottom” để tiết kiệm không gian facet.
Ý nghĩa:
Biểu đồ cung cấp cái nhìn rõ ràng về sự phân bố tình trạng vụ án giữa hai khu vực “77th Street” và “Central”. Khu vực 77th Street có sự phân bố đồng đều hơn giữa các tình trạng vụ án, trong khi Central có sự tập trung cao hơn vào một số tình trạng cụ thể như “AA”.

14. Phân bố số vụ tội phạm theo khu vực và phân loại (2020–2023)

1. ggplot(crime_by_area_status,
2. aes(x = Trang_Thai, y = reorder(Khu_Vuc, -So_Vu), fill = Ty_le)) +
3. geom_tile(color = "white") + geom_text(aes(label = paste0(Ty_le, "%")),
4. color = "black", size = 3.2) +
5. scale_fill_gradient(low = "#d4f0ff", high = "#0066cc") +
6. labs( title = "Tỷ lệ tình trạng vụ án theo khu vực (2020–2023)",
7. x = "Tình trạng vụ án", y = "Khu vực", fill = "Tỷ lệ (%)") +
8. theme_minimal(base_size = 12) +
9. theme( plot.title = element_text(face = "bold", size = 14, hjust = 0.5),
10. axis.text.x = element_text(angle = 45, hjust = 1),
11. panel.grid = element_blank())

Giải thích
Kỹ thuật:  - Dòng 1–4: Cấu trúc heatmap đúng; nên làm tròn nhãn paste0(round(Ty_le,1), “%”) để gọn hơn.
- Dòng 5: Thang màu hợp lý; có thể thay bằng scale_fill_viridis_c(option=“C”) cho dễ phân biệt.
- Dòng 6–7: Nhãn rõ, tiêu đề tốt; tránh hard-code “2020–2023” (dùng range(Nam)).
- Dòng 8–11: Theme sạch; angle=45 hợp lý, có thể thêm legend.position=“top” để bố cục cân đối.
Ý nghĩa:
Biểu đồ này cho thấy sự phân bố tỷ lệ tình trạng vụ án theo từng khu vực, với phần lớn các khu vực có tỷ lệ tội nghiêm trọng (AA) cao. Các khu vực như Foothill, Van Nuys và Hollenbeck có sự phân bố tội phạm nghiêm trọng rõ rệt, trong khi những khu vực khác có sự phân bổ đa dạng hơn với các tình trạng vụ án khác như AO, IC.

15. Mối quan hệ giữa “Trạng thái vụ án” và “Phân loại tội phạm”

1. df_status_type <- crime_final %>%
2.   filter(Nam != 2024) %>%  mutate(
3.     Phan_Loai = recode(Phan_Loai, "1" = "Tội nghiêm trọng", "2" = "Tội không nghiêm trọng"), Trang_Thai = fct_lump_n(Trang_Thai, n = 6)
4.   ) %>% count(Phan_Loai, Trang_Thai, name = "So_Vu") %>%
5.   group_by(Phan_Loai) %>% mutate(Ty_le = So_Vu / sum(So_Vu) * 100)
6. ggplot(df_status_type, aes(x = Phan_Loai, y = Ty_le, fill = Trang_Thai)) +
7.   geom_col(position = "fill", color = "white") +
8.   geom_text(aes(label =ifelse(Ty_le > 3, paste0(round(Ty_le, 1), "%"),"")),
9.    position = position_fill(vjust = 0.5), size = 3) +
10.   scale_fill_brewer(palette = "Set2") +
11.   scale_y_continuous(labels = percent_format(scale = 100)) +
12.   labs( title = "Phân bố trạng thái vụ án theo\n loại tội phạm (2020–2023)",
13.     subtitle = "Biểu đồ cột chồng 100% — thể hiện tỷ trọng từng\n trạng thái trong mỗi loại tội", x = "Phân loại tội phạm", y = "Tỷ trọng (%)",
14.     fill = "Trạng thái hồ sơ" ) + theme_minimal() +
15.   theme( plot.title = element_text(face = "bold", hjust = 0, lineheight = 1.1),
16.     plot.subtitle = element_text(color = "gray35", hjust = 0, size = 12, lineheight = 1.2), plot.caption = element_text(color = "gray50", hjust = 0), 
17.     legend.position = "top" )

Giải thích
Kỹ thuật:
- Dòng 1–5: Tiền xử lý ổn; tránh “chuẩn hoá kép”: dùng y = So_Vu + position=“fill” hoặc giữ y = Ty_le và bỏ position=“fill”. Nhớ library(forcats) cho fct_lump_n().
- Dòng 6–9: Cột chồng 100% hợp lý; nhãn nên làm tròn: round(..,1). Nếu chuyển sang y=So_Vu, tạo nhãn từ tỷ lệ tính sẵn theo nhóm Phan_Loai.
- Dòng 10–11: Màu Set2 dễ đọc; scale_y_continuous(labels = scales::percent_format(accuracy = 1)) là đủ (không cần scale = 100).
- Dòng 12–17: Nhãn/theme đẹp; tránh hard-code “2020–2023” (lấy từ range(Nam)), legend đặt top là hợp lý.
Ý nghĩa:
Biểu đồ này cho thấy tội không nghiêm trọng có tỷ lệ vụ án đang điều tra (AO) cao hơn nhiều so với tội nghiêm trọng, trong khi tội nghiêm trọng lại có tỷ lệ vụ án chưa giải quyết cao hơn. Các trạng thái khác như AA, CC, và JA có tỷ lệ thấp hơn, nhưng vẫn chiếm một phần nhất định trong mỗi nhóm tội phạm.

16. Số tội danh trong mỗi vụ án

1. crime_final <- crime_final %>%
2.   mutate(
3.     So_Toi_Danh = rowSums(select(., starts_with("Ma_Toi_Pham")) != "0", na.rm = TRUE)  )
4. # Đếm số vụ án có 1, 2, 3, 4 tội danh và tính tỷ lệ phần trăm
5. statistics <- crime_final %>%
6.   count(So_Toi_Danh) %>%
7.   mutate(Ty_le = n / sum(n) * 100)
8. statistics <- statistics %>%
9.   mutate(vjust_position = ifelse(Ty_le > 90, 1, -0.5))
10. # Vẽ biểu đồ tỷ lệ phần trăm của mỗi nhóm tội danh
11. ggplot(statistics, aes(x = factor(So_Toi_Danh), y = Ty_le, fill = factor(So_Toi_Danh))) +
12.   geom_bar(stat = "identity", color = "black") +
13.   geom_text(aes(label = paste0(round(Ty_le, 1), "%")), vjust = statistics$vjust_position, size = 5) +
14.   labs(
15.     title = "Tỷ lệ phần trăm vụ án theo số lượng tội danh",
16.     x = "Số tội danh",
17.     y = "Tỷ lệ (%)",
18.     fill = "Số tội danh"
19.   ) +
20.   theme_minimal() +
21.   theme(
22.     plot.title = element_text(size = 16, face = "bold"),
23.     axis.title = element_text(size = 14),
24.     axis.text = element_text(size = 12))

Giải thích
Kỹ thuật
- Dòng 1–3: Tính So_Toi_Danh nên dùng số thay vì so sánh chuỗi “0”: mutate(So_Toi_Danh = across(starts_with(“Ma_Toi_Pham”)) |> {(.) rowSums(. != 0,
na.rm = TRUE)}).
- Dòng 5–7: Tổng hợp OK; có thể count(So_Toi_Danh, name=“So_Vu”) |> mutate(Ty_le = So_Vu/sum(So_Vu)100).
- Dòng 8–9: Không nên gọi vjust từ data bên ngoài layer; tính trong data rồi dùng aes(vjust = vjust_position) trong geom_text().
- Dòng 11–24: Dùng geom_col() (gọn), legend.position=“none” (fill trùng trục X), và scale_y_continuous(labels = scales::percent_format(accuracy = 0.1)) để hiển thị phần trăm đẹp hơn.
Ý nghĩa:*
Biểu đồ cho thấy rằng phần lớn các vụ án trong dữ liệu này có 1 tội danh, một số ít có 2 tội danh, và rất ít vụ án có 3 tội danh. Không có vụ án nào có 4 tội danh. Điều này phản ánh rằng các vụ án trong bộ dữ liệu này có xu hướng đơn giản hơn, với ít tội danh trong mỗi vụ.

17. Số vụ tội phạm theo năm báo cáo

1. crime_by_year <- crime_renamed %>% mutate(Nam = year(ymd(Ngay_Bao_Cao))) %>%
2.   group_by(Nam) %>% summarise(So_Vu = n(), .groups = "drop")
3. ggplot(crime_by_year, aes(x = So_Vu, y = factor(Nam))) +
4.   geom_col(fill = "#FFCC99") + labs( title = "Số vụ tội phạm theo năm báo cáo",
5.   x = "Số vụ tội phạm", y = "Năm" ) + theme_minimal(base_size = 12) +
6.   theme(plot.title = element_text(face = "bold"))

Giải thích
Kỹ thuật:
- Dòng 1–2: Tiền xử lý gọn, đúng; có thể thêm arrange(Nam) để trục Y hiển thị theo thời gian.
- Dòng 3–4: Biểu đồ ngang rõ ràng; dùng geom_col() hợp lý, màu nhẹ dễ nhìn.
- Dòng 5: Nhãn đầy đủ, theme tối giản ổn.
- Dòng 6: Có thể thêm axis.text.y = element_text(face=“bold”) hoặc geom_text(aes(label=So_Vu), hjust=-0.1) để biểu đồ trực quan hơn.
Ý nghĩa:
Biểu đồ cho thấy số vụ tội phạm tăng mạnh trong năm 2024, với số vụ cao nhất trong các năm từ 2020 đến 2024. Các năm trước đó (2020-2023) có xu hướng giảm dần về số vụ tội phạm.

18. Top 10 mã tội phạm phổ biến nhất

1. crime_by_code <- crime_renamed %>%  group_by(Ma_Toi_Pham_1) %>%
2.   summarise(So_Vu = n(), .groups = "drop") %>% arrange(desc(So_Vu)) %>%
3.   slice_head(n = 10) 
4. ggplot(crime_by_code, aes(x = So_Vu, y = reorder(Ma_Toi_Pham_1, So_Vu), fill = So_Vu)) + geom_col() + labs( title = "Top 10 mã tội phạm phổ biến nhất",
5.    x = "Số vụ tội phạm", y = "Mã tội phạm" ) +
6.   scale_fill_gradient(low = "lightcoral", high = "darkred") +   theme_minimal(base_size = 12) + theme(plot.title = element_text(face = "bold"))

Giải thích
Kỹ thuật
- Dòng 1–2: Tiền xử lý gọn, đúng; có thể thêm arrange(Nam) để trục Y đúng thứ tự thời gian.
- Dòng 3–4: Biểu đồ ngang hợp lý; geom_col() thay vì geom_bar(stat=“identity”) là chuẩn.
- Dòng 5: Nhãn rõ, theme tối giản đẹp.
- Dòng 6: Có thể thêm axis.text.y = element_text(face=“bold”) hoặc fill=“#F4A261” cho màu ấm dễ nhìn hơn.
Ý nghĩa:
Biểu đồ thể hiện top 10 mã tội phạm phổ biến nhất, trong đó mã 510 có số vụ cao nhất, vượt qua 100,000 vụ. Các mã còn lại có số vụ giảm dần nhưng vẫn đóng góp đáng kể. Biểu đồ cho thấy sự phân bố không đều, với một số mã chiếm ưu thế lớn trong tổng số vụ tội phạm.

19. Top 10 địa điểm xảy ra tội phạm nhiều nhấ

1. crime_by_place <- crime_renamed %>% group_by(Ma_Khu_Vuc) %>%
2.   summarise(So_Vu = n(), .groups = "drop") %>% arrange(desc(So_Vu)) %>%
3.   slice_head(n = 10) 
4. ggplot(crime_by_place, aes(x = So_Vu, y = reorder(Ma_Khu_Vuc, So_Vu), fill = So_Vu)) + geom_col() + labs( title = "Top 10 địa điểm xảy ra tội phạm nhiều nhất", x = "Số vụ", y = "Mô tả địa điểm" ) +  scale_fill_gradient(low = "lightblue", high = "darkblue") + theme_minimal(base_size = 12) +
5.   theme(plot.title = element_text(face = "bold"))

Giải thích
Kỹ thuật:
- Dòng 1–3: Có thể gọn bằng count(Ma_Khu_Vuc, name=“So_Vu”, sort=TRUE) |> slice_max(So_Vu, n=10).
- Dòng 4: fill = So_Vu tạo legend thừa → thêm guides(fill = “none”); đổi scale_fill_viridis_c() thân thiện mù màu.
- Dòng 4: Thêm nhãn số geom_text(aes(label = scales::comma(So_Vu)), hjust = -0.1) + expand = expansion(mult = c(0, .05)).
- Nhãn: đổi y = “Khu vực” (đúng với Ma_Khu_Vuc).
Ý nghĩa:
Biểu đồ cho thấy khu vực “Central” (1) có số vụ tội phạm cao nhất, vượt qua 60,000 vụ, trong khi các khu vực như “Rampart” (2) và “Southwest” (3) có số vụ thấp hơn. Màu sắc gradient giúp phân biệt các khu vực có số vụ nhiều nhất.

20. Mối quan hệ giữa tuổi của nạn nhân và số tội danh trong mỗi vụ án

1. final <- crime_final %>%
2.   mutate(Nhom_Tuoi = factor(Nhom_Tuoi))
3. ggplot(final, aes(x = Nhom_Tuoi, y = Tuoi_Nan_Nhan, fill = Nhom_Tuoi)) +
4.   geom_boxplot() +
5.   labs(title = "Mối quan hệ giữa tuổi của nạn nhân và\n số tội danh trong mỗi vụ án", x = "Nhóm tuổi", y = "Tuổi của nạn nhân") +
6.   theme_minimal() +
7.   theme( plot.title = element_text(size = 16, face = "bold", lineheight = 1.1),
8.     axis.title = element_text(size = 14),
9.     axis.text = element_text(size = 12), 
10.     axis.text.x = element_blank() )

Giải thích
Kỹ thuật: 
- Dòng 1–2: Tiền xử lý đúng; có thể thêm forcats::fct_reorder(Nhom_Tuoi, Tuoi_Nan_Nhan) nếu muốn sắp theo trung vị.
- Dòng 3–4: geom_boxplot() hợp lý; nếu nhiều nhóm, nên thêm outlier.color=“gray50”, alpha=0.8 để đồ thị sạch hơn.
- Dòng 5: Tiêu đề sai nội dung — nên đổi thành “Phân bố tuổi nạn nhân theo nhóm tuổi” cho đúng ý.
- Dòng 6–10: Theme ổn; nếu muốn hiển thị nhãn trục X, bỏ axis.text.x = element_blank() hoặc xoay nhẹ 30°.
Ý nghĩa:
- Nhóm tuổi “Cao niên (60-74)” có độ tuổi trung bình cao nhất, với sự phân bổ rộng và có một vài giá trị cực trị.
- Nhóm tuổi “Dưới 10 tuổi” có độ tuổi rất thấp, nhưng độ phân tán khá rộng.
- Các nhóm khác như Già (75+) và Thanh niên (18-29) có sự phân bố tuổi khá đồng đều, nhưng độ tuổi của nạn nhân trong các nhóm này có xu hướng tăng dần theo số tội danh.

PHẦN 2: PHÂN TÍCH MÃ CHỨNG KHOÁN VNM

CHƯƠNG 1: GIỚI THIỆU BỘ DỮ LIỆU

1. Đọc dữ liệu

1. # Đọc 3 sheet vào 3 biến riêng
2. sheet1 <- read_excel("D:/ngongulaptrinh/VNM/VNM.xlsx", sheet = "CDKT")
3. sheet2 <- read_excel("D:/ngongulaptrinh/VNM/VNM.xlsx", sheet = "HDKD")
4. sheet3 <- read_excel("D:/ngongulaptrinh/VNM/VNM.xlsx", sheet = "LCTT")
5. # Gộp 3 bảng lại thành một (ví dụ gộp theo hàng - row bind)
6. vnm <- sheet1 %>%
7.   full_join(sheet2, by = names(sheet1)[1]) %>%
8.   full_join(sheet3, by = names(sheet1)[1]) %>%
9.   arrange(!!sym(names(sheet1)[1]))
10. name_map <- tibble::tibble(ten_goc = names(vnm)); names(vnm) <- janitor::make_clean_names(names(vnm)); name_map$ten_moi <- names(vnm); head(name_map, 12)
1. # Kiểm tra kết quả
2. head(vnm,10)

Giải thích
Kỹ thuật:
- Dòng 1–3: read_excel() — đọc ba sheet riêng biệt từ cùng một file VNM.xlsx, lần lượt là CDKT, HDKD và LCTT. Mỗi sheet đại diện cho một báo cáo tài chính khác nhau của Vinamilk.
- Dòng 6–9: sử dụng full_join() để gộp ba bảng dữ liệu lại dựa trên cột đầu tiên (thường là Năm), đảm bảo không mất dữ liệu giữa các sheet. Hàm arrange() giúp sắp xếp lại theo thứ tự thời gian tăng dần.
- Dòng 11: tibble() — tạo bảng ánh xạ tên cột gốc, lưu lại để so sánh trước và sau khi đổi tên.
- Dòng 11 : make_clean_names() — chuẩn hóa toàn bộ tên cột (bỏ dấu, thay khoảng trắng bằng “_”), tránh lỗi mã hóa tiếng Việt.
- Dòng 12: gán tên mới vào bảng name_map, sau đó dùng head() để xem nhanh 12 dòng đầu tiên trong bảng ánh xạ tên biến.
- Dòng 14: head(vnm, 10) — xem 10 dòng đầu của dữ liệu sau khi gộp, đảm bảo quá trình kết nối thành công.
Ý nghĩa:
Đoạn mã thực hiện bước tiền xử lý dữ liệu tài chính: đọc, gộp, chuẩn hóa và kiểm tra.
Cách gộp này giúp tập hợp toàn bộ dữ liệu 3 báo cáo (CĐKT, HĐKD, LCTT) theo từng năm, tạo nền tảng cho các bước phân tích tiếp theo.
Việc chuẩn hóa tên biến giúp R xử lý mượt tiếng Việt, hạn chế lỗi font hoặc lỗi truy cập cột.

2. Khám phá dữ liệu

1. Xem nhanh 10 dòng đầu của các biến chính

1. bien_chinh <- c(
2.   "Năm",
3.   "tong_cong_tai_san", "no_phai_tra", "von_chu_so_huu")
4. vnm %>%
5.   dplyr::select(dplyr::any_of(bien_chinh)) %>%
6.   head(10)

Giải thích
Kỹ thuật:
- Dòng 1: Chọn 4 biến chính: Năm, Tổng tài sản, Nợ phải trả, Vốn chủ sở hữu .
- Dòng 5: Dùng select(any_of()) để lấy các cột này và head(10) xem 10 dòng đầu.
Ý nghĩa:
Kiểm tra nhanh quy mô và cấu trúc tài chính từng năm.
Đảm bảo dữ liệu đã gộp đúng và cân đối giữa tài sản – nguồn vốn.

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

1. dim(vnm)
## [1]  10 154

Giải thích
dim(vnm)
Trả về số dòng và số cột của dữ liệu.
Cung cấp thông tin về quy mô mẫu dữ liệu, hỗ trợ kiểm tra xem dữ liệu đã được nhập đầy đủ chưa.

3. Kiểm tra kiểu dữ liệu của biến năm

1. if ("Năm" %in% names(vnm)) str(vnm$Nam)

Giải thích
- str(vnm\$Năm) Kiểm tra riêng kiểu dữ liệu của biến Năm (numeric, character, hay date).
Giúp đảm bảo rằng cột năm đang ở định dạng số, cần thiết cho các phép nhóm, lọc và phân tích theo thời gian.

4. Kiểm tra dữ liệu thiếu (tổng số NA toàn bảng)

1. sum(is.na(vnm))
## [1] 122

Giải thích
-sum(is.na(vnm))
Đếm tổng số giá trị bị thiếu (NA) trong toàn bộ bảng dữ liệu.
Cho biết mức độ hoàn thiện của dữ liệu; nếu số lượng NA lớn, cần xử lý trước khi thống kê.

5. Kiểm tra trùng lặp theo cột năm

1. if ("Năm" %in% names(vnm)) table(duplicated(vnm$Năm))

Giải thích
-table(duplicated(vnm\$Năm))
Kiểm tra các giá trị trùng lặp trong biến Năm.
Nếu có dòng trùng, cần xem xét gộp hoặc loại bỏ để đảm bảo mỗi năm chỉ có một quan sát đại diện, giữ cho dữ liệu nhất quán khi phân tích chuỗi thời gian. Nhưng kết quả cho thấy không có dòng trùng.

6. Xem 10 dòng cuối cùng của các biến quan trọng

1. bien <- c(
2.   "nam", "tong_cong_tai_san", "no_phai_tra", "von_chu_so_huu")
3. vnm %>%
4.   dplyr::select(dplyr::any_of(bien_chinh)) %>%
5.   tail(10)

Giải thích
Kỹ thuật:
- Dòng 1: Tạo danh sách biến chính gồm Năm, Tổng tài sản, Nợ phải trả, Vốn chủ sở hữu.
- Dòng 4-5: select(any_of()) chọn các cột này; tail(10) hiển thị 10 dòng cuối trong bảng dữ liệu.
Ý nghĩa:
Giúp kiểm tra dữ liệu giai đoạn gần nhất (các năm cuối).
Dùng để xác nhận tính liên tục và hợp lệ của dữ liệu trước khi phân tích xu hướng tài chính.

7. Kiểm tra số lượng biến theo từng kiểu dữ liệu

1. table(map_chr(vnm, ~ class(.x)[1]))
## 
## character   numeric   POSIXct 
##        27       126         1

Giải thích
Kỹ thuật:
- map_chr(...class(.x)[1]) lấy kiểu dữ liệu của từng cột.
-table() đếm số lượng cột theo từng kiểu.
Ý nghĩa:
Giúp xem bao nhiêu cột là số, chữ, hay ngày, phục vụ chuẩn hóa dữ liệu.

CHƯƠNG 2: XỬ LÝ DỮ LIỆU THÔ VÀ MÃ HÓA

1. Xử lý cột thời gian

1. # Tạo cột năm (YYYY) từ cột POSIXct 'nam'
2. vnm <- vnm %>%
3.   mutate(n = as.numeric(format(as.Date(nam, tz = "UTC"), "%Y")))
4. # Kiểm tra nhanh
5. vnm %>% select(nam, n) %>% head()

Giải thích
Kỹ thuật:
- Dòng 3:ymd(Năm) chuyển chuỗi ngày (ví dụ “2020-12-31”) về định dạng ngày chuẩn.
year(...) trích riêng phần năm (YYYY).
suppressWarnings(...) ẩn cảnh báo nếu một vài dòng không đúng định dạng ngày.
- Dòng 4: filter(!is.na(Năm)) loại bỏ dòng trống hoặc lỗi khi chuyển đổi.
- Dòng 5: distinct(Năm, .keep_all = TRUE) nếu còn trùng năm, chỉ giữ 1 dòng.
- Dòng 6: arrange(Năm) sắp xếp lại theo thứ tự năm tăng dần.
Ý nghĩa:
Giúp đồng nhất định dạng thời gian trong toàn bộ dữ liệu, đảm bảo mỗi quan sát đại diện cho một năm duy nhất.

2. Chuyển định dạng các cột ký tự về dạng số

1. vnm <- vnm %>%
2.   mutate(across(where(is.character) & !matches("^(Năm|Nam|Year|Date|Ngay|date|ngay)$"),
3.                 ~ suppressWarnings(parse_number(.x))))

Giải thích
Kỹ thuật:
- Dòng 2: where(is.character): chọn tất cả cột có kiểu chuỗi ký tự.
!matches("\^(Năm\|Nam\|Year\|Date\|Ngay\|date\|ngay)\$") loại trừ các cột có tên liên quan đến thời gian.
- Dòng 4:parse_number(.x) tự động chuyển ký tự sang số, bỏ dấu phẩy, dấu cách, ký tự đặc biệt.
suppressWarnings() ẩn cảnh báo nhỏ khi gặp ô trống hoặc ký hiệu không phải số.
Ý nghĩa:
Giúp chuẩn hóa kiểu dữ liệu trong toàn bộ bộ dữ liệu tài chính, đảm bảo mọi biến định lượng đều ở dạng số.
Cột Năm vẫn giữ nguyên định dạng thời gian, giúp phân tích theo chuỗi năm chính xác.

3. Xử lý dữ liệu bị thiếu

1. vnm <- vnm %>%
2.   # Chuyển dấu "-" trong các cột ký tự thành NA
3.   mutate(across(where(is.character) & !matches("^(Năm|Nam|Year|Date|Ngay|date|ngay)$"),
4.                 ~ na_if(.x, "-"))) %>%
5.   # Thay toàn bộ NA trong các cột số bằng 0
6.   mutate(across(where(is.numeric) & !matches("^(Năm|Nam|Year|Date|Ngay|date|ngay)$"),
7.                 ~ dplyr::coalesce(.x, 0))) 

Giải thích
Kỹ thuật:
- Dòng 1: library(stringr): nạp một gói cần thiết làm việc với chuỗi ký tự (stringr).
- Dòng 2-6: where(is.character): chọn những cột có kiểu dữ liệu là ký tự (chữ hoặc chuỗi).
!matches(…): loại bỏ các cột liên quan đến thời gian như Năm, Date, Ngày để không bị tác động trong quá trình xử lý.
na_if(.x, “-”): nếu ô dữ liệu chứa dấu “–”, hệ thống sẽ thay bằng giá trị thiếu (NA).
- Dòng 9: where(is.numeric): chọn tất cả các cột dạng số trong bảng dữ liệu.
coalesce(.x, 0): thay toàn bộ giá trị thiếu (NA) trong các cột số bằng 0.
Ý nghĩa:
Tất cả các dấu “–” trong dữ liệu được thay bằng giá trị thiếu NA, sau đó những ô trống này được điền bằng 0. Bộ dữ liệu trở nên đầy đủ, không còn giá trị thiếu hoặc ký hiệu đặc biệt, giúp cho việc thống kê, tính toán và phân tích tài chính được thực hiện chính xác và ổn định hơn.

4. Chuyển định dạng số

1. library(scales)
2. vnm <- vnm %>%
3.   mutate(across(where(is.numeric) & !matches("Năm"), ~ .x / 1e9))  
4. # Hiển thị kết quả có dấu phân cách hàng nghìn
5. vnm %>%
6.   mutate(across(where(is.numeric) & !matches("Năm"),
7.                 ~ comma(.x, accuracy = 0.01))) %>%
8. select("tong_cong_tai_san", "no_phai_tra", "von_chu_so_huu") %>%  
9. head()

Giải thích
Kỹ thuật:
- Dòng 2-3: across(where(is.numeric), ~ .x / 1e9) → Chia toàn bộ các biến số cho 1 tỷ để chuyển từ đồng → tỷ đồng.
- Dòng 5-7: scales::comma() → Định dạng số có dấu phân cách hàng nghìn (,) giúp dễ đọc hơn.
accuracy = 0.01 → Giữ hai chữ số thập phân (có thể chỉnh tuỳ ý).
- Dòng 8: select() → chọn cột để hiển thị.
- Dòng 9: head() → Hiển thị vài dòng đầu để kiểm tra kết quả.
Ý nghĩa:
Việc đưa các giá trị về tỷ đồng giúp dễ diễn giải, đặc biệt khi vẽ đồ thị hoặc tính tỷ lệ phần trăm.
Định dạng số có dấu phân cách giúp tăng tính trực quan và độ chính xác khi trình bày kết quả trong báo cáo tài chính.

5. Chọn biến để phân tích

1. targets <- c(
2.  "nam",
3.   "tong_cong_tai_san",
4.   "tai_san_ngan_han",
5.   "tien_va_cac_khoan_tuong_duong_tien",
6.   "cac_khoan_dau_tu_tai_chinh_ngan_han",
7.   "cac_khoan_phai_thu_ngan_han",
8.   "hang_ton_kho",
9.   "tai_san_do_dang_dai_han",
10.   "chi_phi_tra_truoc_dai_han",
11.   "tai_san_co_dinh_huu_hinh",
12.   "tong_nguon_von",
13.   "doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02",
14.   "no_phai_tra",
15.   "no_ngan_han",
16.   "vay_ngan_han",
17.   "no_dai_han",
18.   "von_chu_so_huu",
19.   "loi_nhuan_sau_thue_chua_phan_phoi",
20.   "loi_nhuan_sau_thue_tndn",
21.   "luu_chuyen_tien_thuan_tu_hoat_dong_kinh_doanh",
22.   "luu_chuyen_tien_thuan_tu_hoat_dong_dau_tu",
23.   "luu_chuyen_tien_thuan_tu_hoat_dong_tai_chinh"
24. )
25. have    <- intersect(targets, names(vnm))
26. missing <- setdiff(targets, names(vnm))
27. vnm20 <- vnm[, have, drop = FALSE]
28. cat("Số biến chọn được:", length(have), "\n")
## Số biến chọn được: 22
1. if (length(missing)) {
2.   cat("Biến chưa tìm thấy (kiểm tra tên cột trong dữ liệu):\n")
3.   print(missing)
4. }
5. # Xem nhanh cấu trúc kết quả
6. str(vnm20)
## tibble [10 × 22] (S3: tbl_df/tbl/data.frame)
##  $ nam                                                     : POSIXct[1:10], format: "2015-12-31" "2016-12-31" ...
##  $ tong_cong_tai_san                                       : num [1:10] 27478 29379 34667 37366 44700 ...
##  $ tai_san_ngan_han                                        : num [1:10] 16732 18674 20307 20560 24722 ...
##  $ tien_va_cac_khoan_tuong_duong_tien                      : num [1:10] 1359 655 963 1523 2665 ...
##  $ cac_khoan_dau_tu_tai_chinh_ngan_han                     : num [1:10] 8668 10454 10562 8674 12436 ...
##  $ cac_khoan_phai_thu_ngan_han                             : num [1:10] 2685 2866 4592 4639 4503 ...
##  $ hang_ton_kho                                            : num [1:10] 3810 4522 4021 5526 4983 ...
##  $ tai_san_do_dang_dai_han                                 : num [1:10] 844 993 1929 868 944 ...
##  $ chi_phi_tra_truoc_dai_han                               : num [1:10] 417 460 612 751 679 ...
##  $ tai_san_co_dinh_huu_hinh                                : num [1:10] 7796 7916 10291 13048 13744 ...
##  $ tong_nguon_von                                          : num [1:10] 27478 29379 34667 37366 44700 ...
##  $ doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02: num [1:10] 40080 46794 51041 52562 56318 ...
##  $ no_phai_tra                                             : num [1:10] 6554 6973 10794 11095 14969 ...
##  $ no_ngan_han                                             : num [1:10] 6004 6457 10196 10640 14443 ...
##  $ vay_ngan_han                                            : num [1:10] 1476 1333 268 1060 5351 ...
##  $ no_dai_han                                              : num [1:10] 550 515 599 455 526 ...
##  $ von_chu_so_huu                                          : num [1:10] 20924 22406 23873 26271 29731 ...
##  $ loi_nhuan_sau_thue_chua_phan_phoi                       : num [1:10] 5392 5582 5737 7155 7875 ...
##  $ loi_nhuan_sau_thue_tndn                                 : num [1:10] 7770 9364 10278 10206 10554 ...
##  $ luu_chuyen_tien_thuan_tu_hoat_dong_kinh_doanh           : num [1:10] 7659 8390 9602 8140 11410 ...
##  $ luu_chuyen_tien_thuan_tu_hoat_dong_dau_tu               : num [1:10] -2126 -1946 -1779 -1045 -6748 ...
##  $ luu_chuyen_tien_thuan_tu_hoat_dong_tai_chinh            : num [1:10] -1764 -7141 -7535 -6535 -3516 ...

Giải thích
Kỹ thuật
- Dòng 1–24: targets <- c(...) — khai báo danh sách 22 biến tài chính mục tiêu (năm, tài sản, nợ, vốn, doanh thu, lợi nhuận, dòng tiền…). Đây là bước đặt tiêu chí lọc để chỉ làm việc với các cột quan trọng.
- Dòng 25: lấy giao giữa targets và tên cột thực tế của vnm, đảm bảo chỉ giữ những biến đang tồn tại trong dữ liệu để tránh lỗi do sai tên.
- Dòng 26: liệt kê những biến bị thiếu (có trong targets nhưng không có trong vnm), hỗ trợ phát hiện sai chính tả/khác chuẩn.
- Dòng 27: tạo tập con chỉ gồm các cột đã xác thực (have). Tham số drop = FALSE giữ cấu trúc data frame ngay cả khi chỉ có một cột được chọn.
- Dòng 28: in số lượng biến đã chọn thành công để kiểm chứng nhanh.
- Dòng 29–32: nếu có biến thiếu thì in danh sách các cột thiếu để người dùng rà soát và chuẩn hoá tên cột trong file nguồn.
- Dòng 34: kiểm tra cấu trúc dữ liệu sau lọc (tên biến, kiểu dữ liệu, số quan sát) để chắc chắn dữ liệu đã sẵn sàng cho các bước phân tích tiếp theo.
Ý nghĩa:
Đây là bước tiền xử lý có chọn lọc, giúp tập trung vào các chỉ tiêu tài chính cốt lõi, giảm nhiễu và tránh lỗi truy cập biến.
Việc tách have/missing tạo cơ chế tự kiểm tra: dữ liệu thay đổi hoặc tên cột lệch chuẩn sẽ được phát hiện ngay.
Bộ biến bao quát ba trụ cột: (i) Tài sản, (ii) Nguồn vốn & nợ, (iii) Hiệu quả & dòng tiền — tạo nền tảng cho mô tả thống kê, phân tích cơ cấu và mô hình dự báo.
Cách viết này giúp quy trình linh hoạt và tái lập: khi cập nhật dữ liệu mới, chỉ cần chạy lại khối lệnh để đồng bộ danh mục biến.

6. Mã hóa khả năng thanh khoản

1. vnm20 <- vnm20 %>%
2. mutate(
3. current_ratio = `tai_san_ngan_han` / `no_ngan_han`,
4. cash_ratio    = `tien_va_cac_khoan_tuong_duong_tien` / `no_ngan_han`)
5. head(vnm20[, c("current_ratio", "cash_ratio")])

Giải thích
Kỹ thuật:
- Dòng 2_4: tạo ra hai biến mới trong bảng dữ liệu vnm20.
current_ratio: được tính bằng Tài sản ngắn hạn / Nợ ngắn hạn. → Đây là hệ số thanh toán hiện hành, đo mức độ đảm bảo của tài sản lưu động so với nợ phải trả trong năm.
cash_ratio: được tính bằng Tiền và các khoản tương đương tiền / Nợ ngắn hạn. → Đây là hệ số thanh toán bằng tiền, phản ánh khả năng đáp ứng nhanh các khoản nợ ngắn hạn chỉ bằng tiền mặt.
- Dòng 5: hiển thị 6 dòng đầu tiên của hai biến vừa tạo, giúp bạn kiểm tra kết quả tính toán.
Ý nghĩa:
- Hệ số thanh toán hiện hành (Current Ratio)
Các giá trị > 1 cho thấy doanh nghiệp có khả năng thanh toán ngắn hạn tốt, tức là tài sản lưu động đủ bù đắp nợ phải trả.
Tỷ lệ quanh 2 lần được xem là an toàn và lành mạnh, phản ánh khả năng duy trì dòng vốn lưu động ổn định.
- Hệ số thanh toán bằng tiền (Cash Ratio)
Các giá trị trong khoảng 0.09–0.22 là mức hợp lý, nghĩa là chỉ 9–22% nợ ngắn hạn có thể được thanh toán ngay bằng tiền mặt.
- Tổng thể, hai hệ số cho thấy VNM có cấu trúc vốn lưu động lành mạnh, duy trì cân bằng giữa khả năng thanh toán và hiệu quả sử dụng tiền mặt..

7. Mã hóa cấu trúc vốn (Đòn bẩy tài chính)

1. vnm20 <- vnm20 %>%
2. mutate(
3. debt_ratio          = `no_phai_tra` / `tong_nguon_von`,
4. equity_ratio        = `von_chu_so_huu` / `tong_nguon_von`,
5. short_debt_ratio    = `vay_ngan_han` / `no_ngan_han`,
6. long_debt_to_equity = `no_dai_han` / `von_chu_so_huu`
7. )
8. head(vnm20[, c("debt_ratio", "equity_ratio", "short_debt_ratio", "long_debt_to_equity")])

Giải thích kỹ thuật

debt_ratio: là tỷ lệ giữa Nợ phải trả / Tổng nguồn vốn. → Đo lường mức độ sử dụng nợ trong tổng cơ cấu vốn của doanh nghiệp.

equity_ratio: là tỷ lệ Vốn chủ sở hữu / Tổng nguồn vốn. → Phản ánh phần vốn tự có chiếm trong tổng nguồn vốn.

short_debt_ratio: là tỷ lệ Vay ngắn hạn / Nợ ngắn hạn. → Cho thấy nợ ngắn hạn đến từ nguồn vay bao nhiêu phần trăm.

long_debt_to_equity: là tỷ lệ Nợ dài hạn / Vốn chủ sở hữu. → Đánh giá mức độ đòn bẩy tài chính dài hạn.

Ý nghĩa:

Tỷ lệ nợ trên tổng nguồn vốn (Debt ratio: 0.23 – 0.33) → Doanh nghiệp chỉ dùng khoảng 23–33% vốn vay trong tổng nguồn vốn. → Cho thấy mức đòn bẩy tài chính thấp, cấu trúc vốn an toàn và thận trọng.

Tỷ lệ vốn chủ sở hữu (Equity ratio: 0.66 – 0.76) → Vốn tự có chiếm phần lớn (66–76%) trong nguồn vốn. → Phản ánh khả năng tự chủ tài chính cao, ít phụ thuộc vào vốn vay.

Tỷ lệ vay ngắn hạn trong nợ ngắn hạn (Short debt ratio: 0.02 – 0.51) → Biến động giữa các năm cho thấy doanh nghiệp linh hoạt trong chính sách tài trợ vốn lưu động. → Các giai đoạn tỷ lệ cao thể hiện nhu cầu vốn ngắn hạn tăng, nhưng vẫn trong mức kiểm soát rủi ro hợp lý.

Tỷ lệ nợ dài hạn trên vốn chủ sở hữu (Long debt to equity: 0.017 – 0.026) → Rất thấp, cho thấy doanh nghiệp hạn chế sử dụng nợ dài hạn. → Phản ánh chiến lược tài chính thận trọng, giảm rủi ro gánh nặng lãi vay dài hạn.

Tổng thể: → Vinamilk có cấu trúc vốn lành mạnh, rủi ro tài chính thấp, và khả năng tự tài trợ vốn cao. → Đây là đặc trưng của doanh nghiệp ổn định, ít phụ thuộc nợ, hướng đến phát triển bền vững.

8. Mã hóa cấu trúc tài sản

1. library(dplyr)
2. vnm20 <- vnm20 %>%
3. mutate(
4. inventory_share = `hang_ton_kho` / `tai_san_ngan_han`,
5. ppe_to_assets   = `tai_san_co_dinh_huu_hinh` / `tong_cong_tai_san`,
6. re_to_equity    = `loi_nhuan_sau_thue_chua_phan_phoi` / `von_chu_so_huu`)
7. head(vnm20[, c("inventory_share", "ppe_to_assets", "re_to_equity")])

Giải thích
Kỹ thuật
- Dòng 4: Tạo biến thể hiện tỷ trọng hàng tồn kho trong tổng tài sản ngắn hạn. → Cho biết mức vốn lưu động đang bị “giữ” trong hàng tồn kho.
- Dòng 5: Xác định tỷ lệ tài sản cố định hữu hình so với tổng tài sản. → Phản ánh mức đầu tư vào cơ sở vật chất, nhà máy, máy móc thiết bị.
- Dòng 6: Đo lường tỷ lệ lợi nhuận giữ lại trong vốn chủ sở hữu. → Giúp đánh giá chính sách tái đầu tư nội bộ của doanh nghiệp.
- Dòng 7: Hiển thị 6 dòng đầu tiên để kiểm tra kết quả mã hóa.
Ý nghĩa:
- Tỷ trọng hàng tồn kho (0.16–0.27) → Cho thấy doanh nghiệp duy trì mức dự trữ hợp lý, hỗ trợ ổn định sản xuất và cung ứng. → Mức này phản ánh quản lý vốn lưu động hiệu quả, tránh ứ đọng hàng hóa.
- Tỷ trọng tài sản cố định hữu hình (0.26–0.35) → Thể hiện đầu tư mạnh vào tài sản sản xuất, đảm bảo năng lực hoạt động dài hạn. → Tỷ lệ ổn định qua các năm cho thấy chiến lược duy trì cơ sở vật chất ổn định và hiện đại hóa liên tục. - Tỷ lệ lợi nhuận giữ lại trên vốn chủ (0.20–0.27) → Phản ánh khả năng tự tích lũy vốn cao, Vinamilk chủ động tái đầu tư từ lợi nhuận. → Đây là tín hiệu tốt về sức khỏe tài chính và tính bền vững trong tăng trưởng.

9. Mã hóa dòng tiền (cường độ tạo và sử dụng tiền)

1. vnm20 <- vnm20 %>%
2. mutate(
3. cfo_to_assets = `luu_chuyen_tien_thuan_tu_hoat_dong_kinh_doanh` / `tong_cong_tai_san`,
4. cfo_to_liab   = `luu_chuyen_tien_thuan_tu_hoat_dong_kinh_doanh` / `no_phai_tra`,
5. cfi_intensity = `luu_chuyen_tien_thuan_tu_hoat_dong_dau_tu` / `tong_cong_tai_san`,
6. cff_intensity = `luu_chuyen_tien_thuan_tu_hoat_dong_tai_chinh` / `tong_cong_tai_san`)
7. head(vnm20[, c("cfo_to_assets", "cfo_to_liab", "cfi_intensity", "cff_intensity")])

Giải thích
Kỹ thuật:
- Dòng 3: Đo hiệu suất tạo tiền từ hoạt động chính so với quy mô tài sản của doanh nghiệp.
- Dòng 5: Cho biết khả năng tạo tiền để thanh toán các khoản nợ, phản ánh mức độ an toàn tài chính.
- Dòng 6: Phản ánh mức độ sử dụng tiền cho đầu tư dài hạn, giá trị âm là chi tiền đầu tư (mở rộng tài sản).
- Dòng 8: Thể hiện cường độ huy động hoặc chi trả vốn tài chính, giá trị âm thường do doanh nghiệp trả nợ hoặc chi cổ tức.
- Dòng 10: Hiển thị 6 dòng đầu tiên để kiểm tra kết quả mã hóa.
Ý nghĩa:
- CFO/Tổng tài sản (0.21 – 0.28) → Mức khá cao, cho thấy Vinamilk tạo ra dòng tiền ổn định từ hoạt động kinh doanh, tương ứng khoảng 21–28% giá trị tài sản mỗi năm. → Đây là dấu hiệu của hiệu quả hoạt động mạnh và chất lượng lợi nhuận cao.
- CFO/Nợ phải trả (0.68 – 1.20) → Các giá trị > 1 cho thấy dòng tiền hoạt động đủ khả năng bao phủ toàn bộ nợ phải trả, tức là doanh nghiệp không phụ thuộc vào dòng tiền vay mượn để duy trì hoạt động. → Chỉ tiêu này phản ánh mức độ an toàn tài chính rất cao.
- CFI/Tổng tài sản (-0.03 đến -0.15) → Giá trị âm hợp lý vì đây là chi đầu tư tài sản cố định, mở rộng sản xuất. → Mức âm vừa phải chứng tỏ doanh nghiệp đầu tư có kiểm soát, không gây áp lực dòng tiền.
- CFF/Tổng tài sản (-0.06 đến -0.24) → Âm do chi trả cổ tức, trả nợ vay, phù hợp với doanh nghiệp có dòng tiền hoạt động mạnh và ít phụ thuộc nguồn tài trợ bên ngoài. → Cho thấy Vinamilk đang ở giai đoạn ổn định, tập trung vào duy trì và phân phối lợi nhuận hơn là mở rộng vốn vay.
- Tổng thể: → Vinamilk có khả năng tạo tiền mạnh, đầu tư thận trọng và chính sách tài chính ổn định. → Cấu trúc dòng tiền lành mạnh: CFO dương lớn, CFI âm hợp lý, CFF âm nhẹ — mô hình dòng tiền “ổn định – an toàn – tự tài trợ” đặc trưng của doanh nghiệp trưởng thành và bền vững.

10. Mã hóa khả năng sinh lời

1. vnm20 <- vnm20 %>%
2.   mutate(
3.     roa  = `loi_nhuan_sau_thue_tndn` / `tong_cong_tai_san`,
4.     roe  = `loi_nhuan_sau_thue_tndn` / `von_chu_so_huu`,
5.     ros  = `loi_nhuan_sau_thue_tndn` / `doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02`,
6.     asset_turnover = `doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02` / `tong_cong_tai_san`,
7.     leverage = `tong_cong_tai_san` / `von_chu_so_huu`,
8.     dupont = ros * asset_turnover * leverage  )
9. head(vnm20[, c("roa", "roe", "ros", "asset_turnover", "leverage", "dupont")])

Giải thích
Kỹ thuật:
- Dòng 3: Đo lường hiệu quả sử dụng tài sản để tạo ra lợi nhuận.
- Dòng 4: Phản ánh tỷ suất lợi nhuận của cổ đông, hay mức sinh lời trên mỗi đồng vốn tự có.
- Dòng 5: Cho biết biên lợi nhuận ròng, tức là doanh nghiệp giữ lại được bao nhiêu lợi nhuận từ 1 đồng doanh thu.
- Dòng 6: Đo mức độ hiệu quả sử dụng tài sản để tạo doanh thu.
- Dòng 9: Cho biết mức độ đòn bẩy tài chính – doanh nghiệp dùng bao nhiêu tài sản trên mỗi đồng vốn chủ.
- Dòng 10: Là mô hình DuPont 3 bước, giải thích ROE đến từ đâu:
Hiệu quả hoạt động (ROS)
Hiệu quả sử dụng tài sản (Asset turnover)
Mức độ sử dụng đòn bẩy tài chính (Leverage)
Ý nghĩa:
- ROA (0.23 – 0.32) → Hiệu suất sinh lời trên tổng tài sản đạt 23–32%, mức rất cao so với chuẩn trung bình của ngành thực phẩm (thường 10–15%). → Thể hiện hiệu quả sử dụng tài sản vượt trội trong tạo lợi nhuận.
- ROE (0.33 – 0.43) → Tỷ suất sinh lời trên vốn chủ sở hữu đạt 33–43%, chứng tỏ khả năng tạo giá trị cao cho cổ đông. → Mức này ổn định qua các năm, phản ánh tài chính vững mạnh và quản trị hiệu quả.
- ROS (0.18 – 0.20) → Biên lợi nhuận ròng ở mức 18–20%, tức là Vinamilk giữ lại được gần 1/5 doanh thu dưới dạng lợi nhuận. → Đây là dấu hiệu của hiệu quả hoạt động kinh doanh tốt, đặc biệt trong ngành có biên lợi nhuận thấp.
- Asset Turnover (1.23 – 1.59) → Mỗi đồng tài sản tạo ra khoảng 1.2–1.6 đồng doanh thu mỗi năm. → Mức vòng quay này cho thấy tài sản được khai thác hiệu quả và tối ưu hóa trong vận hành.
- Leverage (1.31 – 1.50) → Đòn bẩy tài chính thấp – chỉ dùng thêm 0.3–0.5 lần nợ so với vốn chủ. → Điều này phản ánh mức độ an toàn tài chính cao, ít phụ thuộc vào nợ vay.
- DuPont (0.33 – 0.43) → Kết quả trùng khớp với ROE, xác nhận mô hình DuPont tính đúng. → Phân tích cho thấy ROE cao của Vinamilk đến từ biên lợi nhuận ổn định và hiệu quả sử dụng tài sản tốt, không phải do dùng đòn bẩy nợ.

CHƯƠNG 3: THỐNG KÊ CƠ BẢN

1. Thống kê quy mô và phạm vi dữ liệu

1. vnm20 %>%
2.   summarise(
3.     so_quan_sat = n(),
4.     nam_dau = min(nam, na.rm = TRUE),
5.     nam_cuoi = max(nam, na.rm = TRUE)
6.   )

Giải thích
Kỹ thuật:
- Dòng 3: đếm tổng số dòng dữ liệu (tức là số năm có quan sát).
- Dòng 4-5: lấy năm nhỏ nhất và lớn nhất trong dữ liệu, loại bỏ giá trị thiếu (na.rm = TRUE).
Ý nghĩa:
Bộ dữ liệu có 10 quan sát, tương ứng với 10 năm tài chính liên tục, từ 2015 đến 2024.

2. Tính giá trị trung bình (Mean) cho các biến tài chính

1. library(tidyr)
2. mean_long <- vnm20 %>%
3.   summarise(across(where(is.numeric) & !matches("^(Năm|Nam)$"),
4.                    ~ mean(.x, na.rm = TRUE))) %>%
5.   pivot_longer(everything(),
6.                names_to = "Chỉ_tiêu",
7.                values_to = "Trung_bình")
8. print(mean_long, n = Inf)
## # A tibble: 40 × 2
##    Chỉ_tiêu                                                 Trung_bình
##    <chr>                                                         <dbl>
##  1 tong_cong_tai_san                                        43156.    
##  2 tai_san_ngan_han                                         27182.    
##  3 tien_va_cac_khoan_tuong_duong_tien                        1906.    
##  4 cac_khoan_dau_tu_tai_chinh_ngan_han                      14994.    
##  5 cac_khoan_phai_thu_ngan_han                               4916.    
##  6 hang_ton_kho                                              5189.    
##  7 tai_san_do_dang_dai_han                                   1205.    
##  8 chi_phi_tra_truoc_dai_han                                  679.    
##  9 tai_san_co_dinh_huu_hinh                                 11120.    
## 10 tong_nguon_von                                           43156.    
## 11 doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02 54946.    
## 12 no_phai_tra                                              13484.    
## 13 no_ngan_han                                              12993.    
## 14 vay_ngan_han                                              4839.    
## 15 no_dai_han                                                 491.    
## 16 von_chu_so_huu                                           29672.    
## 17 loi_nhuan_sau_thue_chua_phan_phoi                         5700.    
## 18 loi_nhuan_sau_thue_tndn                                   9709.    
## 19 luu_chuyen_tien_thuan_tu_hoat_dong_kinh_doanh             9121.    
## 20 luu_chuyen_tien_thuan_tu_hoat_dong_dau_tu                -1891.    
## 21 luu_chuyen_tien_thuan_tu_hoat_dong_tai_chinh             -6097.    
## 22 current_ratio                                                2.17  
## 23 cash_ratio                                                   0.148 
## 24 debt_ratio                                                   0.305 
## 25 equity_ratio                                                 0.695 
## 26 short_debt_ratio                                             0.330 
## 27 long_debt_to_equity                                          0.0175
## 28 inventory_share                                              0.199 
## 29 ppe_to_assets                                                0.264 
## 30 re_to_equity                                                 0.201 
## 31 cfo_to_assets                                                0.221 
## 32 cfo_to_liab                                                  0.751 
## 33 cfi_intensity                                               -0.0475
## 34 cff_intensity                                               -0.146 
## 35 roa                                                          0.236 
## 36 roe                                                          0.337 
## 37 ros                                                          0.179 
## 38 asset_turnover                                               1.31  
## 39 leverage                                                     1.44  
## 40 dupont                                                       0.337

Giải thích
Kỹ thuật:
- Dòng 2: Tính trung bình (mean) cho tất cả các cột dạng số (numeric) trong bảng vnm20, loại bỏ cột năm (!matches("Năm\|Nam")) và bỏ qua giá trị thiếu (na.rm = TRUE).
- Dòng 4: Chuyển dữ liệu từ dạng ngang sang dọc, mỗi dòng thể hiện một tên biến (Chỉ_tiêu) và giá trị trung bình tương ứng (Trung_bình).
- Dòng 5: In toàn bộ kết quả, không bị cắt bớt, giúp xem hết các chỉ tiêu.
Ý nghĩa:
- Tổng tài sản bình quân: khoảng 43.156 tỷ đồng, trong đó tài sản ngắn hạn chiếm hơn 60%, thể hiện mức thanh khoản cao.
- Vốn chủ sở hữu trung bình đạt gần 29.672 tỷ đồng, trong khi nợ phải trả khoảng 13.484 tỷ đồng, cho thấy cấu trúc vốn an toàn (nợ ~30%).
- Doanh thu thuần bình quân đạt 54.946 tỷ đồng, cao hơn tổng tài sản, phản ánh hiệu quả khai thác tài sản tốt (vòng quay > 1).
- Lợi nhuận sau thuế TNDN trung bình gần 9.709 tỷ đồng, tương ứng ROA ~23% và ROE ~34%, mức sinh lời rất cao trong ngành.
- Dòng tiền từ hoạt động kinh doanh (CFO) trung bình dương mạnh (≈9.121 tỷ), trong khi dòng tiền đầu tư và tài chính âm hợp lý, chứng tỏ Vinamilk tự tài trợ cho đầu tư và trả cổ tức.
- Các chỉ tiêu như current_ratio ~2.17 và cash_ratio ~0.15 xác nhận thanh khoản ổn định, không dư thừa vốn lưu động.

3. Tính độ lệch chuẩn (Standard Deviation) cho các chỉ tiêu tài chính

1. sd_long <- vnm20 %>%
2.   summarise(across(where(is.numeric) & !matches("^(Năm|Nam)$"),
3.                    ~ sd(.x, na.rm = TRUE))) %>%
4.   pivot_longer(everything(), names_to = "Chi_tieu", values_to = "Do_lech_chuan")
5. # Hiển thị kết quả theo dạng ma trận 2 hàng, 4 cột (in theo hàng)
6. mat <- matrix(
7.   paste(sd_long$Chi_tieu, round(sd_long$Do_lech_chuan, 2), sep = " : "),
8.   ncol = 4, byrow = TRUE)
9. print(mat, quote = FALSE)
##       [,1]                                                  
##  [1,] tong_cong_tai_san : 10194.62                          
##  [2,] cac_khoan_phai_thu_ngan_han : 1340.29                 
##  [3,] tai_san_co_dinh_huu_hinh : 1998.66                    
##  [4,] no_ngan_han : 4441.58                                 
##  [5,] loi_nhuan_sau_thue_chua_phan_phoi : 1687.63           
##  [6,] luu_chuyen_tien_thuan_tu_hoat_dong_tai_chinh : 2834.33
##  [7,] equity_ratio : 0.04                                   
##  [8,] ppe_to_assets : 0.05                                  
##  [9,] cfi_intensity : 0.06                                  
## [10,] ros : 0.02                                            
##       [,2]                             
##  [1,] tai_san_ngan_han : 7944.32       
##  [2,] hang_ton_kho : 925.42            
##  [3,] tong_nguon_von : 10194.62        
##  [4,] vay_ngan_han : 3582.8            
##  [5,] loi_nhuan_sau_thue_tndn : 1063.06
##  [6,] current_ratio : 0.37             
##  [7,] short_debt_ratio : 0.18          
##  [8,] re_to_equity : 0.07              
##  [9,] cff_intensity : 0.07             
## [10,] asset_turnover : 0.16            
##       [,3]                                                              
##  [1,] tien_va_cac_khoan_tuong_duong_tien : 744.1                        
##  [2,] tai_san_do_dang_dai_han : 401.47                                  
##  [3,] doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02 : 7220.17
##  [4,] no_dai_han : 77.9                                                 
##  [5,] luu_chuyen_tien_thuan_tu_hoat_dong_kinh_doanh : 1166.64           
##  [6,] cash_ratio : 0.04                                                 
##  [7,] long_debt_to_equity : 0.01                                        
##  [8,] cfo_to_assets : 0.05                                              
##  [9,] roa : 0.06                                                        
## [10,] leverage : 0.08                                                   
##       [,4]                                               
##  [1,] cac_khoan_dau_tu_tai_chinh_ngan_han : 5468.71      
##  [2,] chi_phi_tra_truoc_dai_han : 144.6                  
##  [3,] no_phai_tra : 4402.05                              
##  [4,] von_chu_so_huu : 5862.52                           
##  [5,] luu_chuyen_tien_thuan_tu_hoat_dong_dau_tu : 2846.87
##  [6,] debt_ratio : 0.04                                  
##  [7,] inventory_share : 0.04                             
##  [8,] cfo_to_liab : 0.26                                 
##  [9,] roe : 0.07                                         
## [10,] dupont : 0.07

Giải thích
Kỹ thuật:
- Dòng 3: sd() tính độ lệch chuẩn – đo mức phân tán hoặc biến động của dữ liệu quanh giá trị trung bình.
na.rm = TRUE bỏ qua giá trị thiếu khi tính.
- Dòng 4: pivot_longer() giúp hiển thị mỗi chỉ tiêu tài chính cùng với độ lệch chuẩn của nó.
Ý nghĩa:
- Tổng tài sản và vốn chủ sở hữu có độ lệch chuẩn khá lớn (≈ 10.000 tỷ và 5.800 tỷ) → cho thấy quy mô Vinamilk tăng trưởng đáng kể qua 10 năm.
- Doanh thu và lợi nhuận dao động vừa phải (7.200 tỷ và 1.000 tỷ), phản ánh mức tăng trưởng ổn định, không biến động đột ngột.
- Nợ dài hạn có độ lệch chuẩn rất thấp (~78 tỷ) → doanh nghiệp ít sử dụng nợ dài hạn, chính sách vay ổn định.
- Các chỉ tiêu tỷ suất như ROA (0.055), ROE (0.066) hay ROS (0.022) có biến động nhỏ → chứng tỏ hiệu quả sinh lời duy trì ổn định theo thời gian.
- Dòng tiền đầu tư và tài chính có độ lệch chuẩn cao (~2.8 nghìn tỷ) → phản ánh chu kỳ chi tiêu đầu tư và trả cổ tức thay đổi theo từng năm.

4. Thống kê phân vị cho các chỉ tiêu tài chính chính yếu

1. summary(vnm20[, c("tong_cong_tai_san", 
2.                   "von_chu_so_huu", 
3.                   "doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02", 
4.                   "loi_nhuan_sau_thue_tndn", 
5.                   "roa", "roe")])
##  tong_cong_tai_san von_chu_so_huu 
##  Min.   :27478     Min.   :20924  
##  1st Qu.:35342     1st Qu.:24473  
##  Median :46566     Median :31274  
##  Mean   :43156     Mean   :29672  
##  3rd Qu.:51626     3rd Qu.:34681  
##  Max.   :55049     Max.   :36174  
##  doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02
##  Min.   :40080                                           
##  1st Qu.:51421                                           
##  Median :57977                                           
##  Mean   :54946                                           
##  3rd Qu.:60266                                           
##  Max.   :61783                                           
##  loi_nhuan_sau_thue_tndn      roa              roe        
##  Min.   : 7770           Min.   :0.1712   Min.   :0.2575  
##  1st Qu.: 9105           1st Qu.:0.1825   1st Qu.:0.2702  
##  Median : 9829           Median :0.2341   Median :0.3445  
##  Mean   : 9709           Mean   :0.2358   Mean   :0.3374  
##  3rd Qu.:10485           3rd Qu.:0.2803   3rd Qu.:0.3842  
##  Max.   :11236           Max.   :0.3187   Max.   :0.4305

Giải thích
Kỹ thuật:
- Hàm summary() hiển thị 6 thống kê cơ bản: Min, 1st Qu., Median, Mean, 3rd Qu., Max cho từng biến.
- Các biến chọn gồm: tổng tài sản, vốn chủ sở hữu, doanh thu thuần, lợi nhuận sau thuế, ROA, ROE — đại diện cho quy mô, hiệu quả và khả năng sinh lời.
Ý nghĩa:
- Kết quả thống kê phân vị cho thấy các chỉ tiêu tài chính chủ yếu của Vinamilk trong giai đoạn 2015–2024 có mức dao động hẹp và phân phối cân đối.
Tổng tài sản và vốn chủ sở hữu tăng đều, thể hiện quy mô doanh nghiệp mở rộng ổn định.
- Doanh thu thuần dao động quanh 40–62 nghìn tỷ đồng, trung vị cao hơn trung bình, cho thấy xu hướng tăng trưởng liên tục.
- Lợi nhuận sau thuế ổn định ở mức 8–11 nghìn tỷ đồng, phản ánh hiệu quả hoạt động bền vững.
- Các tỷ suất sinh lời ROA (≈23%) và ROE (≈34%) duy trì ở mức cao, ổn định qua các năm, khẳng định khả năng sử dụng tài sản và vốn chủ hiệu quả, cùng nền tảng tài chính vững mạnh của doanh nghiệp.

5. Tính hệ số biến thiên

1. library(dplyr)
2. # Chọn các biến tiêu biểu cần xem
3. vars_focus <- c("tong_cong_tai_san", 
4.                 "von_chu_so_huu",
5.                 "doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02",
6.                 "loi_nhuan_sau_thue_tndn",
7.                 "roa", "roe")
8. cv_long <- vnm20 %>%
9.   summarise(across(all_of(vars_focus),
10.                    ~ sd(.x, na.rm = TRUE) / mean(.x, na.rm = TRUE))) %>%
11.   tidyr::pivot_longer(everything(),
12.                       names_to = "Chi_tieu",
13.                       values_to = "He_so_bien_thien")
14. print(cv_long, n = Inf)
## # A tibble: 6 × 2
##   Chi_tieu                                                 He_so_bien_thien
##   <chr>                                                               <dbl>
## 1 tong_cong_tai_san                                                   0.236
## 2 von_chu_so_huu                                                      0.198
## 3 doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02            0.131
## 4 loi_nhuan_sau_thue_tndn                                             0.109
## 5 roa                                                                 0.233
## 6 roe                                                                 0.195

Giải thích
Kỹ thuật:
- Hệ số biến thiên (CV = SD / Mean) đo lường mức biến động tương đối của các chỉ tiêu chính.
- Sáu biến được chọn đại diện cho ba nhóm:
Quy mô tài sản & vốn (tong_cong_tai_san, von_chu_so_huu).
Hiệu quả hoạt động (doanh_thu_thuan_…, loi_nhuan_sau_thue_tndn).
Khả năng sinh lời (roa, roe).
- CV nhỏ → biến ổn định; CV lớn → biến động mạnh theo thời gian.
Ý nghĩa:
- Kết quả cho thấy CV của các biến đều thấp hơn 0.3, chứng tỏ dữ liệu ổn định và ít biến động.
- ROA, ROE có CV thấp nhất → hiệu quả sinh lời của Vinamilk ổn định, ít rủi ro.
- Doanh thu và lợi nhuận có CV vừa phải → phản ánh tăng trưởng đều qua các năm.
- Tổng thể, hệ số biến thiên khẳng định Vinamilk duy trì sự ổn định cao trong hoạt động tài chính và hiệu quả kinh doanh giai đoạn 2015–2024.

6. Tính tốc độ tăng trưởng năm (YoY) cho các chỉ tiêu chính

1. vars_focus <- c("tong_cong_tai_san",
2.                 "von_chu_so_huu",
3.                 "doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02",
4.                 "loi_nhuan_sau_thue_tndn",
5.                 "roa","roe")
6. yoy <- vnm20 %>%
7.   arrange(nam) %>%
8.   mutate(across(all_of(vars_focus),
9.                 ~ (.x / dplyr::lag(.x) - 1),
10.                 .names = "{.col}_yoy")) %>%
11.   select(nam, ends_with("_yoy"))
12. print(yoy, n = Inf)
## # A tibble: 10 × 7
##    nam                 tong_cong_tai_san_yoy von_chu_so_huu_yoy
##    <dttm>                              <dbl>              <dbl>
##  1 2015-12-31 00:00:00               NA                 NA     
##  2 2016-12-31 00:00:00                0.0692             0.0708
##  3 2017-12-31 00:00:00                0.180              0.0655
##  4 2018-12-31 00:00:00                0.0778             0.100 
##  5 2019-12-31 00:00:00                0.196              0.132 
##  6 2020-12-31 00:00:00                0.0835             0.132 
##  7 2021-12-31 00:00:00                0.101              0.0655
##  8 2022-12-31 00:00:00               -0.0909            -0.0846
##  9 2023-12-31 00:00:00                0.0864             0.0673
## 10 2024-12-31 00:00:00                0.0451             0.0328
## # ℹ 4 more variables:
## #   doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02_yoy <dbl>,
## #   loi_nhuan_sau_thue_tndn_yoy <dbl>, roa_yoy <dbl>, roe_yoy <dbl>

Giải thích
Kỹ thuật:
- Dòng 6-12: Tốc độ tăng trưởng YoY = (Giá_trị_t - Giá_trị_t-1) / Giá_trị_t-1 * 100
lag() lấy giá trị năm trước để tính phần trăm thay đổi qua thời gian.
Dòng đầu tiên (NA) tương ứng với năm đầu tiên (không có dữ liệu so sánh).
Ý nghĩa:
- Tổng tài sản và vốn chủ sở hữu tăng đều hằng năm (≈7–13%) → phản ánh quy mô mở rộng ổn định.
- Doanh thu thuần duy trì mức tăng trưởng 2–17%/năm, cho thấy tăng trưởng bền vững, ít biến động. - Lợi nhuận sau thuế tăng nhanh giai đoạn 2015–2017 (≈20%), chậm lại sau 2018 và giảm nhẹ 2022 → ảnh hưởng chu kỳ thị trường.
- ROA và ROE dao động nhẹ quanh –10% đến +12% → phản ánh hiệu suất sinh lời có biến động nhưng vẫn ổn định trong dài hạn. - Tổng thể, tốc độ tăng trưởng của các chỉ tiêu cho thấy Vinamilk duy trì quỹ đạo tăng trưởng tích cực, quy mô tài chính mở rộng và khả năng sinh lời ổn định trong gần một thập kỷ.

7. Tính tốc độ tăng trưởng trung bình

1. vars_focus <- c("tong_cong_tai_san",
2.                 "von_chu_so_huu",
3.                 "doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02",
4.                 "loi_nhuan_sau_thue_tndn")
5. cagr_long <- vnm20 %>%
6.   summarise(across(all_of(vars_focus),
7.                    ~ (last(.x) / first(.x))^(1 / (n() - 1)) - 1)) %>%
8.   tidyr::pivot_longer(everything(),
9.                       names_to = "Chi_tieu",
10.                       values_to = "CAGR")
11. print(cagr_long, n = Inf)
## # A tibble: 4 × 2
##   Chi_tieu                                                   CAGR
##   <chr>                                                     <dbl>
## 1 tong_cong_tai_san                                        0.0803
## 2 von_chu_so_huu                                           0.0627
## 3 doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02 0.0493
## 4 loi_nhuan_sau_thue_tndn                                  0.0220

Giải thích
Kỹ thuật:
- Công thức tính tốc độ tăng trưởng trung bình năm (CAGR):
CAGR = (Giá_trị_cuối / Giá_trị_đầu)^(1 / (n - 1)) - 1
- Trong R, công thức được biểu diễn qua last(.x) và first(.x) để lấy giá trị đầu và cuối của chuỗi dữ liệu.
- Dòng 7: n() đếm tổng số quan sát, 1/(n()-1) chính là số năm trung bình.
- Dòng 6-10: summarise(across(…)) giúp áp dụng công thức cho nhiều biến cùng lúc, còn pivot_longer() đưa kết quả về dạng “dài” (tidy data) gồm hai cột: Chi_tieu và CAGR.
Ý nghĩa:
- Tổng tài sản (8.0%/năm) và vốn chủ sở hữu (6.3%/năm) tăng đều qua thời gian, phản ánh quy mô doanh nghiệp mở rộng ổn định.
- Doanh thu thuần (4.9%/năm) vẫn tăng trưởng nhưng chậm hơn tài sản → cho thấy hiệu suất khai thác tài sản đang giảm nhẹ theo chu kỳ bão hòa.
- Lợi nhuận sau thuế (2.2%/năm) có tốc độ tăng thấp nhất, gợi ý biên lợi nhuận thu hẹp do chi phí và cạnh tranh gia tăng.
- Nhìn chung, các chỉ tiêu đều duy trì CAGR dương, chứng tỏ Vinamilk tăng trưởng ổn định, quy mô tài chính bền vững, song cần chú ý cải thiện tốc độ sinh lời để duy trì lợi thế dài hạn.

8. Thống kê tương quan giữa các chỉ tiêu sinh lời

1. # Chọn các biến đại diện cho khả năng sinh lời
2. vars_profit <- c("roa", "roe", "ros", "asset_turnover")
3. # Tính ma trận tương quan Pearson
4. cor_profit <- cor(select(vnm20, all_of(vars_profit)), use = "complete.obs")
5. print(cor_profit)
##                      roa       roe       ros asset_turnover
## roa            1.0000000 0.9787901 0.9293363      0.9510533
## roe            0.9787901 1.0000000 0.9491142      0.8978388
## ros            0.9293363 0.9491142 1.0000000      0.7712612
## asset_turnover 0.9510533 0.8978388 0.7712612      1.0000000

Giải thích
Kỹ thuật:
- Dòng 4: cor() tính hệ số tương quan Pearson giữa các cặp biến.
use = "complete.obs" bỏ qua các hàng có giá trị thiếu (NA).
- Kết quả là ma trận tương quan, giá trị nằm trong khoảng từ –1 đến +1: Gần +1 → quan hệ cùng chiều mạnh.
Gần –1 → quan hệ ngược chiều mạnh.
Gần 0 → ít hoặc không tương quan.
Ý nghĩa: - Các chỉ tiêu sinh lời của Vinamilk có mối tương quan rất chặt chẽ (r = 0.77–0.98), cho thấy hiệu quả tài chính nhất quán và ổn định.
- ROA, ROE và ROS biến động cùng chiều, phản ánh khả năng sinh lợi cao và đồng bộ giữa biên lợi nhuận, hiệu quả sử dụng tài sản và vốn chủ sở hữu.
- Mức tương quan mạnh này khẳng định cấu trúc sinh lời của doanh nghiệp bền vững, quản trị tài chính hiệu quả và duy trì hiệu suất ổn định qua các năm.

9. Kiểm tra phân phối chuẩn

1. library(dplyr)
2. vars_focus <- c("tong_cong_tai_san",
3.                 "doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02",
4.                 "loi_nhuan_sau_thue_tndn",
5.                 "roa", "roe")
6. # Kiểm định Shapiro-Wilk cho từng biến
7. normality <- vars_focus %>%
8.   setNames(vars_focus) %>%
9.   lapply(function(var) shapiro.test(vnm20[[var]])) %>%
10.   sapply(function(x) c(W = x$statistic, p_value = x$p.value)) %>%
11.   t() %>%
12.   as.data.frame()
13. print(normality)
##                                                                W.W    p_value
## tong_cong_tai_san                                        0.9035840 0.23975928
## doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02 0.8643530 0.08585985
## loi_nhuan_sau_thue_tndn                                  0.9669759 0.86147891
## roa                                                      0.9114342 0.29098864
## roe                                                      0.9101301 0.28188605

Giải thích
Kỹ thuật
- Dòng 3-7: Tạo danh sách các biến tài chính cần kiểm tra tính chuẩn (normality) bằng kiểm định Shapiro-Wilk: vars_focus <- c(...).
- Dòng 9-14: setNames(vars_focus): Đặt tên cho các biến theo vars_focus.
lapply(...): Áp dụng Shapiro-Wilk cho mỗi biến trong danh sách vars_focus.
sapply(...): Trích xuất giá trị thống kê W và p-value từ kết quả kiểm định.
t(): Chuyển đổi ma trận thành dạng cột.
as.data.frame(): Chuyển đổi kết quả thành data frame để dễ đọc.
- Dòng 15: print(normality) → In ra bảng kết quả kiểm định W và p-value của các biến.
Ý nghĩa:
- Tổng tài sản (p = 0.24) và doanh thu thuần (p = 0.086) có p > 0.05 → phân phối gần chuẩn, cho thấy quy mô tài sản và doanh thu của Vinamilk tăng đều, ổn định theo thời gian.
- Lợi nhuận sau thuế (p = 0.86) hoàn toàn tuân theo phân phối chuẩn → hiệu quả kinh doanh ổn định, ít biến động cực đoan.
- ROA (p = 0.29) và ROE (p = 0.28) cũng đạt phân phối gần chuẩn → phản ánh mức sinh lời ổn định và bền vững.
- Tổng thể, các chỉ tiêu tài chính của Vinamilk không có sự lệch đáng kể, dữ liệu ổn định và đáng tin cậy — phù hợp để tiếp tục phân tích hồi quy hoặc mô hình dự báo trong các chương sau.

10. Thống kê tương quan giữa dòng tiền và khả năng sinh lời

1. library(dplyr)
2. vars_cash_profit <- c("luu_chuyen_tien_thuan_tu_hoat_dong_kinh_doanh",
3.                       "luu_chuyen_tien_thuan_tu_hoat_dong_dau_tu",
4.                       "luu_chuyen_tien_thuan_tu_hoat_dong_tai_chinh",
5.                       "loi_nhuan_sau_thue_tndn",
6.                       "roa",
7.                       "roe")
8. cor_cash_profit <- cor(select(vnm20, all_of(vars_cash_profit)), use = "complete.obs")
9. print(cor_cash_profit)
##                                               luu_chuyen_tien_thuan_tu_hoat_dong_kinh_doanh
## luu_chuyen_tien_thuan_tu_hoat_dong_kinh_doanh                                   1.000000000
## luu_chuyen_tien_thuan_tu_hoat_dong_dau_tu                                      -0.604409983
## luu_chuyen_tien_thuan_tu_hoat_dong_tai_chinh                                   -0.005932113
## loi_nhuan_sau_thue_tndn                                                         0.694467793
## roa                                                                            -0.156886854
## roe                                                                            -0.017393076
##                                               luu_chuyen_tien_thuan_tu_hoat_dong_dau_tu
## luu_chuyen_tien_thuan_tu_hoat_dong_kinh_doanh                                -0.6044100
## luu_chuyen_tien_thuan_tu_hoat_dong_dau_tu                                     1.0000000
## luu_chuyen_tien_thuan_tu_hoat_dong_tai_chinh                                 -0.6534454
## loi_nhuan_sau_thue_tndn                                                      -0.6363893
## roa                                                                          -0.3208969
## roe                                                                          -0.3881551
##                                               luu_chuyen_tien_thuan_tu_hoat_dong_tai_chinh
## luu_chuyen_tien_thuan_tu_hoat_dong_kinh_doanh                                 -0.005932113
## luu_chuyen_tien_thuan_tu_hoat_dong_dau_tu                                     -0.653445440
## luu_chuyen_tien_thuan_tu_hoat_dong_tai_chinh                                   1.000000000
## loi_nhuan_sau_thue_tndn                                                        0.004406250
## roa                                                                            0.192383349
## roe                                                                            0.173359483
##                                               loi_nhuan_sau_thue_tndn
## luu_chuyen_tien_thuan_tu_hoat_dong_kinh_doanh              0.69446779
## luu_chuyen_tien_thuan_tu_hoat_dong_dau_tu                 -0.63638933
## luu_chuyen_tien_thuan_tu_hoat_dong_tai_chinh               0.00440625
## loi_nhuan_sau_thue_tndn                                    1.00000000
## roa                                                        0.04130204
## roe                                                        0.18652388
##                                                       roa         roe
## luu_chuyen_tien_thuan_tu_hoat_dong_kinh_doanh -0.15688685 -0.01739308
## luu_chuyen_tien_thuan_tu_hoat_dong_dau_tu     -0.32089689 -0.38815511
## luu_chuyen_tien_thuan_tu_hoat_dong_tai_chinh   0.19238335  0.17335948
## loi_nhuan_sau_thue_tndn                        0.04130204  0.18652388
## roa                                            1.00000000  0.97879005
## roe                                            0.97879005  1.00000000

Giải thích
Kỹ thuật:
- Dòng 9-12: cor(select(vnm20, all_of(vars_cash_profit)), use = "complete.obs"): Tính toán hệ số tương quan Pearson giữa các biến trong vars_cash_profit từ dữ liệu vnm20.
Hàm select() giúp chọn các cột liên quan từ bảng dữ liệu, vàuse = "complete.obs" chỉ dùng các quan sát đầy đủ (không có giá trị thiếu). print(cor_cash_profit): In kết quả hệ số tương quan ra màn hình.

Ý nghĩa:
- Lưu chuyển tiền thuần từ hoạt động kinh doanh (CFO) có tương quan dương rất mạnh với lợi nhuận sau thuế (r = 0.69) và cũng dương với ROA, ROE (r ≈ 0.19) → dòng tiền từ hoạt động chính gắn chặt với khả năng sinh lời, chứng tỏ chất lượng lợi nhuận cao.
- Lưu chuyển tiền thuần từ hoạt động đầu tư (CFI) tương quan âm mạnh với CFO (r = –0.60) và âm với lợi nhuận (r = –0.16) → khi Vinamilk tăng đầu tư, dòng tiền giảm tạm thời, phản ánh chi đầu tư tài sản cố định định kỳ.
- Lưu chuyển tiền thuần từ hoạt động tài chính (CFF) tương quan âm nhẹ với ROE và lợi nhuận (r ≈ –0.06 đến –0.17) → do chi trả cổ tức, giảm nợ khi hiệu quả cao.

11. Thống kê tương quan giữa cơ cấu tài chính và khả năng sinh lời

1. library(dplyr)
2. vars_structure_profit <- c("debt_ratio", "equity_ratio", "long_debt_to_equity",          "current_ratio", "roa", "roe")       
3. cor_structure_profit <- cor(select(vnm20, all_of(vars_structure_profit)), use = "complete.obs") 
4. print(cor_structure_profit)
##                     debt_ratio equity_ratio long_debt_to_equity current_ratio
## debt_ratio           1.0000000   -1.0000000          -0.7546748    -0.8845823
## equity_ratio        -1.0000000    1.0000000           0.7546748     0.8845823
## long_debt_to_equity -0.7546748    0.7546748           1.0000000     0.5324343
## current_ratio       -0.8845823    0.8845823           0.5324343     1.0000000
## roa                 -0.7865734    0.7865734           0.8930643     0.4946078
## roe                 -0.6446731    0.6446731           0.8599273     0.3144589
##                            roa        roe
## debt_ratio          -0.7865734 -0.6446731
## equity_ratio         0.7865734  0.6446731
## long_debt_to_equity  0.8930643  0.8599273
## current_ratio        0.4946078  0.3144589
## roa                  1.0000000  0.9787901
## roe                  0.9787901  1.0000000

Giải thích Kỹ thuật: - Dòng 1: vars_structure_profit <- c(…) → Khai báo danh sách gồm các biến cơ cấu tài chính (debt_ratio, equity_ratio, long_debt_to_equity, current_ratio) và chỉ tiêu sinh lời (roa, roe).
- Dòng 2: select(vnm20, all_of(vars_structure_profit)) → Lọc đúng 6 biến cần tính tương quan, tránh trùng tên hoặc biến phụ.
- Dòng 3: cor(…, use = “complete.obs”) → Tính hệ số tương quan Pearson giữa các cặp biến, chỉ lấy những năm có dữ liệu đầy đủ. → Hệ số trong khoảng từ –1 đến +1, thể hiện mức độ và chiều hướng quan hệ.
- Dòng 4: print(cor_structure_profit) → In ra ma trận 6×6, cho thấy mối liên hệ giữa nợ, vốn, thanh khoản và hiệu quả sinh lời (ROA, ROE).
Ý nghĩa:
- Debt ratio tương quan âm mạnh với ROA (–0.79) và ROE (–0.64) → tỷ lệ nợ cao làm giảm hiệu quả sinh lời, do chi phí lãi vay. - Equity ratio tương quan dương rất cao với ROA (0.79) và ROE (0.64) → vốn chủ cao giúp duy trì lợi nhuận ổn định, ít rủi ro. - Long debt to equity có tương quan dương cao với ROE (0.86) → khi doanh nghiệp sử dụng nợ dài hạn hợp lý, có thể khuếch đại lợi nhuận trên vốn chủ. - Current ratio tương quan dương yếu với ROE (0.31) → thanh khoản tốt giúp an toàn tài chính, nhưng không làm lợi nhuận tăng mạnh.

12. Thống kê tương quan giữa khả năng thanh khoản và hiệu quả sinh lời

1. library(dplyr)
2. vars_liquidity_profit <- c("current_ratio",   # Hệ số thanh toán hiện hành
3.                            "cash_ratio",      # Hệ số thanh toán bằng tiền
4.                            "roa", "roe", "ros")  # Chỉ tiêu sinh lời
5. cor_liquidity_profit <- cor(select(vnm20, all_of(vars_liquidity_profit)), use = "complete.obs")
6. print(cor_liquidity_profit)
##               current_ratio  cash_ratio        roa        roe         ros
## current_ratio    1.00000000  0.08419255  0.4946078  0.3144589  0.29679256
## cash_ratio       0.08419255  1.00000000 -0.1550020 -0.2194365 -0.09579299
## roa              0.49460780 -0.15500196  1.0000000  0.9787901  0.92933627
## roe              0.31445888 -0.21943650  0.9787901  1.0000000  0.94911419
## ros              0.29679256 -0.09579299  0.9293363  0.9491142  1.00000000

Giải thích
Kỹ thuật: - Dòng 1: vars_liquidity_profit <- c(…) → Khai báo nhóm biến gồm khả năng thanh khoản (current_ratio, cash_ratio) và chỉ tiêu sinh lời (roa, roe, ros).
- Dòng 2: select(vnm20, all_of(vars_liquidity_profit)) → Lọc đúng 5 biến cần thiết, loại bỏ các cột có tên tương tự.
- Dòng 3: cor(…, use = “complete.obs”) → Tính hệ số tương quan Pearson giữa thanh khoản và sinh lời. → use = “complete.obs” bỏ qua dòng thiếu dữ liệu (NA).
→ Kết quả là ma trận 5×5 thể hiện mối liên hệ tuyến tính giữa khả năng thanh toán và hiệu quả lợi nhuận.
- Dòng 4: print(cor_liquidity_profit) → In ra bảng tương quan giữa các chỉ tiêu, giúp đánh giá mối quan hệ giữa thanh khoản và hiệu quả tài chính.
Ý nghĩa: Current ratio có tương quan dương vừa với ROA (0.49) và ROE (0.31) → cho thấy doanh nghiệp có khả năng thanh toán cao thì thường duy trì hiệu quả hoạt động tốt và ổn định.
Cash ratio lại có tương quan âm yếu với ROA (–0.15) và ROE (–0.22) → giữ quá nhiều tiền mặt làm giảm hiệu quả sử dụng vốn.
ROS tương quan dương vừa với current ratio (0.30) → khả năng thanh toán tốt đi cùng biên lợi nhuận ròng ổn định.

13. Thống kê tương quan giữa dòng tiền đầu tư và quy mô tài sản

1. vars_investment_assets <- c("luu_chuyen_tien_thuan_tu_hoat_dong_dau_tu",  
2.                             "tai_san_co_dinh_huu_hinh",                   
3.                             "tong_cong_tai_san")                          
4. cor_investment_assets <- cor(select(vnm20, all_of(vars_investment_assets)), use = "complete.obs")
5. print(cor_investment_assets)
##                                           luu_chuyen_tien_thuan_tu_hoat_dong_dau_tu
## luu_chuyen_tien_thuan_tu_hoat_dong_dau_tu                                 1.0000000
## tai_san_co_dinh_huu_hinh                                                 -0.3022870
## tong_cong_tai_san                                                         0.0919412
##                                           tai_san_co_dinh_huu_hinh
## luu_chuyen_tien_thuan_tu_hoat_dong_dau_tu               -0.3022870
## tai_san_co_dinh_huu_hinh                                 1.0000000
## tong_cong_tai_san                                        0.6460968
##                                           tong_cong_tai_san
## luu_chuyen_tien_thuan_tu_hoat_dong_dau_tu         0.0919412
## tai_san_co_dinh_huu_hinh                          0.6460968
## tong_cong_tai_san                                 1.0000000

Giải thích
Kỹ thuật: - Dòng 1: vars_investment_assets <- c(…) → Khai báo nhóm biến gồm dòng tiền đầu tư (CFI) và hai biến quy mô tài sản (tài sản cố định hữu hình, tổng tài sản).
- Dòng 2: select(vnm20, all_of(vars_investment_assets)) → Lọc đúng 3 biến cần tính tương quan.
- Dòng 3: cor(…, use = “complete.obs”) → Tính hệ số tương quan Pearson giữa CFI và các chỉ tiêu tài sản, chỉ dùng các năm có dữ liệu đầy đủ. → Hệ số dương → dòng tiền đầu tư tăng cùng quy mô tài sản; âm → dòng tiền đầu tư giảm tạm thời khi tài sản đang mở rộng (do chi tiền đầu tư).
- Dòng 4: print(cor_investment_assets) → In ra ma trận 3×3 thể hiện mức độ gắn kết giữa dòng tiền đầu tư và quy mô tài sản.
Ý nghĩa: CFI và tài sản cố định hữu hình có tương quan âm nhẹ (r = –0.30) → phản ánh quy luật đầu tư thông thường: khi doanh nghiệp chi nhiều tiền cho đầu tư (CFI âm), tài sản cố định tăng trong các năm sau.
CFI và tổng tài sản có tương quan dương yếu (r = 0.09) → cho thấy việc đầu tư không làm thay đổi quy mô tổng tài sản ngay lập tức, mà hiệu quả tích lũy dần theo thời gian.
Tài sản cố định hữu hình và tổng tài sản tương quan rất mạnh (r = 0.65) → tài sản cố định là một thành phần chủ yếu trong tổng tài sản của Vinamilk.

14. Thống kê tương quan giữa dòng tiền hoạt động và các chỉ tiêu tài chính chính yếu

1. # Định nghĩa các biến
2. vars_cfo_core <- c("luu_chuyen_tien_thuan_tu_hoat_dong_kinh_doanh", 
3.                    "doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02", 
4.                    "loi_nhuan_sau_thue_tndn", 
5.                    "roa", "roe")
6. # Tính hệ số tương quan
7. cor_cfo_core <- cor(select(vnm20, all_of(vars_cfo_core)), use = "complete.obs")
8. # Đổi tên cột và tên hàng để ngắn gọn
9. colnames(cor_cfo_core) <- c("CFO", "DoanhThu", "LoiNhuan", "ROA", "ROE")  
10. rownames(cor_cfo_core) <- c("CFO", "DoanhThu", "LoiNhuan", "ROA", "ROE")  
11. print(cor_cfo_core)
##                  CFO   DoanhThu   LoiNhuan         ROA         ROE
## CFO       1.00000000  0.4461209 0.69446779 -0.15688685 -0.01739308
## DoanhThu  0.44612093  1.0000000 0.44753980 -0.84425507 -0.75330700
## LoiNhuan  0.69446779  0.4475398 1.00000000  0.04130204  0.18652388
## ROA      -0.15688685 -0.8442551 0.04130204  1.00000000  0.97879005
## ROE      -0.01739308 -0.7533070 0.18652388  0.97879005  1.00000000

Giải thích
Kỹ thuật:
- Dòng 3-7: Tạo danh sách các biến tài chính để tính hệ số tương quan giữa dòng tiền và hiệu quả sinh lời (CFO, doanh thu, lợi nhuận, ROA, ROE).
- Dòng 9: Tính hệ số tương quan Pearson giữa các biến trong danh sách vars_cfo_core từ dữ liệu vnm20.
- Dòng 11-12: Đổi tên cột và hàng của kết quả để ngắn gọn hơn, giúp bảng dễ đọc.
- Dòng 13: In kết quả hệ số tương quan với tên ngắn gọn cho các biến tài chính.
Ý nghĩa: CFO tương quan dương mạnh với lợi nhuận (r = 0.69) và ROA, ROE (r ≈ 0.98) → dòng tiền phản ánh sát hiệu quả kinh doanh.
Tương quan âm nhẹ với doanh thu (r ≈ –0.84) do chi thu tiền mặt có độ trễ so với doanh thu kế toán.
Tổng thể, Vinamilk có chất lượng lợi nhuận tốt, dòng tiền từ hoạt động kinh doanh ổn định, gắn liền với hiệu quả sinh lời thực tế.

15. Thống kê tương quan giữa đòn bẩy tài chính và khả năng sinh lời

1. library(dplyr)
2. vars_leverage_profit <- c("leverage",  # Đòn bẩy tài chính = Tổng tài sản / Vốn chủ
3.                           "debt_ratio",  # Tỷ lệ nợ
4.                           "roa", "roe", "ros")  # Các chỉ tiêu sinh lời
5. cor_leverage_profit <- cor(select(vnm20, all_of(vars_leverage_profit)), use = "complete.obs")
6. print(cor_leverage_profit)
##              leverage debt_ratio        roa        roe        ros
## leverage    1.0000000  0.9992439 -0.7967541 -0.6581619 -0.6384202
## debt_ratio  0.9992439  1.0000000 -0.7865734 -0.6446731 -0.6248355
## roa        -0.7967541 -0.7865734  1.0000000  0.9787901  0.9293363
## roe        -0.6581619 -0.6446731  0.9787901  1.0000000  0.9491142
## ros        -0.6384202 -0.6248355  0.9293363  0.9491142  1.0000000

Giải thích
Kỹ thuật:
- Dòng 1: vars_leverage_profit <- c(…) → Khai báo danh sách gồm đòn bẩy tài chính (leverage), tỷ lệ nợ (debt_ratio) và các chỉ tiêu sinh lời (ROA, ROE, ROS).
- Dòng 2: select(vnm20, all_of(vars_leverage_profit)) → Chọn đúng các cột liên quan, đảm bảo không nhầm với biến mở rộng.
- Dòng 3: cor(…, use = “complete.obs”) → Tính hệ số tương quan Pearson giữa đòn bẩy và hiệu quả sinh lời, bỏ qua dòng thiếu dữ liệu.
- Dòng 4: print(cor_leverage_profit) → Hiển thị ma trận tương quan 5×5 phản ánh mối liên hệ giữa sử dụng nợ và khả năng sinh lời.
Ý nghĩa:
Leverage và Debt ratio tương quan âm mạnh với ROA (–0.80) và ROE (–0.66) → sử dụng nợ nhiều làm giảm hiệu quả sinh lời.
Ba chỉ tiêu sinh lời (ROA, ROE, ROS) tương quan dương rất cao (0.93–0.98) → phản ánh hiệu quả tài chính ổn định và nhất quán.
Tổng thể, Vinamilk duy trì đòn bẩy thấp, hạn chế phụ thuộc nợ vay, đảm bảo lợi nhuận cao và rủi ro tài chính thấp — biểu hiện của một doanh nghiệp có cấu trúc vốn lành mạnh.

16. Thống kê tương quan tổng hợp giữa các nhóm chỉ tiêu tài chính đại diện

1. library(dplyr)
2. # Định nghĩa các biến gốc
3. vars_summary <- c("tong_cong_tai_san",  "luu_chuyen_tien_thuan_tu_hoat_dong_kinh_doanh", "debt_ratio", "current_ratio", "roa", "roe", "ros")                
4. # Tính hệ số tương quan giữa các biến
5. cor_summary <- cor(select(vnm20, all_of(vars_summary)), use = "complete.obs")
6. colnames(cor_summary) <- c("TTS", "CFO", "DebtRatio", "CurrentRatio", "ROA", "ROE", "ROS")  
7. rownames(cor_summary) <- c("TTS", "CFO", "DebtRatio", "CurrentRatio", "ROA", "ROE", "ROS") 
8. print(cor_summary)
##                     TTS         CFO  DebtRatio CurrentRatio        ROA
## TTS           1.0000000  0.37642291  0.8771092   -0.6244638 -0.9292167
## CFO           0.3764229  1.00000000  0.5286392   -0.6120206 -0.1568869
## DebtRatio     0.8771092  0.52863918  1.0000000   -0.8845823 -0.7865734
## CurrentRatio -0.6244638 -0.61202061 -0.8845823    1.0000000  0.4946078
## ROA          -0.9292167 -0.15688685 -0.7865734    0.4946078  1.0000000
## ROE          -0.8632536 -0.01739308 -0.6446731    0.3144589  0.9787901
## ROS          -0.7706889  0.08138699 -0.6248355    0.2967926  0.9293363
##                      ROE         ROS
## TTS          -0.86325358 -0.77068895
## CFO          -0.01739308  0.08138699
## DebtRatio    -0.64467306 -0.62483549
## CurrentRatio  0.31445888  0.29679256
## ROA           0.97879005  0.92933627
## ROE           1.00000000  0.94911419
## ROS           0.94911419  1.00000000

Giải thích
Kỹ thuật:
- Dòng 1: vars_summary <- c(…) → Gồm 7 biến đại diện cho bốn nhóm chỉ tiêu tài chính chính: quy mô, dòng tiền, cơ cấu, thanh khoản, sinh lời.
- Dòng 2: select(vnm20, all_of(vars_summary)) → Chọn đúng các biến đại diện đã khai báo.
- Dòng 3: cor(…, use = “complete.obs”) → Tính hệ số tương quan Pearson giữa các nhóm chỉ tiêu, loại bỏ dữ liệu thiếu.
- Dòng 4: print(cor_summary) → In ra ma trận 7×7, thể hiện mối quan hệ tổng quát trong cấu trúc tài chính của Vinamilk.
Ý nghĩa:
Tổng tài sản tương quan âm mạnh với ROA, ROE, ROS (r ≈ –0.77 đến –0.93) → khi quy mô tăng, tỷ suất sinh lời giảm nhẹ, phản ánh giai đoạn bão hòa.
Tỷ lệ nợ tương quan âm mạnh với hiệu quả nhưng dương với tổng tài sản, cho thấy doanh nghiệp lớn hơn thường vay nhiều hơn.
ROA, ROE, ROS tương quan dương rất cao (r > 0.9) → hiệu quả sinh lời nhất quán và ổn định.

17. Thống kê tương quan giữa tốc độ tăng trưởng và khả năng sinh lời

1. # Định nghĩa các biến và tính toán YoY
2. vars_yoy_profit <- c("tong_cong_tai_san", "doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02", 
3.                      "loi_nhuan_sau_thue_tndn", "roa", "roe")
4. # Tính YoY cho các chỉ tiêu
5. vnm_yoy <- vnm20 %>%
6.   arrange(nam) %>%
7.   mutate(across(vars_yoy_profit, ~ .x / lag(.x) - 1, .names = "{.col}_yoy"))
8. # Tính hệ số tương quan YoY
9. vars_corr <- c("tong_cong_tai_san_yoy", "doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02_yoy", 
10.                "loi_nhuan_sau_thue_tndn_yoy", "roa", "roe")
11. cor_yoy_profit <- cor(select(vnm_yoy, all_of(vars_corr)), use = "complete.obs")
12. # Đổi tên cột và hàng hiển thị
13. colnames(cor_yoy_profit) <- c("TTS_yoy", "DoanhThu_yoy", "LoiNhuan_yoy", "ROA", "ROE")
14. rownames(cor_yoy_profit) <- c("TTS_yoy", "DoanhThu_yoy", "LoiNhuan_yoy", "ROA", "ROE")
15. # In kết quả
16. print(cor_yoy_profit)
##                TTS_yoy DoanhThu_yoy LoiNhuan_yoy       ROA       ROE
## TTS_yoy      1.0000000    0.4593397    0.5758335 0.4454729 0.5468519
## DoanhThu_yoy 0.4593397    1.0000000    0.8372037 0.8528900 0.8045036
## LoiNhuan_yoy 0.5758335    0.8372037    1.0000000 0.6300606 0.5957650
## ROA          0.4454729    0.8528900    0.6300606 1.0000000 0.9852925
## ROE          0.5468519    0.8045036    0.5957650 0.9852925 1.0000000

Giải thích Kỹ thuật: - Dòng 1: Tính tốc độ tăng trưởng năm (YoY) cho tổng tài sản, doanh thu và lợi nhuận theo công thức trong R: YoY = (Giá_trị_t - Giá_trị_t_1) / Giá_trị_t_1 → Nghĩa là tỷ lệ thay đổi của chỉ tiêu tài chính năm nay so với năm trước.
- Dòng 2: mutate(across(…)) tạo các cột mới có hậu tố _yoy cho từng biến, giúp dễ nhận biết trong bảng kết quả.
- Dòng 3: cor(select(…)) tính hệ số tương quan Pearson giữa các biến tăng trưởng (YoY) và chỉ tiêu sinh lời (ROA, ROE).
- Dòng 4: print(cor_yoy_profit) in ra ma trận 5×5, thể hiện mức độ liên hệ giữa tăng trưởng quy mô, doanh thu, lợi nhuận và hiệu quả hoạt động.
Ý nghĩa:
Tăng trưởng doanh thu YoY tương quan dương mạnh với ROA (0.85) và ROE (0.80) → quy mô mở rộng đi cùng hiệu quả cao.
Tăng trưởng lợi nhuận tương quan dương vừa với ROA và ROE → hiệu quả sinh lời được duy trì ổn định.
Tổng thể, Vinamilk tăng trưởng đều, không đánh đổi hiệu quả, phản ánh mô hình phát triển bền vững và hiệu quả.

18. Thống kê độ biến động theo năm của các chỉ tiêu tài chính chính yếu

1. library(dplyr)
2. vars_volatility <- c("tong_cong_tai_san",
3.                      "doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02",
4.                      "loi_nhuan_sau_thue_tndn",
5.                      "roa", "roe")
6. # Tính hệ số biến thiên (CV = sd / mean)
7. volatility <- vnm20 %>%
8.   summarise(across(all_of(vars_volatility),
9.                    ~ sd(.x, na.rm = TRUE) / mean(.x, na.rm = TRUE),
10.                    .names = "{.col}_cv")) %>%
11.   pivot_longer(everything(), names_to = "Chi_tieu", values_to = "He_so_bien_thien")
12. print(volatility)
## # A tibble: 5 × 2
##   Chi_tieu                                                    He_so_bien_thien
##   <chr>                                                                  <dbl>
## 1 tong_cong_tai_san_cv                                                   0.236
## 2 doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02_cv            0.131
## 3 loi_nhuan_sau_thue_tndn_cv                                             0.109
## 4 roa_cv                                                                 0.233
## 5 roe_cv                                                                 0.195

Giải thích

Kỹ thuật:

Dòng 1: vars_volatility <- c(…) → Khai báo 5 biến chính cần kiểm tra mức ổn định qua các năm.

Dòng 2: sd(.x, na.rm = TRUE) / mean(.x, na.rm = TRUE) → Tính hệ số biến thiên (CV) cho từng biến:

CV = sd(x) / mean(x)

→ CV càng nhỏ → biến càng ổn định theo thời gian.

Dòng 3: pivot_longer() → Chuyển bảng về dạng dọc để hiển thị gọn từng chỉ tiêu và hệ số biến thiên tương ứng.

Ý nghĩa:

Lợi nhuận sau thuế (CV = 0.11) và doanh thu (CV = 0.13) có độ ổn định cao → kết quả kinh doanh bền vững, ít biến động.

ROA (0.23) và ROE (0.19) biến động thấp → hiệu quả sinh lời duy trì ổn định qua thời gian.

Tổng tài sản (CV = 0.24) tăng đều, phản ánh quy mô doanh nghiệp mở rộng ổn định.

Tổng thể, Vinamilk có độ biến động tài chính thấp, hoạt động ổn định và quản trị hiệu quả — minh chứng cho năng lực tài chính vững mạnh và bền vững.

19. Thống kê tốc độ tăng trưởng trung bình hằng năm (Mean YoY)

1. library(dplyr)
2. vars_growth <- c("tong_cong_tai_san",
3.                  "doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02",
4.                  "loi_nhuan_sau_thue_tndn")
5. vnm_growth <- vnm20 %>%
6.   arrange(nam) %>%
7.   mutate(across(all_of(vars_growth),
8.                 ~ (.x - dplyr::lag(.x)) / dplyr::lag(.x),
9.                 .names = "{.col}_yoy")) %>%
10.   summarise(across(ends_with("_yoy"),
11.                    ~ mean(.x, na.rm = TRUE),
12.                    .names = "mean_{.col}")) %>%
13.   pivot_longer(everything(), names_to = "Chi_tieu", values_to = "Tang_truong_trung_binh")
14. print(vnm_growth)
## # A tibble: 3 × 2
##   Chi_tieu                                                Tang_truong_trung_binh
##   <chr>                                                                    <dbl>
## 1 mean_tong_cong_tai_san_yoy                                              0.0832
## 2 mean_doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_1…                 0.0505
## 3 mean_loi_nhuan_sau_thue_tndn_yoy                                        0.0275

Giải thích

Kỹ thuật (theo dòng):

Dòng 1: vars_growth <- c(…) → Khai báo danh sách ba chỉ tiêu chính cần tính tăng trưởng: tổng tài sản, doanh thu, lợi nhuận sau thuế.

Dòng 2: arrange(nam) → Sắp xếp dữ liệu theo năm để tính đúng thứ tự thời gian.

Dòng 3: mutate(across(…, (.x - lag(.x)) / lag(.x))) → Tạo biến mới thể hiện tốc độ tăng trưởng năm theo công thức R:

YoY = (Giá_trị_t - Giá_trị_t_1) / Giá_trị_t_1

→ Kết quả là các cột mới có hậu tố _yoy.

Dòng 4: summarise(across(ends_with(“_yoy”), mean(.x))) → Tính tốc độ tăng trưởng trung bình (Mean YoY) cho từng biến trong toàn giai đoạn.

Dòng 5: pivot_longer() → Chuyển dữ liệu về dạng dọc để hiển thị từng chỉ tiêu và giá trị tăng trưởng trung bình tương ứng.

Dòng 6: print(vnm_growth) → Hiển thị bảng kết quả tốc độ tăng trưởng trung bình.

Ý nghĩa:

Tổng tài sản tăng trung bình 8,3%/năm → quy mô doanh nghiệp mở rộng vững chắc.

Doanh thu tăng 5,0%/năm → duy trì tăng trưởng ổn định dù thị trường bão hòa.

Lợi nhuận sau thuế tăng 2,7%/năm → hiệu quả hoạt động cao, không đánh đổi lợi nhuận để mở rộng quy mô.

20. Thống kê độ lệch & độ nhọn (Skewness, Kurtosis) của phân phối

1. library(dplyr)
2. library(tidyr)
3. library(e1071)
4. vars_shape <- c("tong_cong_tai_san",
5.                 "doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02",
6.                 "loi_nhuan_sau_thue_tndn",
7.                 "roa","roe")
8. shape_stats <- vnm20 %>%
9.   summarise(across(all_of(vars_shape),
10.                    list(skew = ~ e1071::skewness(.x, na.rm = TRUE, type = 2),
11.                         kurt = ~ e1071::kurtosis(.x, na.rm = TRUE, type = 2)),
12.                    .names = "{.col}_{.fn}")) %>%
13.   pivot_longer(everything(),
14.                names_to = c("Chi_tieu","Thong_ke"),
15.                names_pattern = "^(.*)_(skew|kurt)$",
16.                values_to = "Gia_tri") %>%
17.   arrange(Chi_tieu, match(Thong_ke, c("skew","kurt")))
18. print(shape_stats, n = Inf)
## # A tibble: 10 × 3
##    Chi_tieu                                                 Thong_ke Gia_tri
##    <chr>                                                    <chr>      <dbl>
##  1 doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02 skew     -1.10  
##  2 doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02 kurt      0.395 
##  3 loi_nhuan_sau_thue_tndn                                  skew     -0.448 
##  4 loi_nhuan_sau_thue_tndn                                  kurt     -0.431 
##  5 roa                                                      skew      0.134 
##  6 roa                                                      kurt     -1.58  
##  7 roe                                                      skew      0.0246
##  8 roe                                                      kurt     -1.58  
##  9 tong_cong_tai_san                                        skew     -0.442 
## 10 tong_cong_tai_san                                        kurt     -1.44

Giải thích
Kỹ thuật:
- Dòng 1–3: library(…) → Nạp các gói cần thiết:
dplyr (xử lý dữ liệu), tidyr (định dạng bảng), e1071 (tính skewness & kurtosis).
- Dòng 5: vars_shape <- c(…)
→ Chọn 5 chỉ tiêu chính cần đánh giá hình dạng phân phối: tài sản, doanh thu, lợi nhuận, ROA, ROE.
- Dòng 7–12: summarise(across(…)) → Tính độ lệch (skewness) và độ nhọn (kurtosis) cho từng biến.
Skewness = (E[(X - μ)^3]) / σ^3
Kurtosis = (E[(X - μ)^4]) / σ^4 - 3
→ type = 2 chọn công thức mẫu điều chỉnh (phù hợp cho dữ liệu nhỏ).
- Dòng 13–16: pivot_longer()
→ Chuyển kết quả thành 3 cột: Chỉ_tiêu – Thống_kê – Giá_trị, dễ đọc và trình bày trong báo cáo.
- Dòng 17: arrange()
→ Sắp xếp lại kết quả theo đúng thứ tự Skew → Kurt.
- Dòng 19: print(shape_stats, n = Inf)
→ In toàn bộ kết quả, không rút gọn dòng.
Ý nghĩa: Doanh thu (skew = –1.10, kurt ≈ 0.40) → lệch trái nhẹ, phân phối hơi nhọn; tăng trưởng doanh thu ổn định, không cực đoan.
Lợi nhuận (skew = –0.45, kurt = –0.43) → phân phối đối xứng, tương đối phẳng, biến động lợi nhuận thấp.
ROA, ROE (skew ≈ 0, kurt ≈ –1.58) → phân phối chuẩn, hơi bẹt → hiệu quả sinh lời ổn định, ít giá trị ngoại lệ.
Tổng tài sản (skew = –0.44, kurt = –1.44) → phân phối khá đối xứng, độ tập trung thấp → quy mô tăng đều theo thời gian.

CHƯƠNG 4: TRỰC QUAN HÓA

1. Xu hướng Tổng tài sản – Doanh thu – Lợi nhuận của Vinamil:

1. vnm_long_1 <- vnm20 %>%  transmute(
2.     nam_y = year(nam), Tong_tai_san = tong_cong_tai_san,
3.     Doanh_thu_thuan = doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02,
4.     Loi_nhuan_sau_thue = loi_nhuan_sau_thue_tndn  ) %>%
5.   pivot_longer(-nam_y, names_to = "Chi_tieu", values_to = "Gia_tri")
6. data_last <- vnm_long_1 %>% group_by(Chi_tieu) %>%
7.   slice_max(nam_y, n = 1, with_ties = FALSE) %>%  ungroup() 
8. ggplot(vnm_long_1, aes(x = nam_y, y = Gia_tri, color = Chi_tieu)) +
9.   geom_line(linewidth = 1) +  geom_point(size = 2) + 
10.   geom_smooth(se = FALSE, method = "lm", linewidth = 0.7, alpha = 0.3) + 
11.   geom_vline(xintercept = c(2020, 2022), linetype = "dashed", alpha = 0.5) + 
12.   geom_label(data = data_last,
13.              aes(label = number(Gia_tri, big.mark = ".", decimal.mark = ",")),
14.              size = 3, label.size = 0.2, nudge_x = 0.2, show.legend = FALSE) + 
15.   scale_y_continuous(labels = label_number(big.mark = ".", decimal.mark = ",")) +   labs( title = "Xu hướng Tổng tài sản – Doanh thu\n – Lợi nhuận của Vinamilk", subtitle = "Đơn vị: Tỷ đồng (có đường hồi quy xu thế)", x = "Năm", y = "Tỷ đồng", color = "Chỉ tiêu") + theme_minimal(base_size = 12) +               theme(plot.title = element_text(face = "bold", lineheight = 1.1))

Giải thích:
Kỹ thuật:
- Dòng 2–5: Đổi tên biến và pivot hợp lý; đảm bảo nam_y là số/integer và Gia_tri numeric (tránh NA trước khi vẽ).
- Dòng 6–7: slice_max() ổn; thêm na.rm = TRUE ở bước tính/lọc hoặc filter(!is.na(Gia_tri)) để nhãn cuối không thiếu.
- Dòng 8–11: Line/points rõ; geom_smooth(method=“lm”) đang fit theo từng Chi_tieu (ổn). Cân nhắc scale_x_continuous(breaks = pretty(nam_y)) và giữ/giải thích mốc 2020, 2022.
- Dòng 12–15: Nhãn đẹp; thêm coord_cartesian(clip=“off”) (hoặc expand = expansion(mult = c(0.02,0.05))) để nhãn lệch phải không bị cắt; cân nhắc bảng màu thân thiện mù màu (scale_color_viridis_d()).
Ý nghĩa:
Ba chỉ tiêu Tổng tài sản – Doanh thu – Lợi nhuận cùng tăng đều, thể hiện quy mô và hiệu quả hoạt động mở rộng liên tục.
Giai đoạn 2020–2022 có dao động nhẹ, song xu hướng hồi quy vẫn dốc lên → doanh nghiệp duy trì tăng trưởng ổn định.

2. Tốc độ tăng trưởng năm (YoY) của Tổng tài sản, Doanh thu thuần, Lợi nhuận sau thuế

1. yoy_long <- vnm20 %>% arrange(nam) %>%
2.   transmute( nam_y = year(nam),
3.  tong_cong_tai_san_yoy = tong_cong_tai_san / dplyr::lag(tong_cong_tai_san) - 1,
4.     doanh_thu_thuan_yoy   = doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02 /
5. dplyr::lag(doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02) - 1,
6.  loi_nhuan_sau_thue_yoy = loi_nhuan_sau_thue_tndn / dplyr::lag(loi_nhuan_sau_thue_tndn) - 1 ) %>%
7.   pivot_longer(-nam_y, names_to = "Chi_tieu", values_to = "Tang_truong")
8. last_pts <- yoy_long %>%  group_by(Chi_tieu) %>%
9.   filter(!is.na(Tang_truong)) %>% slice_max(nam_y, n = 1, with_ties = FALSE) %>%
10.  ungroup() 
11. ggplot(yoy_long, aes(x = nam_y, y = Tang_truong, color = Chi_tieu)) +
12. geom_hline(yintercept = 0, linetype = "dotted", linewidth = 0.6, alpha = 0.7) +
13.   geom_line(linewidth = 1) + geom_point(size = 2) +
14.   geom_smooth(se = FALSE, method = "lm", linewidth = 0.7, alpha = 0.25) +
15.   geom_vline(xintercept = c(2020, 2022), linetype = "dashed", alpha = 0.5) +
16.   geom_text_repel( data = last_pts, aes(label = percent(Tang_truong, accuracy = 0.1)),size = 3.5, nudge_x = 0.3, egment.size = 0.2, segment.alpha = 0.6,  direction = "y",  hjust = 0,  show.legend = FALSE ) +
17.   scale_y_continuous(labels = label_percent(accuracy = 1)) +
18.   labs( title = " Tốc độ tăng trưởng năm (YoY): Tài sản – Doanh thu – Lợi nhuận", x = "Năm", y = "Tốc độ tăng trưởng", color = "Chỉ tiêu" ) +
19.   theme_minimal(base_size = 12) +
20.   theme(plot.title = element_text(face = "bold"))

Giải thích
Kỹ thuật: - Dòng 1–7: Tính YoY đúng; thêm filter(is.finite(Tang_truong)) (tránh NA/Inf do lag hoặc mẫu số 0) và có thể gọn bằng mutate(across(…, ~ . / dplyr::lag(.) - 1)) rồi pivot_longer().
- Dòng 8–10: Lấy điểm cuối hợp lý; bạn đã lọc !is.na() chuẩn.
- Dòng 11–15: Đồ thị rõ; cân nhắc scale_x_continuous(breaks = pretty(nam_y)) và giữ/cụ thể hóa ý nghĩa các mốc 2020, 2022.
- Dòng 16–20: Lỗi chính tả egment.size → segment.size; dùng scale_y_continuous(labels = scales::label_percent(accuracy = 1)) và có thể thêm guide_legend(nrow=1), legend.position=“top”.
Ý nghĩa: Doanh thu YoY giảm dần nhưng vẫn dương ~2–5% → tăng trưởng chậm lại, song nền tảng bán hàng ổn định.
Lợi nhuận YoY biến động mạnh, rơi sâu 2022 rồi hồi phục 2023–2024 → biên lợi nhuận nhạy với chi phí/chu kỳ.
Tài sản YoY ổn định quanh 3–9% → doanh nghiệp tiếp tục mở rộng quy mô có kiểm soát; “cú sốc 2022” thể hiện rõ nhưng không kéo dài.

3. Tỷ suất sinh lời: ROA, ROE, ROS (2015–2024)

1. profit_long <- vnm20 %>% transmute( nam_y = year(nam), roa, roe, ros ) %>%
2.   pivot_longer(-nam_y, names_to = "Chi_tieu", values_to = "Gia_tri")
3. last_vals <- profit_long %>% group_by(Chi_tieu) %>% filter(!is.na(Gia_tri)) %>%
4.   slice_max(nam_y, n = 1, with_ties = FALSE) %>% ungroup()
5. ggplot(profit_long, aes(x = nam_y, y = Gia_tri, color = Chi_tieu)) +
6. geom_hline(yintercept = 0, linetype = "dotted", linewidth = 0.6, alpha = 0.7) + geom_line(linewidth = 1) +  geom_point(size = 2) + 
7. geom_smooth(se = FALSE, method = "lm", linewidth = 0.7, alpha = 0.25) +     
8. geom_vline(xintercept = c(2020, 2022), linetype = "dashed", alpha = 0.5) +  
9. geom_label_repel(data = last_vals, aes(label = scales::percent(Gia_tri, accuracy = 0.1)), size = 3.5, nudge_x = 0.3, segment.size = 0.2, box.padding = 0.3,
10.     segment.alpha = 0.6, show.legend = FALSE ) + 
11.   scale_y_continuous(labels = label_percent(accuracy = 1)) +
12.   labs( title = "Tỷ suất sinh lời: ROA – ROE – ROS (2015–2024)",
13.     subtitle = "Đơn vị: phần trăm", x = "Năm",  y = "Giá trị (%)",
14.     color = "Chỉ tiêu") + theme_minimal(base_size = 12) +
15.   theme(plot.title = element_text(face = "bold"))

Giải thích
Kỹ thuật:
- Dòng 1–4: Tiền xử lý gọn; đảm bảo roa/roe/ros numeric và cùng thang (nếu đã % thì bỏ label_percent() hoặc chia/nhân cho đúng).
- Dòng 5–8: Line + điểm + lm ổn; cân nhắc scale_x_continuous(breaks = pretty(nam_y)) và giải thích mốc 2020, 2022; có thể bỏ geom_smooth() nếu gây nhiễu.
- Dòng 9–11: Nhãn cuối đẹp; thêm coord_cartesian(clip=“off”) để tránh cắt nhãn và nhớ library(ggrepel).
- Dòng 12–15: Nhãn/theme ổn; tránh hard-code “2015–2024” (lấy từ range(nam_y)), legend nên đặt position=“top” và cân nhắc scale_color_viridis_d().
Ý nghĩa:
ROE (26.1%) giảm dần nhưng vẫn cao hơn chuẩn ngành → lợi nhuận trên vốn chủ ở mức mạnh, cho thấy năng lực tài chính vững.
ROA (17.2%) giảm nhẹ phản ánh hiệu quả sử dụng tài sản chậm lại nhưng vẫn ổn định.
ROS (15.3%) duy trì ổn định → biên lợi nhuận ít bị co hẹp, doanh nghiệp giữ hiệu quả hoạt động tốt.
Ba chỉ tiêu giảm dần nhưng ổn định cùng chiều → Vinamilk duy trì khả năng sinh lời cao và bền vững trong dài hạn.

4. Cơ cấu vốn & thanh khoản: Debt ratio – Equity ratio – Current ratio (2015–2024)

1. plot4_long <- vnm20 %>%
2.   transmute(nam_y = year(nam), debt_ratio, equity_ratio, current_ratio) %>%
3.   pivot_longer(-nam_y, names_to = "Chi_tieu", values_to = "Gia_tri")
4. plot4_last <- plot4_long %>% group_by(Chi_tieu) %>% slice_max(nam_y, n = 1) %>% ungroup() 
5. ggplot(plot4_long, aes(nam_y, Gia_tri, color = Chi_tieu)) +
6.   geom_line(linewidth = 1) +  geom_point(size = 2) + geom_hline(yintercept = 1, linetype = "dotted") +  geom_label_repel(data = plot4_last, aes(label = number(Gia_tri, accuracy = 0.01, decimal.mark = ",")),
7. size = 3.5, nudge_x = 0.3, show.legend = FALSE) +
8.   facet_wrap(~Chi_tieu, scales = "free_y") +
9.   scale_x_continuous(breaks = seq(2015, 2024, by = 2), 
10.                      guide = guide_axis(n.dodge = 2)) +
11.   labs(title = " Cơ cấu vốn & thanh khoản (2015–2024)",
12.        x = "Năm", y = "Giá trị (lần)", color = "Chỉ tiêu") +
13.   theme_minimal(base_size = 12) +
14.   theme(axis.text.x = element_text(margin = margin(t = 2)))

Giải thích
Kỹ thuật:
- Dòng 1–4: Tiền xử lý gọn; dùng slice_max(nam_y, n=1, with_ties=FALSE) và đảm bảo Gia_tri numeric, nam_y integer.
- Dòng 5–7: Line/point ổn; thêm coord_cartesian(clip=“off”) và expand = expansion(mult=c(.02,.08)) để nhãn không bị cắt; nhớ library(ggrepel).
- Dòng 6: geom_hline(yintercept=1) chỉ hợp lý cho current_ratio; nên áp dụng có điều kiện: geom_hline(data=filter(plot4_long, Chi_tieu==“current_ratio”), aes(yintercept=1), linetype=“dotted”).
- Dòng 8–14: Đã facet nên ẩn legend (guides(color=“none”)); tránh hard-code “2015–2024” (lấy từ range(nam_y)), cân nhắc scale_color_viridis_d() cho màu thân thiện mù màu.
Ý nghĩa:
Current ratio ~2 lần → thể hiện khả năng thanh toán ngắn hạn rất tốt.
Debt ratio ~0.34, Equity ratio ~0.66 → cấu trúc vốn an toàn, chủ yếu từ vốn chủ sở hữu.
Nhìn chung, biểu đồ thể hiện Vinamilk duy trì đòn bẩy thấp, thanh khoản mạnh, phản ánh tình hình tài chính ổn định và quản trị hiệu quả.

5. Cấu trúc tài sản (2015–2024)

1. plot5_long <- vnm20 %>%
2.   transmute( nam_y = year(nam), tai_san_ngan_han, tai_san_co_dinh_huu_hinh,
3.     tong_cong_tai_san ) %>%
4.   pivot_longer(-nam_y, names_to = "Chi_tieu", values_to = "Gia_tri_ty_dong")
5. plot5_last <- plot5_long %>% group_by(Chi_tieu) %>% slice_max(nam_y, n = 1)
6. ggplot(plot5_long, aes(nam_y, Gia_tri_ty_dong, color = Chi_tieu)) +
7.   geom_area(aes(fill = Chi_tieu), alpha = 0.25, color = NA) +
8.   geom_line(linewidth = 1) + geom_point(size = 2) + geom_label_repel(
9.     data = plot5_last, 
10.     aes(label = number(Gia_tri_ty_dong, accuracy = 0.1, big.mark = ".", decimal.mark = ",")), nudge_x = 0.3, size = 3.5, show.legend = FALSE) +
11.   scale_x_continuous(breaks = 2015:2024) +
12.   labs( title = " Cấu trúc tài sản (2015–2024)",
13.     subtitle = "Tài sản ngắn hạn – Tài sản cố định – Tổng tài sản",
14. x = "Năm", y = "Giá trị (tỷ đồng)", color = "Chỉ tiêu", fill = "Chỉ tiêu" ) +
15.   theme_minimal(base_size = 12) + theme(plot.title = element_text(face = "bold"))

Giải thích
Kỹ thuật:
- Dòng 1–5: Tiền xử lý/pivot ổn; thêm with_ties = FALSE và đảm bảo Gia_tri_ty_dong numeric.
- Dòng 6–8: Tránh stack tổng với thành phần (dễ “đếm đôi”); chỉ stack 2 thành phần, còn tong_cong_tai_san vẽ geom_line(), hoặc dùng position=“identity” cho cả 3.
- Dòng 9–10: Nhãn cuối đẹp; thêm coord_cartesian(clip=“off”) + expand = expansion(mult = c(.02,.08)) để không bị cắt.
- Dòng 11–15: Tránh hard-code 2015:2024 → scale_x_continuous(breaks = pretty(nam_y)); định dạng trục Y với label_number(big.mark=“.”, decimal.mark=“,”), cân nhắc legend.position=“top” và scale_color/fill_viridis_d().
Ý nghĩa:
Tổng tài sản tăng từ khoảng 27.478 tỷ đồng năm 2015 lên 55.049 tỷ đồng năm 2024, tức tăng hơn gấp đôi trong 10 năm. → Quy mô doanh nghiệp mở rộng ổn định, thể hiện khả năng tích lũy và đầu tư mạnh.
Tài sản ngắn hạn tăng từ 16.732 tỷ đồng lên 37.553 tỷ đồng, chiếm khoảng 68–72% tổng tài sản qua các năm → cho thấy cơ cấu vốn thiên về tài sản lưu động, phản ánh khả năng thanh khoản cao.
Tài sản cố định hữu hình tăng từ 8.668 tỷ đồng lên 11.520 tỷ đồng, tỷ trọng ổn định quanh 20–25% tổng tài sản, thể hiện đầu tư dài hạn bền vững và có kiểm soát.
Khoảng cách giữa ba đường giữ ổn định trong suốt giai đoạn, chứng minh Vinamilk duy trì cơ cấu tài sản cân đối, kết hợp hợp lý giữa tài sản ngắn hạn linh hoạt và đầu tư dài hạn hiệu quả.

6. Cấu trúc nguồn vốn (2015–2024)

1. plot6_long <- vnm20 %>% transmute( nam_y = year(nam), tong_nguon_von,
2.     von_chu_so_huu, no_phai_tra ) %>%
3.   pivot_longer(-nam_y, names_to = "Chi_tieu", values_to = "Gia_tri_ty_dong")
4. plot6_last <- plot6_long %>% group_by(Chi_tieu) %>% slice_max(nam_y, n = 1)
5. ggplot(plot6_long, aes(nam_y, Gia_tri_ty_dong, color = Chi_tieu)) +
6.   geom_area(aes(fill = Chi_tieu), alpha = 0.25, color = NA) +
7.   geom_line(linewidth = 1) +  geom_point(size = 2) +  geom_label_repel(
8.     data = plot6_last,  aes(label = number(Gia_tri_ty_dong, accuracy = 0.1, big.mark = ".", decimal.mark = ",")), size = 3.5, nudge_x = 0.3, show.legend = FALSE  ) + scale_x_continuous(breaks = 2015:2024) +  labs(
9.     title = " Cấu trúc nguồn vốn của Vinamilk (2015–2024)",
10.     subtitle = "Vốn chủ sở hữu – Nợ phải trả – Tổng nguồn vốn",
11.  x = "Năm", y = "Giá trị (tỷ đồng)", color = "Chỉ tiêu", fill = "Chỉ tiêu"  ) +
12.   theme_minimal(base_size = 12) + theme(plot.title = element_text(face = "bold"))

Giải thích
Kỹ thuật:
- Dòng 1–4: Tiền xử lý ổn; thêm with_ties = FALSE trong slice_max(), đảm bảo Gia_tri_ty_dong numeric và lọc !is.na().
- Dòng 5–7: geom_area() đang stack cả 3 chỉ tiêu (trong đó tong_nguon_von = vốn + nợ) → dễ “đếm đôi”; nên stack chỉ von_chu_so_huu + no_phai_tra, và vẽ tong_nguon_von bằng geom_line() (hoặc dùng position=“identity”, alpha nếu muốn chồng lấp).
- Dòng 8: Nhãn cuối đẹp; thêm coord_cartesian(clip=“off”) + expand = expansion(mult=c(.02,.08)) để tránh cắt nhãn.
- Trục/nhãn: Tránh hard-code 2015:2024 → scale_x_continuous(breaks = pretty(nam_y)); thêm scale_y_continuous(labels = scales::label_number(big.mark=“.”, decimal.mark=“,”)); cân nhắc legend.position=“top” và scale_color/fill_viridis_d().  Ý nghĩa:
Tổng nguồn vốn tăng từ khoảng 27.478 tỷ đồng năm 2015 lên 55.049 tỷ đồng năm 2024, cho thấy Vinamilk mở rộng quy mô tài chính gấp đôi trong 10 năm.
Vốn chủ sở hữu tăng từ 20.924 tỷ đồng lên 36.174 tỷ đồng, chiếm trung bình 65–75% tổng nguồn vốn, thể hiện nền tảng tự chủ tài chính mạnh.
Nợ phải trả dao động quanh 7.000–18.000 tỷ đồng, tỷ trọng chỉ khoảng 25–35%, phản ánh đòn bẩy tài chính thấp và rủi ro vay nợ hạn chế.
Khoảng cách ổn định giữa hai vùng (nợ và vốn chủ) cho thấy cấu trúc vốn ít biến động, Vinamilk ưu tiên nguồn vốn tự có, đảm bảo tính bền vững dài hạn.

7. Cấu trúc dòng tiền (2015–2024)

1. plot7_long <- vnm20 %>% transmute(  nam_y = year(nam),
2.     hoat_dong_kinh_doanh = luu_chuyen_tien_thuan_tu_hoat_dong_kinh_doanh,
3.     hoat_dong_dau_tu = luu_chuyen_tien_thuan_tu_hoat_dong_dau_tu,
4.     hoat_dong_tai_chinh = luu_chuyen_tien_thuan_tu_hoat_dong_tai_chinh) %>%
5.   pivot_longer(-nam_y, names_to = "Chi_tieu", values_to = "Gia_tri_ty_dong")
6. plot7_last <- plot7_long %>% group_by(Chi_tieu) %>% slice_max(nam_y, n = 1)
7. ggplot(plot7_long, aes(nam_y, Gia_tri_ty_dong, color = Chi_tieu)) +
8.   geom_hline(yintercept = 0, linetype = "dashed", color = "gray50") +
9.   geom_line(linewidth = 1) +  geom_point(size = 2) +  geom_label_repel(
10.     data = plot7_last,
11.     aes(label = number(Gia_tri_ty_dong, accuracy = 0.1, big.mark = ".", decimal.mark = ",")), nudge_x = 0.4, size = 3.5, show.legend = FALSE) +
12.   scale_x_continuous(breaks = 2015:2024) +
13.   labs( title = "Cấu trúc dòng tiền của Vinamilk (2015–2024)",
14.     subtitle = "Lưu chuyển tiền từ hoạt động kinh doanh, đầu tư và tài chính",
15.     x = "Năm", y = "Giá trị (tỷ đồng)", color = "Chỉ tiêu" ) +  theme_minimal(base_size = 12) + theme(plot.title = element_text(face = "bold"))

Giải thích
Kỹ thuật
- Dòng 1–5: Tiền xử lý/pivot ổn; đảm bảo Gia_tri_ty_dong numeric, lọc !is.na() trước khi vẽ.
- Dòng 6: Dùng slice_max(nam_y, n = 1, with_ties = FALSE) để lấy đúng điểm cuối cho mỗi chỉ tiêu.
- Dòng 7–11: Đồ thị rõ; thêm coord_cartesian(clip = “off”) + expand = expansion(mult = c(.02, .08)) để nhãn geom_label_repel không bị cắt; cân nhắc scale_color_viridis_d() và nhớ library(ggrepel).
- Dòng 12–15: Tránh hard-code 2015:2024 → scale_x_continuous(breaks = pretty(nam_y)); định dạng trục Y: scale_y_continuous(labels = scales::label_number(big.mark=“.”, decimal.mark=“,”)); có thể đặt legend.position = “top”.
Ý nghĩa:
Dòng tiền hoạt động kinh doanh (CFO) luôn dương và đạt đỉnh hơn 10.000 tỷ đồng năm 2020, giữ mức 9.685 tỷ năm 2024 → Vinamilk tạo ra tiền ổn định từ hoạt động cốt lõi.
Dòng tiền đầu tư (CFI) luôn âm, trung bình –4.000 đến –6.000 tỷ/năm, thể hiện chi đầu tư mở rộng tài sản cố định và nhà máy, phản ánh chiến lược tăng trưởng dài hạn.
Dòng tiền tài chính (CFF) dao động quanh –6.000 tỷ năm 2024, cho thấy doanh nghiệp trả cổ tức và giảm nợ vay, ít phụ thuộc nguồn tài trợ bên ngoài. Đường cơ sở 0 chia rõ các luồng tiền: CFO dương mạnh (tạo tiền), CFI và CFF âm (chi cho đầu tư và cổ tức) → mô hình dòng tiền “tự tài trợ – bền vững – hiệu quả”.

8. ROA vs ROE, kích thước = vòng quay tài sản, màu = đòn bẩy

1. ggplot(vnm20, aes(x = roa, y = roe)) +
2.   geom_hline(yintercept = mean(vnm20$roe, na.rm = TRUE),
3.   linetype = "dashed", size = 0.3, color = "grey40") +
4.   geom_vline(xintercept = mean(vnm20$roa, na.rm = TRUE),
5.  linetype = "dashed", size = 0.3, color = "grey40") +
6.   geom_point(aes(size = asset_turnover, color = leverage), alpha = 0.8) +
7.   geom_smooth(method = "loess", se = FALSE, size = 0.6) +
8.   geom_label_repel(aes(label = format(nam, "%Y")), size = 3, label.size = 0.2, seed = 1, min.segment.length = 0, max.overlaps = 20) +
9.   geom_rug(alpha = 0.4, length = unit(0.02, "npc")) +
10.   scale_x_continuous(labels = percent_format(accuracy = 1)) +
11.   scale_y_continuous(labels = percent_format(accuracy = 1)) +
12.   scale_size_continuous(name = "Vòng quay tài sản") +
13.   scale_color_viridis_c(name = "Đòn bẩy (Assets/Equity)", option = "C") +
14.   labs( title = " Quan hệ ROA và ROE của Vinamilk (2015–2024)",
15.     x = "ROA (Lợi nhuận sau thuế / Tổng tài sản)",
16.     y = "ROE (Lợi nhuận sau thuế / Vốn chủ sở hữu)" ) +
17.   theme_minimal(base_size = 12) + theme( panel.grid.minor = element_blank(),
18.     legend.position = "right", plot.title = element_text(face = "bold"))

Giải thích  Kỹ thuật:
- Dòng 1–5: Bố cục scatter đúng; nên tính sẵn mean_roa/mean_roe rồi dùng geom_hline/vline(data=…) để tránh lặp tính.
- Dòng 6–7: Mapping size/color hợp lý; cân nhắc scale_size_area(max_size=8) (đều diện tích) và giữ method=“loess” chỉ khi đủ điểm.
- Dòng 8–9: Nhãn năm ổn; nếu nam là số (2015…), dùng label = nam thay format(). Thêm coord_cartesian(clip=“off”) để nhãn không bị cắt.
- Dòng 10–18: percent_format() ok nếu roa/roe ở thang 0–1; nếu đã là %, dùng scale=1. Có thể đặt legend.position=“top” và thêm guides(size=guide_legend(order=1), color=guide_colorbar(order=2)).
Ý nghĩa:
Giai đoạn 2015–2017: ROA đạt ~30–32%, ROE ~40–43%, phản ánh giai đoạn tăng trưởng cực thịnh.
Từ 2018–2024: cả ROA và ROE giảm dần (ROA còn ~17%, ROE ~26%), thể hiện biên lợi nhuận bị thu hẹp khi quy mô mở rộng.
Màu điểm (đòn bẩy): từ vàng (cao ~1.5) → tím (thấp ~1.3) cho thấy Vinamilk giảm sử dụng nợ qua thời gian, hướng đến cơ cấu vốn an toàn.
Kích thước điểm (vòng quay tài sản): các năm đầu lớn hơn (1.5–1.6) → chứng tỏ tài sản được khai thác hiệu quả hơn, sau giảm nhẹ còn ~1.2 khi công suất đã ổn định.

9. Heatmap tương quan các chỉ tiêu quan trọng

1. vars_corr <- c("tong_cong_tai_san",    "doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02",
2.  "loi_nhuan_sau_thue_tndn",  "debt_ratio","current_ratio","roa","roe","ros")
3. mat <- cor(select(vnm20, all_of(vars_corr)), use = "complete.obs")
4. short_names <- c( tong_cong_tai_san = "TTS", 
5.   doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02 = "DT",
6.   loi_nhuan_sau_thue_tndn = "LNST", debt_ratio = "Nợ\n/Tổng TS",
7.   current_ratio = "CR", roa = "ROA",  roe = "ROE", ros = "ROS" )
8. rownames(mat) <- short_names[rownames(mat)]
9. colnames(mat) <- short_names[colnames(mat)]
10. heat <- as.data.frame(mat) |>
11.   tibble::rownames_to_column("row") |>
12.   pivot_longer(-row, names_to = "col", values_to = "r")
13. ggplot(heat, aes(x = row, y = col, fill = r)) +
14.   geom_tile(color = "white", size = 0.4) +
15.   geom_text(aes(label = round(r, 2)), size = 3) +
16.   scale_fill_gradient2(low = "#4575b4", mid = "white", high = "#d73027",
17. midpoint = 0, limits = c(-1, 1), name = "Tương quan") +
18.   coord_equal() + labs(title = " Ma trận tương quan (rút gọn)",
19.        subtitle = "TTS – DT – LNST – CR – Debt – ROA – ROE – ROS",
20.        x = NULL, y = NULL) + theme_minimal(base_size = 11) +
21.   theme(axis.text.x = element_text(angle = 0, hjust = 0.5),
22.         panel.grid = element_blank())

Giải thích
Kỹ thuật:
- Dòng 1–3: Tính ma trận tương quan các biến tài chính, lọc dữ liệu hoàn chỉnh bằng complete.obs.
- Dòng 4–9: Rút gọn tên biến giúp biểu đồ dễ đọc, bố trí gọn gàng.
- Dòng 10–12: Chuyển ma trận sang dạng dài để ggplot xử lý.
- Dòng 13–22: Vẽ heatmap, màu đỏ–xanh thể hiện tương quan ±, bố cục đẹp và dễ so sánh.
Ý nghĩa: Các cặp ROA–ROE–ROS có hệ số r > 0.90, thể hiện hiệu quả sinh lời đồng biến rất mạnh.
Debt ratio tương quan âm mạnh với ROA, ROE (–0.7 đến –0.8) → tỷ lệ nợ tăng làm giảm hiệu suất.
TTS (tổng tài sản) tương quan âm với ROA/ROE nhưng dương với Debt → mở rộng quy mô đi kèm tăng nợ, giảm biên lợi nhuận nhẹ.
Biểu đồ giúp nhìn tổng thể cấu trúc mối quan hệ tài chính của Vinamilk một cách trực quan và dễ hiểu.

10. Phân phối ROA, ROE, ROS (2015–2024)

1. plot10_long <- vnm20 %>%
2.   select(nam, roa, roe, ros) %>%
3.   pivot_longer(-nam, names_to = "Chi_tieu", values_to = "Gia_tri") %>%
4.   mutate(Nam = format(nam, "%Y")) 
5. ggplot(plot10_long, aes(x = Chi_tieu, y = Gia_tri, fill = Chi_tieu)) + 
6.   geom_boxplot(alpha = 0.3, width = 0.6, outlier.shape = NA, color = "gray30") +   geom_jitter(aes(color = Nam), size = 3, width = 0.1, alpha = 0.9) +               stat_summary(fun = median, geom = "point", size = 3.2, color = "black") +         stat_summary(fun = mean, geom = "point", shape = 23, size = 3.2, fill = "white") +    stat_summary(fun = mean,
7.  aes(label = scales::percent(..y.., accuracy = 0.1)),
8.  geom = "label_repel", size = 3, label.size = 0,
9.  box.padding = 0.2, color = "gray25", min.segment.length = 0) + 
10.   scale_y_continuous(labels = label_percent(accuracy = 1)) +
11.   scale_fill_manual(values = c(roa = "#F29E9E", roe = "#9ED0A9", ros = "#9EBCF2")) +  scale_color_viridis_d(option = "plasma", begin = 0, end = 0.9) +          labs(
12.     title = " Phân phối ROA – ROE – ROS theo năm (2015–2024)",
13.  subtitle = "Hộp màu theo chỉ tiêu; mỗi chấm tròn là một năm;\n chấm đen = trung vị, hình thoi = trung bình", x = NULL, y = "Giá trị (%)", color = "Năm" ) +
14.   theme_minimal(base_size = 12) + theme(panel.grid.minor = element_blank())

Giải thích
Kỹ thuật:
- Dòng 1–4: Chọn ROA/ROE/ROS, pivot_longer đúng; tạo nhãn năm. Nếu nam là số (2015…), dùng Nam = as.character(nam) thay vì format().
- Dòng 5–6: Boxplot + jitter + median/mean rõ; outlier.shape=NA tránh trùng với jitter. Có thể thêm position_jitter(width=0.1, height=0) để kiểm soát nhiễu.
- Dòng 7–11: Nhãn mean dạng % ổn khi ROA/ROE/ROS ở thang 0–1; nếu đã là %, bỏ label_percent() (hoặc chia 100 trước). Có thể thêm expand = expansion(mult = c(0, .05)) và legend.position=“top”.
- Dòng 12–14: Tiêu đề/phụ đề rõ; theme_minimal() gọn, tắt minor grid hợp lý. Cân nhắc scale_y_continuous(labels=label_percent(accuracy=0.1)) để nhất quán với nhãn mean.
Ý nghĩa:
Mỗi năm là một màu khác nhau, giúp nhận diện nhanh xu hướng biến động qua thời gian.
ROE vẫn nổi bật cao nhất (trung bình ~34.4%), ROA khoảng 23.4%, ROS ~18.8%.
Các năm đầu (màu sáng hơn, 2015–2017) tập trung ở phía trên → hiệu quả cao, trong khi các năm sau (màu trầm hơn, 2021–2024) nằm thấp hơn → lợi nhuận suy giảm nhẹ nhưng ổn định.

11. Quan hệ giữa các chỉ tiêu tài chính chính yếu

1. plot11_data <- vnm20 %>%  select(nam, debt_ratio, roa, current_ratio, tong_cong_tai_san) %>% mutate(Nam = format(nam, "%Y")) 
2. ggplot(plot11_data, aes(x = debt_ratio, y = roa)) +
3. geom_point(aes(size = tong_cong_tai_san, color = current_ratio), alpha = 0.8) +
4. geom_smooth(method = "lm", se = FALSE, color = "gray30", linetype = "dashed") +
5.   geom_text_repel( aes(label = Nam), size = 3.2, color = "gray20", 
6.     max.overlaps = Inf, box.padding = 0.3, point.padding = 0.4, segment.color = "gray60" ) +
7. scale_x_continuous(labels = label_percent(accuracy = 0.1, decimal.mark = ",")) +
8. scale_y_continuous(labels = label_percent(accuracy = 0.1, decimal.mark = ",")) +
9.   scale_color_viridis_c(option = "plasma", begin = 0, end = 1) +
10.   scale_size_continuous(  range = c(3, 9), labels = label_number(accuracy = 0.1, big.mark = ".", decimal.mark = ",", scale_cut = cut_si("B")) ) +
11.   labs( title = "Biểu đồ 11. Quan hệ giữa Tỷ lệ nợ  và ROA",
12.     subtitle = "Màu: Current ratio | Kích thước: Tổng tài sản\n Đường gạch: xu hướng hồi quy",  x = "Tỷ lệ nợ trên tổng nguồn vốn (%)", y = "ROA (Lợi nhuận sau thuế / Tổng tài sản, %)", color = "Current ratio",  size  = "Tổng tài sản") +
13.   theme_minimal(base_size = 12) +
14.   theme(legend.position = "right", panel.grid.minor = element_blank())

Giải thích
Kỹ thuật:
- Dòng 1: Chọn biến chính (năm, debt_ratio, roa, current_ratio, tài sản), tạo biến nhãn năm để hiển thị.
- Dòng 2–4: Vẽ scatter ROA–nợ, thêm kích thước theo tổng tài sản, màu theo current_ratio, đường hồi quy rõ.
- Dòng 5–6: Nhãn năm dùng geom_text_repel hợp lý, tránh chồng chữ, dễ đọc.
- Dòng 7–14: Chuẩn hoá trục %, màu plasma, chú thích rõ ràng; theme tối giản giúp biểu đồ sạch, cân đối.  Ý nghĩa:
Biểu đồ cho thấy mối quan hệ ngược chiều rõ rệt giữa tỷ lệ nợ và hiệu quả sinh lời tài sản (ROA).
Khi tỷ lệ nợ tăng dần từ khoảng 25% lên 33%, ROA giảm từ hơn 30% xuống quanh 17–19%.
Những năm có khả năng thanh toán cao hơn thường đạt ROA tốt hơn, thể hiện nền tài chính lành mạnh hỗ trợ hiệu quả kinh doanh.
Ngược lại, giai đoạn gần đây tuy quy mô tài sản mở rộng nhưng ROA giảm, cho thấy việc sử dụng vốn chưa tối ưu.

12. Quan hệ ROA – ROS

1. plot12_data <- vnm20 %>%  select(nam, roa, ros, asset_turnover) %>%
2.   mutate(Nam = format(nam, "%Y")) 
3. ggplot(plot12_data, aes(x = roa, y = ros)) +
4.   geom_point(aes(size = asset_turnover, color = roa), alpha = 0.8) + 
5. geom_smooth(method = "lm", se = FALSE, color = "gray40", linetype = "dashed") +
6. geom_text_repel(aes(label = Nam), size = 3, color = "gray25") +  
7. scale_x_continuous(labels = label_percent(accuracy = 0.1, decimal.mark = ",")) +
8. scale_y_continuous(labels = label_percent(accuracy = 0.1, decimal.mark = ",")) +
9.   scale_color_viridis_c(option = "plasma", begin = 0.1, end = 0.9) +
10.   scale_size_continuous(range = c(3, 8), 
11. labels = label_number(accuracy = 0.1, big.mark = ".", decimal.mark = ",")) +
12.   labs( title = "Quan hệ giữa ROA và ROS của Vinamilk (2015–2024)",
13.     subtitle = "Kích thước: Vòng quay tài sản (Asset turnover); màu: mức ROA; đường gạch: xu hướng hồi quy",  x = "ROA (Lợi nhuận sau thuế / Tổng tài sản, %)", y = "ROS (Lợi nhuận sau thuế / Doanh thu thuần, %)", size = "Vòng quay tài sản", color = "ROA" ) + theme_minimal(base_size = 12) +
14.   theme(legend.position = "right", panel.grid.minor = element_blank())

Giải thích
Kỹ thuật:
- Dòng 1–2: Lọc biến ROA, ROS, asset_turnover; tạo nhãn năm để hiển thị.
- Dòng 3–5: Vẽ scatter ROA–ROS, thêm kích thước theo asset_turnover và đường hồi quy tuyến tính rõ ràng.
- Dòng 6–8: Nhãn năm với geom_text_repel tránh chồng; trục định dạng phần trăm hợp lý.
- Dòng 9–14: Màu plasma và kích thước hợp lý; tiêu đề, phụ đề và theme rõ, dễ đọc, bố cục cân đối.
Ý nghĩa: Biểu đồ thể hiện mối quan hệ cùng chiều chặt chẽ giữa ROA và ROS của Vinamilk giai đoạn 2015–2024.
Khi ROA tăng từ khoảng 20% lên hơn 30%, ROS cũng tăng tương ứng từ 15% lên hơn 25% → cho thấy doanh nghiệp duy trì hiệu quả hoạt động và biên lợi nhuận ổn định.
Các năm 2017–2019 đạt mức cao nhất, phản ánh giai đoạn sinh lời mạnh và sử dụng tài sản hiệu quả.
Từ 2022–2024, cả hai chỉ tiêu giảm nhẹ, cho thấy hiệu suất đang chậm lại nhưng vẫn giữ được tính cân đối và bền vững trong cấu trúc tài chính.

13. Bản đồ DuPont (ROS × Asset turnover → ROE)

1. p13 <- vnm20 %>% transmute(Nam = format(nam, "%Y"), ros, asset_turnover, leverage, roe) 
2. L0 <- median(p13$leverage, na.rm = TRUE)
3. xseq <- seq(min(p13$asset_turnover, na.rm=TRUE),             max(p13$asset_turnover, na.rm=TRUE), length.out = 100)
4. iso <- expand.grid(roe = c(0.25, 0.30, 0.35, 0.40), asset_turnover = xseq) |>
5.   mutate(ros = roe / (asset_turnover * L0),
6.  nhan = paste0(round(roe*100), "% ROE")) 
7. ggplot(p13, aes(asset_turnover, ros)) +
8.   geom_point(aes(size = roe, color = leverage), alpha = 0.8) +                 
9. geom_smooth(method = "lm", se = FALSE, color = "gray40", linetype = "dashed") + 
10.   geom_path(data = iso, aes(y = ros, group = nhan),
11.             color = "gray60", linetype = "dotted") +                           
12.   geom_text_repel(aes(label = Nam), size = 3, color = "gray20") +              
13.   geom_text(data = iso |> dplyr::group_by(nhan) |> dplyr::slice_tail(n = 1),
14.          aes(y = ros, label = nhan), hjust = 1.1, color = "gray40", size = 3) +
15.   scale_x_continuous("Vòng quay tài sản (lần)",labels = label_number(accuracy = 0.1,  big.mark = ".", decimal.mark = ",")) + scale_y_continuous("ROS (LNST/Doanh thu, %)", labels = label_percent(accuracy = 0.1,                           big.mark = ".", decimal.mark = ",")) +  scale_color_viridis_c(option = "plasma") + labs(title = "Biểu đồ 13. Bản đồ DuPont: ROS × Vòng quay tài sản → ROE (2015–2024)", subtitle = paste0("Đường chấm: các mức ROE tham chiếu (L = ",
16.    round(L0, 2), "×)")) +   theme_minimal(base_size = 12)

Giải thích
Kỹ thuật:
- Dòng 1–2: Chuẩn bị dữ liệu và lấy L0 = median(leverage); hợp lý cho bản đồ DuPont khi giả định đòn bẩy cố định (nhớ đảm bảo leverage > 0).
- Dòng 3–6: Tạo lưới xseq và đường đẳng ROE bằng công thức ros = roe/(asset_turnoverL0); nếu ROE/ROS đang ở dạng %, đổi về tỷ lệ trước khi tính để tránh sai số/∞.
- Dòng 7–12: Scatter + smooth + nhãn năm rõ; có thể dùng scale_size_area(max_size=9) và đặt max.overlaps=Inf/point.padding nhỏ hơn để giảm chồng nhãn.
- Dòng 13–16: Gắn nhãn cuối đường đẳng ROE gọn; định dạng trục % nhất quán, thêm expand = expansion(mult=c(0,.05)) và legend.position=“top”/guides(size=guide_legend(order=1), color=guide_colorbar(order=2)) để bố cục sạch hơn. 
Ý nghĩa:*
Mối quan hệ ROS–AssetTurnover dương: đường hồi quy dốc lên → khi biên lợi nhuận cao hoặc quay vòng tài sản nhanh, ROE có xu hướng tốt hơn.
Giai đoạn cao điểm 2015–2018: điểm các năm này nằm gần/nhỉnh hơn đường 35–40% ROE. Ví dụ 2017 xấp xỉ ROS ~21–22%, vòng quay ~1.5 lần, đòn bẩy ~1.45 ⇒ ROE ≈ 0.21×1.5×1.45 ≈ 46% (báo mức rất cao trên bản đồ).
Sau 2019: nhiều điểm (2020–2024) dịch xuống trái → ROS giảm và vòng quay chậm lại, đẩy ROE về vùng 25–30% dù đòn bẩy gần như không tăng đáng kể (màu gần nhau).

14. Quan hệ giữa Dòng tiền hoạt động & Lợi nhuận sau thuế

1. p14 <- vnm20 %>%
2.   transmute(
3.     Nam = format(nam, "%Y"),
4.     cfo = luu_chuyen_tien_thuan_tu_hoat_dong_kinh_doanh,
5.     profit = loi_nhuan_sau_thue_tndn)
6. ggplot(p14, aes(x = profit, y = cfo)) +
7.   geom_point(aes(color = Nam), size = 4, alpha = 0.8) +      
8.  geom_smooth(method = "lm", se = FALSE, color = "gray40", linetype = "dashed") +
9.   geom_text_repel(aes(label = Nam), size = 3, color = "black") +              
10.   geom_abline(slope = 1, intercept = 0, color = "blue", linetype = "dotted") +
11.   geom_segment(aes(x = profit, y = profit, xend = profit, yend = cfo),
12.  color = "gray70", linetype = "dotted") +                       
13.   scale_x_continuous("Lợi nhuận sau thuế (tỷ đồng)",
14.  labels = label_number(big.mark = ".", decimal.mark = ",")) +
15.   scale_y_continuous("Dòng tiền từ HĐKD (tỷ đồng)",
16.  labels = label_number(big.mark = ".", decimal.mark = ",")) +
17.   labs( title = "Quan hệ giữa Lợi nhuận sau thuế và\n Dòng tiền hoạt động", subtitle = "Đường chấm xanh: CFO = LNST;\n đường gạch xám: xu hướng; màu: theo năm" ) + theme_minimal(base_size = 12) +
18.   theme(legend.position = "right", panel.grid.minor = element_blank())

Giải thích
Kỹ thuật:  - Dòng 1–5: Chuẩn bị dữ liệu CFO–LNST; bảo đảm cùng đơn vị (tỷ đồng) và kiểu số (as.numeric nếu cần).
Dòng 6–8: Scatter màu theo năm + xu hướng lm; có thể thử method = MASS::rlm nếu có outlier.
- Dòng 9–12: Nhãn năm + đường tham chiếu 45° và đoạn chênh lệch; dùng coord_equal() để đường slope = 1 có ý nghĩa trực quan, thêm max.overlaps = Inf. - Dòng 13–16: Nhãn trục rõ; cân nhắc scales::label_number_si() (k, M, B) hoặc thêm expand = expansion(mult = c(0, .05)).
- Dòng 17–18: Tiêu đề/legend gọn; có thể đặt legend.position = “top” và dùng scale_color_viridis_d() cho bảng màu dễ đọc.
Ý nghĩa:  Biểu đồ cho thấy dòng tiền từ hoạt động kinh doanh (CFO) có mối quan hệ rất chặt chẽ với lợi nhuận sau thuế (LNST) của Vinamilk.
Phần lớn các điểm nằm gần hoặc trên đường CFO = LNST, chứng tỏ lợi nhuận được hỗ trợ bởi dòng tiền thật, không phải ghi nhận kế toán.
Đặc biệt, 2018–2020 CFO cao hơn rõ rệt so với LNST → khả năng thu hồi tiền nhanh, chất lượng lợi nhuận cao.
Các năm 2022–2023 CFO thấp hơn LNST → phản ánh sức tiêu thụ giảm và chu kỳ thu tiền dài hơn, nhưng không đáng lo.

15. Mối quan hệ ROA – CFO (2015–2024)

1. p15 <- vnm20 %>%  transmute( Nam = format(nam, "%Y"), roa = roa,
2.     cfo = luu_chuyen_tien_thuan_tu_hoat_dong_kinh_doanh / 1000  )
3. ggplot(p15, aes(x = roa, y = cfo)) +
4.   geom_point(aes(color = Nam), size = 4, alpha = 0.8) +                
5. geom_smooth(method = "lm", se = FALSE, color = "gray40", linetype = "dashed") + 
6.   geom_text_repel(aes(label = Nam), size = 3, color = "black") +       
7.   geom_hline(yintercept = mean(p15$cfo), color = "blue", linetype = "dotted") +
8.   geom_vline(xintercept = mean(p15$roa), color = "red", linetype = "dotted") + 
9.   scale_x_continuous("ROA (Lợi nhuận sau thuế / Tổng tài sản, %)",
10.                  labels = label_percent(accuracy = 0.1, decimal.mark = ",")) +
11.   scale_y_continuous("Dòng tiền từ HĐKD (nghìn tỷ đồng)",
12.                    labels = label_number(big.mark = ".", decimal.mark = ",")) +
13.   labs(title = "Biểu đồ 15. Quan hệ giữa ROA và Dòng tiền hoạt động của Vinamilk\n (2015–2024)", subtitle = "Đường chấm đỏ: ROA TB; chấm xanh: CFO TB; đường gạch: xu hướng hồi quy", color = "Năm" ) + theme_minimal(base_size = 12) +
14.   theme(legend.position = "right", panel.grid.minor = element_blank())

Giải thích
Kỹ thuật:
- Dòng 1–2: Tạo dataset gồm năm, ROA và CFO (quy đổi về nghìn tỷ để dễ đọc).
- Dòng 3–6: Vẽ scatter ROA–CFO, màu theo năm, thêm đường hồi quy và nhãn năm rõ ràng.
- Dòng 7–8: Thêm hai đường trung bình (đỏ – ROA, xanh – CFO) giúp xác định vị trí tương đối các năm.
- Dòng 9–14: Trục và nhãn rõ ràng, định dạng hợp lý; theme tối giản giúp biểu đồ cân đối, dễ so sánh.
Ý nghĩa:
Biểu đồ thể hiện mối quan hệ giữa hiệu quả sinh lời (ROA) và khả năng tạo tiền thật (CFO) của Vinamilk giai đoạn 2015–2024.
Hầu hết các năm nằm gần trung tâm hai đường trung bình → ROA ổn định, CFO duy trì vững.
Năm 2019–2020 nổi bật với ROA cao và CFO mạnh, phản ánh chất lượng lợi nhuận tốt.
Trong khi đó, 2022–2023 cho thấy ROA và CFO cùng giảm, biểu hiện giai đoạn điều chỉnh nhẹ, nhưng 2024 đã phục hồi.
Tổng thể, Vinamilk vẫn giữ khả năng chuyển hóa lợi nhuận thành tiền mặt tốt và bền vững.

16. trực quan hóa tỷ lệ nợ

1. ggplot(vnm20, aes(x = nam, y = debt_ratio)) + geom_point(color = "darkred", size = 3) + geom_line(color = "steelblue", linewidth = 1.2) +
2.   geom_smooth(method = "lm", se = FALSE, color = "darkgreen", linetype = "dashed") +  geom_text(
3.     data = subset(vnm20, debt_ratio == max(debt_ratio, na.rm = TRUE)),
4.   aes(label = round(debt_ratio, 2)), vjust = -1, color = "black", size = 4  ) +
5.   labs( title = "Tỷ lệ nợ (Debt Ratio) qua các năm",
6.     subtitle = "Dữ liệu: Công ty VNM",  x = "Năm",    y = "Tỷ lệ nợ",
7.     caption = "Nguồn: Báo cáo tài chính VNM"  ) +  theme_minimal(base_size = 14)

Giải thích
Kỹ thuật:   - Dòng 1: Thiết lập trục năm–tỷ lệ nợ; dùng điểm và đường nối thể hiện xu hướng theo thời gian.
- Dòng 2: Thêm đường hồi quy tuyến tính (màu xanh đậm, gạch) để làm nổi bật xu hướng dài hạn.
- Dòng 3–4: Gắn nhãn giá trị cực đại giúp nhấn mạnh năm có tỷ lệ nợ cao nhất. - Dòng 5–7: Tiêu đề, phụ đề, chú thích rõ; theme_minimal gọn gàng, đảm bảo đủ 5 lớp trực quan.
Ý nghĩa:
Biểu đồ cho thấy tỷ lệ nợ của Vinamilk tăng đều qua các năm, từ khoảng 24% năm 2016 lên hơn 34% năm 2024.
Xu hướng tuyến tính (đường xanh lá) khẳng định mức gia tăng ổn định trong đòn bẩy tài chính, phù hợp với giai đoạn mở rộng quy mô.
Các điểm dữ liệu không lệch nhiều so với đường xu hướng → phản ánh chính sách nợ ổn định, kiểm soát tốt.
Giá trị cực đại năm 2024 (0.34) là đỉnh tỷ lệ nợ, song vẫn ở mức an toàn so với chuẩn ngành, cho thấy Vinamilk quản trị vốn cân đối giữa vay nợ và vốn chủ sở hữu.

17. Cấu trúc tài sản của Vinamilk (2015–2024)

1. df_asset <- vnm %>%  transmute( Nam = as.numeric(format(as.Date(nam), "%Y")),  
2.     Tai_san_ngan_han = suppressWarnings(parse_number(as.character(tai_san_ngan_han))),
3.     Tai_san_co_dinh_huu_hinh = suppressWarnings(parse_number(as.character(tai_san_co_dinh_huu_hinh))),   Tong_tai_san = suppressWarnings(parse_number(as.character(tong_cong_tai_san)))
4.   ) %>%
5.   pivot_longer(cols = c(Tai_san_ngan_han, Tai_san_co_dinh_huu_hinh, Tong_tai_san), names_to = "Khoan_muc", values_to = "Gia_tri") %>%
6.   filter(!is.na(Gia_tri))
7. ggplot(df_asset, aes(x = Nam, y = Gia_tri / 1000, color = Khoan_muc, group = Khoan_muc)) +  geom_line(linewidth = 1) +  geom_point(size = 3) +
8.   geom_text(aes(label = comma(round(Gia_tri / 1000, 0))), vjust = -0.6, size = 3, show.legend = FALSE) +
9.   scale_x_continuous(breaks = df_asset$Nam) +  # chỉ hiện số năm
10.   scale_color_brewer(palette = "Set2") +
11.   labs( title = "Cấu trúc tài sản của Vinamilk (2015–2024)", subtitle = "So sánh Tài sản ngắn hạn, Tài sản cố định hữu hình\n và Tổng tài sản (nghìn tỷ đồng)", x = "Năm", y = "Giá trị (nghìn tỷ đồng)", color = "Khoản mục"  ) +
12.   theme_minimal(base_size = 12)

Giải thích
Kỹ thuật:
- Dòng 1–3: Tạo năm số và parse số tiền an toàn; nếu nam đã là năm (2015…), bỏ as.Date() và dùng as.integer(nam). Có thể across(where(is.character), readr::parse_number) gọn hơn.
Dòng 4–6: pivot_longer đúng; nên chuẩn hóa nhãn bằng recode(Khoan_muc=…) và lọc NA hợp lý.
- Dòng 7–8: Line + point + nhãn số rõ; cân nhắc scales::label_number_si() hoặc ggrepel để tránh chồng chữ, và coord_cartesian(clip=“off”).
- Dòng 9–10: breaks = df_asset\(Nam dễ lặp; dùng breaks = unique(df_asset\)Nam), thêm expand = expansion(mult=c(0,.02)). Palette “Set2” OK (cần RColorBrewer). - Dòng 11–12: Nhãn/tiêu đề ổn; có thể đặt legend.position=“top” và nêu đơn vị ở trục (nghìn tỷ) để khỏi chia trong nhiều chỗ.  Ý nghĩa:
Tổng tài sản tăng mạnh từ khoảng 25 nghìn tỷ (2015) lên hơn 55 nghìn tỷ (2024) → phản ánh quy mô doanh nghiệp mở rộng liên tục.
Tài sản ngắn hạn tăng nhanh, chiếm tỷ trọng lớn trong tổng tài sản → cho thấy khả năng thanh khoản cao và chính sách quản trị vốn lưu động hiệu quả.
Tài sản cố định hữu hình tăng chậm hơn → hàm ý đầu tư dài hạn được kiểm soát, tránh dàn trải.

18. Tỷ lệ nợ & ROE

1. df <- vnm20 %>%   transmute(Nam = format(nam, "%Y"), debt_ratio, roe)
2. ggplot(df, aes(x = debt_ratio, y = roe)) +
3.   geom_point(color = "darkorange", size = 3, alpha = .8) +         
4.   geom_smooth(method = "lm", se = FALSE, linetype = "dashed") +    
5.   geom_text_repel(aes(label = Nam), size = 3, max.overlaps = Inf) +# 
6.   geom_vline(xintercept = mean(df$debt_ratio, na.rm = TRUE), linetype = "dotted") + 
7.   geom_hline(yintercept = mean(df$roe, na.rm = TRUE), linetype = "dotted") +  
8.   scale_x_continuous(labels = label_percent(accuracy = 0.1, decimal.mark = ","), name = "Tỷ lệ nợ (Debt ratio)") +
9.   scale_y_continuous(labels = label_percent(accuracy = 0.1, decimal.mark = ","), name = "ROE") + labs(title = "Quan hệ giữa tỷ lệ nợ và ROE (2015–2024)",
10.        subtitle = "Hai đường trung bình chia 4 vùng hiệu quả") +
11.   theme_minimal(base_size = 12)

Giải thích
Kỹ thuật:
- Dòng 1: Chuẩn bị dữ liệu đúng; Nam = format(nam, “%Y”) ổn nếu nam là date/POSIXct, còn nếu đã là số thì dùng as.character(nam).
- Dòng 2–4: Scatter + geom_smooth(method=“lm”) hợp lý để thấy xu hướng; màu điểm đặt trực tiếp nên không tạo legend — đúng với mục tiêu gọn.
- Dòng 5: geom_text_repel(max.overlaps = Inf) cho đủ nhãn; để đỡ chồng, thêm point.padding = .2, box.padding = .2 (không cần đổi cấu trúc).
- Dòng 6–7: Dùng mean(df$…) ngay trong geom_vline/hline là đúng (tính một lần trước khi vẽ, không lặp theo điểm/panel).
- Dòng 8–11: label_percent() chuẩn nếu debt_ratio và roe ở thang 0–1 (trường hợp này phù hợp); tiêu đề/phụ đề rõ, theme_minimal() gọn gàng.
Ý nghĩa:
Biểu đồ cho thấy mối quan hệ nghịch biến giữa tỷ lệ nợ và ROE của Vinamilk giai đoạn 2015–2024.
Khi tỷ lệ nợ tăng, ROE có xu hướng giảm, cho thấy hiệu quả sử dụng đòn bẩy tài chính giảm dần.
Các năm 2015–2017 có nợ thấp, ROE cao → cơ cấu vốn an toàn, lợi nhuận tốt.
Ngược lại, 2021–2023 ghi nhận nợ cao và ROE giảm mạnh → áp lực tài chính gia tăng.

19. Quan hệ giữa ROA và ROS (2015–2024)

1. df <- vnm20 %>%
2.   mutate(Nam = as.character(format(nam, "%Y"))) 
3. ggplot(df, aes(x = ros, y = roa, label = Nam)) +
4.   geom_point(color = "tomato", size = 3) +   
5.   geom_smooth(method = "lm", se = FALSE, linetype = "dashed",
6.               color = "blue", linewidth = 1.2) +   
7.   geom_text_repel(size = 3.5, max.overlaps = 15) + 
8.   geom_vline(xintercept = mean(df$ros, na.rm = TRUE),
9.              linetype = "dotted", color = "gray40") + 
10.   geom_hline(yintercept = mean(df$roa, na.rm = TRUE),
11.              linetype = "dotted", color = "gray40") + 
12.   labs(title = "Biểu đồ 19. Quan hệ giữa ROA và ROS (2015–2024)",
13.        subtitle = "Hai đường trung bình chia 4 vùng hiệu quả sinh lời",
14.        x = "ROS (%)", y = "ROA (%)") +   theme_minimal()

Giải thích
Kỹ thuật:
- Dòng 1–2: Tạo nhãn năm đúng; nếu nam đã là số thì dùng as.character(nam) gọn hơn.
- Dòng 3–6: Scatter ROA~ROS + lm gạch xanh rõ xu hướng; ổn.
- Dòng 7–11: text_repel hợp lý; nếu còn chồng, thêm point.padding=.2. Hai đường mean chia 4 vùng đúng mục tiêu.
- Dòng 12–14: Ghi “(%)” nhưng trục chưa scale; nếu ROA/ROS ở thang 0–1, thêm scale_*_continuous(labels=label_percent()), còn nếu đã là %, bỏ “(%)”.
Ý nghĩa:
Biểu đồ thể hiện mối quan hệ thuận chiều giữa tỷ suất sinh lời trên tài sản (ROA) và tỷ suất lợi nhuận trên doanh thu (ROS) của Vinamilk giai đoạn 2015–2024.
Khi ROS tăng → ROA cũng tăng, cho thấy hiệu quả quản trị chi phí và khả năng sinh lời từ doanh thu cao. Giai đoạn 2015–2017 nổi bật với ROS và ROA cao, phản ánh biên lợi nhuận mạnh và tài sản sử dụng hiệu quả.
Các năm 2021–2023 giảm nhẹ cả ROS và ROA → giai đoạn biên lợi nhuận co hẹp, hiệu quả sử dụng tài sản suy yếu.
2024 bắt đầu hồi phục nhẹ, hàm ý tín hiệu tích cực trở lại trong hiệu quả sinh lời.

20. Quan hệ giữa Vốn chủ sở hữu và Tổng tài sản (2015–2024)

1. df <- vnm20 %>%  transmute(  Nam = format(as.Date(nam), "%Y"),   
2.     Von_chu_so_huu = von_chu_so_huu,  No_phai_tra = no_phai_tra ) %>%
3.   pivot_longer(-Nam, names_to = "Khoan_muc", values_to = "Gia_tri")
4. ggplot(df, aes(x = Nam, y = Gia_tri, fill = Khoan_muc)) +
5.   geom_col(position = "dodge") +  geom_text(aes(label = round(Gia_tri, 0)), 
6.   position = position_dodge(width = 1), hjust = 1, vjust = 0.5, color = "black", size = 3, angle = 90) +  geom_hline(yintercept = mean(df$Gia_tri), linetype = "dotted") +  scale_fill_brewer(palette = "Set2") +                             
7.   labs(title = " Cấu trúc vốn: Vốn chủ sở hữu và Nợ phải trả (2015–2024)", subtitle = "So sánh quy mô vốn và nợ qua các năm", x = "Năm", y = "Giá trị (tỷ đồng)", fill = "Khoản mục") + theme_minimal(base_size = 12)

Giải thích Kỹ thuật:
-bDòng 1–3: Chuẩn bị dữ liệu đúng; dùng as.character(nam) nếu nam là số.
-bDòng 4–5: Cột “dodge” và nhãn hiển thị rõ; nên để angle=0 để dễ đọc hơn.
-bDòng 6: Đường trung bình chung hợp lý; nếu muốn riêng từng nhóm thì tính theo “Khoan_muc”.
-bDòng 7: Biểu đồ rõ ràng, màu “Set2” hài hòa, theme tối giản dễ nhìn.
Ý nghĩa: Nợ phải trả luôn chiếm tỷ trọng cao hơn vốn chủ sở hữu, cho thấy Vinamilk sử dụng đòn bẩy tài chính khá lớn.
Giai đoạn 2015–2018: nợ tăng nhanh, song vốn chủ sở hữu cũng mở rộng đáng kể → phản ánh giai đoạn tăng trưởng vốn hóa mạnh.
Giai đoạn 2019–2023: quy mô nợ đạt đỉnh, trong khi vốn chủ sở hữu tăng chậm → có thể là dấu hiệu tái cấu trúc tài chính hoặc ổn định tăng trưởng.
Năm 2024: nợ giảm nhẹ, vốn chủ sở hữu duy trì ổn định → hàm ý xu hướng giảm rủi ro tài chính.