## Warning: package 'showtext' was built under R version 4.5.2
## Loading required package: sysfonts
## Warning: package 'sysfonts' was built under R version 4.5.2
## Loading required package: showtextdb
## Warning: package 'showtextdb' was built under R version 4.5.2
library(sysfonts)
showtext_auto()
font_add(family = "TimesVN", regular = "C:/Windows/Fonts/times.ttf")
theme_set(theme_minimal(base_family = "TimesVN"))Trong suốt quá trình thực hiện bài luận môn Ngôn ngữ lập trình, nhóm chúng em xin bày tỏ lòng biết ơn sâu sắc đến thầy Trần Mạnh Tường, người đã tận tình hướng dẫn, cung cấp kiến thức và định hướng cho chúng em trong suốt học kỳ vừa qua. Những bài giảng, góp ý và sự hỗ trợ quý báu của thầy là nền tảng quan trọng giúp chúng em hoàn thành bài luận này một cách hiệu quả và đúng hướng.
Chúng em ý thức rằng bài luận này khó tránh khỏi những thiếu sót nhất định do hạn chế về thời gian, kinh nghiệm và kiến thức thực tiễn. Rất mong nhận được những nhận xét và góp ý chân thành từ thầy để nhóm có thể rút kinh nghiệm, hoàn thiện bản thân và nâng cao hơn nữa năng lực học tập trong tương lai.
Cuối cùng, nhóm xin gửi lời tri ân sâu sắc đến thầy vì đã luôn tận tâm giảng dạy, truyền đạt kiến thức và truyền cảm hứng trong suốt quá trình học tập. Kính chúc thầy sức khỏe dồi dào, tinh thần nhiệt huyết và nhiều thành công trên con đường sự nghiệp của mình.
Bài tiểu luận bao gồm 2 phần:
Phần 1: Phân tích dữ liệu tội phạm tại Los Angeles (Crime Data) giai đoạn 2020 - 2023
Phần 2: Phân tích dữ liệu tài chính Công ty Cổ phần Sữa Việt Nam (VNM) giai đoạn 2015 - 2024
Trong bối cảnh xã hội hiện đại, tội phạm không chỉ là vấn đề pháp lý mà còn là một hiện tượng xã hội phản ánh nhiều chiều cạnh của đời sống kinh tế, chính trị và văn hóa. Los Angeles – một trong những đô thị lớn nhất và đa dạng nhất của Hoa Kỳ – luôn được xem là “tấm gương phản chiếu” của các biến động xã hội, đặc biệt trong giai đoạn 2020–2023.nana
Đây là giai đoạn chịu ảnh hưởng nặng nề bởi đại dịch COVID-19, khủng hoảng kinh tế – việc làm, thay đổi chính sách an ninh công cộng và sự phát triển nhanh của công nghệ. Những yếu tố này tác động mạnh đến hành vi con người, mô hình cư trú, cũng như cấu trúc xã hội từ đó làm thay đổi bản chất và xu hướng của tội phạm.
Việc phân tích đa chiều về tội phạm tại Los Angeles không chỉ giúp nhận diện được xu hướng biến động theo thời gian và không gian, mà còn góp phần đánh giá các yếu tố xã hội – kinh tế – chính sách có ảnh hưởng đến tình hình an ninh đô thị. Đề tài này mang tính thực tiễn cao, hỗ trợ cơ quan quản lý, nhà nghiên cứu, và cộng đồng trong việc hoạch định các giải pháp phòng ngừa tội phạm và đảm bảo an ninh xã hội bền vững.
Đối tượng nghiên cứu:
Tình hình tội phạm tại thành phố Los Angeles, bao gồm các loại hình tội phạm (bạo lực, trộm cắp, xâm hại, ma túy, gian lận,….) và các yếu tố xã hội có ảnh hưởng.
Phạm vi nghiên cứu:
Không gian: Thành phố Los Angeles, bang California, Hoa Kỳ.
Thời gian: Từ năm 2020 đến năm 2023 – giai đoạn có biến động mạnh về kinh tế – xã hội do đại dịch và thay đổi chính sách.
Phạm vi dữ liệu: Bộ dữ liệu Los Angeles Crime Data do LAPD (Los Angeles Police Department) công bố công khai, kết hợp với các nguồn dữ liệu phụ trợ như dân số, thu nhập bình quân, tỷ lệ thất nghiệp và dữ liệu COVID-19.
Bộ dữ liệu “Crime Data from 2020 to Present” được thu thập từ Sở Cảnh sát Los Angeles (LAPD), phản ánh tình hình tội phạm tại thành phố Los Angeles trong giai đoạn từ năm 2020 đến năm 2024.
Dữ liệu được công khai thông qua cổng dữ liệu mở của thành phố, cung cấp thông tin chi tiết về từng vụ án hình sự đã được ghi nhận.
Sau khi kiểm tra và làm sạch, bộ dữ liệu còn lại 760.049 quan sát (dòng dữ liệu), tương ứng với các vụ phạm tội riêng lẻ và 12 biến (cột dữ liệu) chính phục vụ phân tích, bao gồm: date, area, district, severity, crime_type, age, sex, premise_type, status, lalat, lon, year.
Mỗi dòng trong bộ dữ liệu thể hiện một sự kiện phạm tội cụ thể bao gồm thông tin về loại tội phạm, khu vực xảy ra, thời gian, giới tính và độ tuổi của nạn nhân, cùng với toạ độ địa lý của vụ án.
Giải thích kỹ thuật:
library(readxl): nạp gói readxl – một thư viện trong R dùng để đọc dữ liệu từ file Excel (.xls hoặc .xlsx).
read_excel("..."): đọc toàn bộ dữ liệu từ đường dẫn được chỉ định và lưu vào đối tượng df.
Hàm này tự động nhận diện kiểu dữ liệu của từng cột (số, ký tự, ngày,...).
Kết quả là một bảng dữ liệu (data frame) chứa toàn bộ thông tin về các vụ phạm tội tại Los Angeles.
Giải thích kỹ thuật:
head(df) hiển thị 6 dòng đầu tiên trong bộ dữ liệu df.
tail(df) hiển thị 6 dòng cuối cùng trong cùng bộ dữ liệu.
Hai hàm này giúp ta xem nhanh cấu trúc dữ liệu — gồm các biến có trong tập dữ liệu, tên cột, kiểu dữ liệu (số, ký tự, ngày tháng) và cách dữ liệu được lưu trữ. Đây là bước cơ bản để đảm bảo dữ liệu đã được đọc đúng định dạng.
## [1] 944235
## [1] 28
Giải thích kỹ thuật:
nrow(df) trả về số lượng dòng trong bộ dữ liệu df, tức là tổng số vụ án được ghi nhận.
ncol(df) trả về số lượng cột, tức là tổng số biến mô tả thông tin của mỗi vụ án.
Hai hàm này giúp ta nắm quy mô dữ liệu, biết được số quan sát (records) và số đặc trưng (variables). Đây là thông tin quan trọng trước khi thực hiện các bước làm sạch hoặc phân tích, nhằm xác định khối lượng xử lý và khả năng lưu trữ.
Ý nghĩa thống kê:
Kết quả cho thấy bộ dữ liệu ghi nhận 944.235 vụ án với 28 đặc trưng mô tả cho mỗi vụ (chẳng hạn như thời gian, địa điểm, loại tội phạm, độ tuổi, giới tính,…).
## [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:
Lệnh names(df) giúp liệt kê toàn bộ tên các biến (cột) trong bộ dữ liệu.
## tibble [944,235 × 28] (S3: tbl_df/tbl/data.frame)
## $ DR_NO : num [1:944235] 1.90e+08 2.00e+08 2.00e+08 2.01e+08 2.21e+08 ...
## $ Date Rptd : POSIXct[1:944235], format: "2020-01-03" "2020-09-02" ...
## $ DATE OCC : POSIXct[1:944235], format: "2020-01-03" "2020-08-02" ...
## $ TIME OCC : num [1:944235] 2130 1800 1700 2037 1200 ...
## $ AREA : num [1:944235] 7 1 3 9 6 18 1 3 13 19 ...
## $ AREA NAME : chr [1:944235] "Wilshire" "Central" "Southwest" "Van Nuys" ...
## $ Rpt Dist No : num [1:944235] 784 182 356 964 666 ...
## $ Part 1-2 : num [1:944235] 1 1 1 1 2 2 2 2 2 2 ...
## $ Crm Cd : num [1:944235] 510 330 480 343 354 354 354 354 354 624 ...
## $ Crm Cd Desc : chr [1:944235] "VEHICLE - STOLEN" "BURGLARY FROM VEHICLE" "BIKE - STOLEN" "SHOPLIFTING-GRAND THEFT ($950.01 & OVER)" ...
## $ Mocodes : chr [1:944235] NA "1822 1402 0344" "0344 1251" "0325 1501" ...
## $ Vict Age : num [1:944235] 0 47 19 19 28 41 25 27 24 26 ...
## $ Vict Sex : chr [1:944235] "M" "M" "X" "M" ...
## $ Vict Descent : chr [1:944235] "O" "O" "X" "O" ...
## $ Premis Cd : num [1:944235] 101 128 502 405 102 501 502 248 750 502 ...
## $ Premis Desc : chr [1:944235] "STREET" "BUS STOP/LAYOVER (ALSO QUERY 124)" "MULTI-UNIT DWELLING (APARTMENT, DUPLEX, ETC)" "CLOTHING STORE" ...
## $ Weapon Used Cd: num [1:944235] NA NA NA NA NA NA NA NA NA 400 ...
## $ Weapon Desc : chr [1:944235] NA NA NA NA ...
## $ Status : chr [1:944235] "AA" "IC" "IC" "IC" ...
## $ Status Desc : chr [1:944235] "Adult Arrest" "Invest Cont" "Invest Cont" "Invest Cont" ...
## $ Crm Cd 1 : num [1:944235] 510 330 480 343 354 354 354 354 354 624 ...
## $ Crm Cd 2 : num [1:944235] 998 998 NA NA NA NA NA NA NA NA ...
## $ Crm Cd 3 : num [1:944235] NA NA NA NA NA NA NA NA NA NA ...
## $ Crm Cd 4 : logi [1:944235] NA NA NA NA NA NA ...
## $ LOCATION : chr [1:944235] "1900 S LONGWOOD AV" "1000 S FLOWER ST" "1400 W 37TH ST" "14000 RIVERSIDE DR" ...
## $ Cross Street : chr [1:944235] NA NA NA NA ...
## $ LAT : chr [1:944235] "340375" "340444" "34021" "341576" ...
## $ LON : chr [1:944235] "-1183506" "-1182628" "-1183002" "-1184387" ...
Giải thích kỹ thuật:
Hàm str() hiển thị cấu trúc chi tiết của từng biến, bao gồm tên, kiểu dữ liệu, và một vài giá trị mẫu.
## $DR_NO
## [1] "numeric"
##
## $`Date Rptd`
## [1] "POSIXct" "POSIXt"
##
## $`DATE OCC`
## [1] "POSIXct" "POSIXt"
##
## $`TIME OCC`
## [1] "numeric"
##
## $AREA
## [1] "numeric"
##
## $`AREA NAME`
## [1] "character"
##
## $`Rpt Dist No`
## [1] "numeric"
##
## $`Part 1-2`
## [1] "numeric"
##
## $`Crm Cd`
## [1] "numeric"
##
## $`Crm Cd Desc`
## [1] "character"
##
## $Mocodes
## [1] "character"
##
## $`Vict Age`
## [1] "numeric"
##
## $`Vict Sex`
## [1] "character"
##
## $`Vict Descent`
## [1] "character"
##
## $`Premis Cd`
## [1] "numeric"
##
## $`Premis Desc`
## [1] "character"
##
## $`Weapon Used Cd`
## [1] "numeric"
##
## $`Weapon Desc`
## [1] "character"
##
## $Status
## [1] "character"
##
## $`Status Desc`
## [1] "character"
##
## $`Crm Cd 1`
## [1] "numeric"
##
## $`Crm Cd 2`
## [1] "numeric"
##
## $`Crm Cd 3`
## [1] "numeric"
##
## $`Crm Cd 4`
## [1] "logical"
##
## $LOCATION
## [1] "character"
##
## $`Cross Street`
## [1] "character"
##
## $LAT
## [1] "character"
##
## $LON
## [1] "character"
Giải thích kỹ thuật:
Hàm sapply(df, class) trả về kiểu dữ liệu của từng cột trong data frame.
Kết quả cho biết biến nào thuộc dạng numeric, character, Date, hay factor.
Ý nghĩa thống kê:
Dựa trên kết quả kiểm tra kiểu dữ liệu, ta có thể phân loại các biến trong bộ dữ liệu như sau:
Biến định lượng: TIME OCC, Vict Age, AREA, Crm Cd, Crm Cd 1, Crm Cd 2, Crm Cd 3, Premis Cd, Weapon Used Cd.
Biến định tính: AREA NAME, Crm Cd Desc, Vict Sex, Vict Descent, Premis Desc, Weapon Desc, Status, Status Desc, LOCATION, Cross Street.
Biến thời gian: Date Rptd, DATE OCC.
Biến vị trí địa lý: LAT, LON.
Biến logic: Crm Cd 4.
Từ bộ dữ liệu gốc, chúng em sẽ tiến hành lựa chọn và đổi tên 11 biến quan trọng cần cho bài nghiên cứu. Các biến được đặt lại tên ngắn gọn, dễ hiểu.
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
crime_data <- df %>%
select(`DATE OCC`,`AREA NAME`,`Part 1-2`,`Crm Cd Desc`,`Vict Age`,`Vict Sex`,`Weapon Desc`, `Status Desc`,`LAT`,`LON`) %>%
rename(
date = `DATE OCC`,
area = `AREA NAME`,
severity = `Part 1-2`,
crime_type = `Crm Cd Desc`,
age = `Vict Age`,
sex = `Vict Sex`,
weapon = `Weapon Desc`,
status = `Status Desc`,
lat = `LAT`,
lon = `LON`
)Giải thích kỹ thuật:
Hàm select() trong dplyr được dùng để lựa chọn các biến cần thiết từ bộ dữ liệu ban đầu.
Hàm rename() giúp đổi tên các biến sang dạng ngắn gọn, thống nhất với quy tắc đặt tên.
Kết quả thu được là một bảng dữ liệu nhỏ gọn hơn, chỉ chứa 11 biến quan trọng nhất.
Ý nghĩa thống kê:
Các biến được giữ lại bao gồm:
date: thời điểm xảy ra vụ án (biến thời gian).
area: khu vực xảy ra vụ án (biến định tính).
severity: mức độ nghiêm trọng của vụ án (định tính thứ bậc).
crime_type: mô tả loại tội phạm (định tính).
age: tuổi nạn nhân (định lượng liên tục).
sex: giới tính nạn nhân (định tính).
weapon: loại vũ khí được sử dụng.
status: tình trạng xử lý vụ án (định tính).
lat, lon: tọa độ địa lý nơi xảy ra vụ án (biến định lượng).
## date area severity crime_type age sex weapon
## 0 0 0 0 0 126595 619758
## status lat lon
## 0 0 0
## [1] 746353
Giải thích kỹ thuật:
Hàm is.na(): kiểm tra giá trị bị thiếu (NA) trong từng ô dữ liệu, trả về TRUE/FALSE
Hàm colSums(): tính tổng số TRUE (tức là số NA) theo từng cột
=> colSums(is.na(crime_data)) cho biết mỗi biến có bao nhiêu giá trị bị thiếu
Hàm sum(): tính tổng tất cả các giá trị TRUE trong toàn bộ bảng
=> sum(is.na(crime_data)) cho biết tổng số giá trị thiếu trong toàn bộ dataset
Ý nghĩa thống kê:
Biến sex có 126.595 và biến weapon có 619.758 dữ liệu bị thiếu.
Các biến còn lại không có dữ liệu bị thiếu.
Tổng cộng có 746.353 ô dữ liệu bị trống.
## [1] 11098
Giải thích kỹ thuật:
Hàm duplicated(): xác định các dòng bị trùng lặp trong bộ dữ liệu, trả về TRUE/FALSE
Hàm sum(): tính tổng số dòng TRUE, tức là tổng số dòng bị trùng
=> sum(duplicated(crime_data)) cho biết có bao nhiêu quan sát trùng lặp trong dữ liệu
Ý nghĩa thống kê:
Kết quả cho thấy 11.098 quan sát bị trùng lặp.
Trong bộ dữ liệu, mỗi dòng (một quan sát) không nhất thiết tương ứng với một vụ án duy nhất, có thể có nhiều nạn nhân trong cùng một sự việc, các biến như date, area, crime_type… sẽ giống nhau, khiến hệ thống nhận diện là trùng lặp về mặt kỹ thuật, dù thực tế chúng phản ánh các đối tượng khác nhau trong cùng vụ án.
Nếu loại bỏ các bản ghi này, dữ liệu sẽ mất thông tin về số lượng nạn nhân, giới tính hoặc độ tuổi — những yếu tố quan trọng trong phân tích hành vi tội phạm.
Vì vậy, nhóm giữ nguyên toàn bộ các bản ghi trùng lặp để đảm bảo tính toàn vẹn, đầy đủ và chính xác của bộ dữ liệu, đặc biệt cho các phân tích liên quan đến nhân khẩu học của nạn nhân.
Giải thích kỹ thuật:
-weapon — tidyselect: chọn tất cả các cột trừ cột weapon.
if_any(-weapon, is.na): áp dụng is.na cho mỗi cột được chọn, trả về một logical vector theo hàng, TRUE nếu ít nhất một cột trong hàng đó là NA. !if_any(...): phủ định, TRUE khi không có NA trong tất cả các cột được chọn (tức là hàng hợp lệ).
filter(...): giữ lại các hàng với điều kiện TRUE
Biến crime được tạo mới từ crime_data sau khi đã loại bỏ các dòng có dữ liệu thiếu (trừ biến weapon), đảm bảo bộ dữ liệu đầu vào cho các bước phân tích sau đầy đủ và không bị gián đoạn bởi NA.
Ý Nghĩa thống kê:
Các giá trị NA trong biến weapon không phải là lỗi nhập liệu, mà phản ánh bản chất của dữ liệu thực tế: Nhiều vụ án không có vũ khí được sử dụng, chẳng hạn như trộm cắp, lừa đảo hoặc các hành vi phạm tội không liên quan đến bạo lực.
Trong các trường hợp này, biến weapon được để trống (NA) để biểu thị rằng không có vũ khí được ghi nhận. Vì vậy, các giá trị NA ở biến weapon có ý nghĩa thực tế, tương đương với việc “không sử dụng vũ khí”. Do đó, em không loại bỏ các dòng có NA ở biến weapon, để tránh làm sai lệch bản chất của dữ liệu gốc và giữ nguyên thông tin thống kê về tần suất sử dụng vũ khí trong tội phạm.
## [1] "Date"
Giải thích kỹ thuật:
Hàm as.Date() dùng để chuyển đổi dữ liệu thời gian từ dạng ký tự hoặc dạng thời gian phức hợp (như POSIXct/POSIXt) sang định dạng ngày (Date) trong R.
Lệnh class(crime$date) giúp kiểm tra kiểu dữ liệu của biến date sau khi chuyển đổi, đảm bảo rằng biến này đã được nhận diện đúng là kiểu Date.
Giải thích kỹ thuật:
Hàm format() được dùng để trích xuất thông tin cụ thể từ biến ngày tháng, ở đây là năm ("%Y").
Lệnh as.Date(crime$date) đảm bảo rằng biến date được định dạng đúng kiểu ngày trước khi trích xuất.
Sau câu lệnh này, cột mới tên là year sẽ được tạo ra, lưu trữ năm xảy ra vụ án dưới dạng ký tự (character).
Giải thích kỹ thuật:
%>% là toán tử pipe trong dplyr, giúp nối các thao tác xử lý dữ liệu một cách trực quan.
filter() là hàm dùng để lọc các quan sát theo điều kiện nhất định.
Ở đây: age >= 0: loại bỏ các giá trị tuổi âm, đảm bảo tuổi của nạn nhân hợp lệ. year >= 2020 & year <= 2023: giữ lại các quan sát xảy ra trong giai đoạn nghiên cứu (2020–2023).
## tibble [760,572 × 11] (S3: tbl_df/tbl/data.frame)
## $ date : Date[1:760572], format: "2020-01-03" "2020-08-02" ...
## $ area : chr [1:760572] "Wilshire" "Central" "Southwest" "Van Nuys" ...
## $ severity : num [1:760572] 1 1 1 1 2 2 2 2 2 2 ...
## $ crime_type: chr [1:760572] "VEHICLE - STOLEN" "BURGLARY FROM VEHICLE" "BIKE - STOLEN" "SHOPLIFTING-GRAND THEFT ($950.01 & OVER)" ...
## $ age : num [1:760572] 0 47 19 19 28 41 25 27 24 26 ...
## $ sex : chr [1:760572] "M" "M" "X" "M" ...
## $ weapon : chr [1:760572] NA NA NA NA ...
## $ status : chr [1:760572] "Adult Arrest" "Invest Cont" "Invest Cont" "Invest Cont" ...
## $ lat : chr [1:760572] "340375" "340444" "34021" "341576" ...
## $ lon : chr [1:760572] "-1183506" "-1182628" "-1183002" "-1184387" ...
## $ year : chr [1:760572] "2020" "2020" "2020" "2020" ...
Giải thích kỹ thuật:
str() là hàm cơ bản trong R dùng để hiển thị cấu trúc tổng quan của dữ liệu: bao gồm số dòng, số cột, tên biến, kiểu dữ liệu từng cột và một số giá trị đầu tiên.
Ý nghĩa thống kê:
Sau quá trình làm sạch, bộ dữ liệu “Crime Data from 2020 to Present” thu thập từ Sở Cảnh sát Los Angeles (LAPD) còn lại 760.572 quan sát và 11 biến.
crime <- crime %>%
mutate(
lat = as.numeric(lat),
lon = as.numeric(lon)
) %>%
mutate(
lat = ifelse(lat > 100, lat / 10, lat),
lon = ifelse(lon > -200, lon * 100, lon)
)Giải thích kỹ thuật:
mutate() là hàm trong dplyr dùng để tạo mới hoặc chỉnh sửa các biến.
as.numeric(lat) và as.numeric(lon) chuyển các cột lat (vĩ độ) và lon (kinh độ) từ kiểu ký tự (character) sang kiểu số (numeric) để thực hiện các phép toán.
ifelse(lat > 100, lat / 10, lat): nếu giá trị vĩ độ lớn hơn 100 (không hợp lý cho Los Angeles, vì LA nằm khoảng 33–34 độ vĩ bắc), sẽ chia cho 10 để chuẩn hóa về đúng giá trị thực.
ifelse(lon > -200, lon * 100, lon): nếu giá trị kinh độ lớn hơn -200 (nhận dạng các giá trị bị sai định dạng âm hoặc thiếu dấu), nhân 100 để điều chỉnh về tọa độ hợp lý.
Ý nghĩa thống kê:
Dữ liệu ban đầu có một số giá trị lat và lon bị sai lệch do lỗi nhập liệu hoặc định dạng, nằm ngoài phạm vi thực tế của Los Angeles (LAT ≈ 33.7–34.4, LON ≈ -118.6 đến -118.1). Các giá trị này bị lệch một bậc thập phân nên được hiệu chỉnh để đảm bảo tọa độ chính xác trên bản đồ.
Việc chuẩn hóa các tọa độ giúp các thao tác trực quan hóa không gặp lỗi, đảm bảo bản đồ tội phạm hiển thị đúng vị trí các vụ án.
## [1] NA
## [2] "STRONG-ARM (HANDS, FIST, FEET OR BODILY FORCE)"
## [3] "VEHICLE"
## [4] "UNKNOWN WEAPON/OTHER WEAPON"
## [5] "VERBAL THREAT"
## [6] "BELT FLAILING INSTRUMENT/CHAIN"
## [7] "HAND GUN"
## [8] "UNKNOWN FIREARM"
## [9] "KNIFE WITH BLADE 6INCHES OR LESS"
## [10] "FIXED OBJECT"
## [11] "KITCHEN KNIFE"
## [12] "MACHETE"
## [13] "MACE/PEPPER SPRAY"
## [14] "CLUB/BAT"
## [15] "STICK"
## [16] "OTHER KNIFE"
## [17] "PHYSICAL PRESENCE"
## [18] "KNIFE WITH BLADE OVER 6 INCHES IN LENGTH"
## [19] "HAMMER"
## [20] "AIR PISTOL/REVOLVER/RIFLE/BB GUN"
## [21] "SEMI-AUTOMATIC PISTOL"
## [22] "SIMULATED GUN"
## [23] "RAZOR"
## [24] "OTHER FIREARM"
## [25] "FOLDING KNIFE"
## [26] "PIPE/METAL PIPE"
## [27] "ROCK/THROWN OBJECT"
## [28] "RIFLE"
## [29] "OTHER CUTTING INSTRUMENT"
## [30] "FIRE"
## [31] "REVOLVER"
## [32] "BOTTLE"
## [33] "SCISSORS"
## [34] "SWITCH BLADE"
## [35] "BRASS KNUCKLES"
## [36] "UNKNOWN TYPE CUTTING INSTRUMENT"
## [37] "BLUNT INSTRUMENT"
## [38] "BOARD"
## [39] "STUN GUN"
## [40] "CLEAVER"
## [41] "RAZOR BLADE"
## [42] "SCREWDRIVER"
## [43] "SHOTGUN"
## [44] "CONCRETE BLOCK/BRICK"
## [45] "CAUSTIC CHEMICAL/POISON"
## [46] "SEMI-AUTOMATIC RIFLE"
## [47] "SCALDING LIQUID"
## [48] "TIRE IRON"
## [49] "BOWIE KNIFE"
## [50] "GLASS"
## [51] "AXE"
## [52] "TOY GUN"
## [53] "BOMB THREAT"
## [54] "SAWED OFF RIFLE/SHOTGUN"
## [55] "MARTIAL ARTS WEAPONS"
## [56] "DEMAND NOTE"
## [57] "DIRK/DAGGER"
## [58] "ASSAULT WEAPON/UZI/AK47/ETC"
## [59] "ROPE/LIGATURE"
## [60] "HECKLER & KOCH 93 SEMIAUTOMATIC ASSAULT RIFLE"
## [61] "EXPLOXIVE DEVICE"
## [62] "SWORD"
## [63] "MAC-11 SEMIAUTOMATIC ASSAULT WEAPON"
## [64] "SYRINGE"
## [65] "BOW AND ARROW"
## [66] "LIQUOR/DRUGS"
## [67] "DOG/ANIMAL (SIC ANIMAL ON)"
## [68] "BLACKJACK"
## [69] "ICE PICK"
## [70] "RELIC FIREARM"
## [71] "AUTOMATIC WEAPON/SUB-MACHINE GUN"
## [72] "ANTIQUE FIREARM"
## [73] "HECKLER & KOCH 91 SEMIAUTOMATIC ASSAULT RIFLE"
## [74] "STRAIGHT RAZOR"
## [75] "M1-1 SEMIAUTOMATIC ASSAULT RIFLE"
## [76] "STARTER PISTOL/REVOLVER"
## [77] "UZI SEMIAUTOMATIC ASSAULT RIFLE"
## [78] "MAC-10 SEMIAUTOMATIC ASSAULT WEAPON"
## [79] "UNK TYPE SEMIAUTOMATIC ASSAULT RIFLE"
## [80] "M-14 SEMIAUTOMATIC ASSAULT RIFLE"
library(dplyr)
library(stringr)
crime <- crime %>%
mutate(
weapon_group = case_when(
str_detect(weapon, "GUN|RIFLE|PISTOL|REVOLVER|FIREARM|SHOTGUN|UZI|MAC|ASSAULT WEAPON|AUTOMATIC") ~ "Firearm",
str_detect(weapon, "KNIFE|BLADE|MACHETE|RAZOR|DAGGER|SWORD|ICE PICK|DIRK|CLEAVER") ~ "Sharp object",
str_detect(weapon, "BAT|CLUB|PIPE|STICK|BOARD|HAMMER|BRICK|ROCK|TIRE IRON|AXE|BLUNT") ~ "Blunt object",
str_detect(weapon, "BOMB|EXPLOSIVE|FIRE|CHEMICAL|POISON|SCALDING|ACID") ~ "Chemical/Explosive",
str_detect(weapon, "STUN GUN|MACE|PEPPER|GAS") ~ "Support weapon",
str_detect(weapon, "ROPE|LIGATURE|DOG|ANIMAL|SYRINGE|LIQUOR|DRUG") ~ "Control tool",
str_detect(weapon, "STRONG-ARM|BODILY FORCE|VERBAL|PHYSICAL PRESENCE|DEMAND NOTE|NONE|UNKNOWN") ~ "Bare-handed attack",
is.na(weapon) ~ "No weapon",
TRUE ~ "Other"
)
)Giái thích kỹ thuật:
unique(crime$weapon): In ra danh sách các giá trị khác nhau hiện có trong cột weapon.
crime <- crime %>% mutate(...): Tạo các cột mới (không thay đổi cột gốc), lưu lại kết quả trở lại crime.
weapon_group = case_when(...)
- case_when(): đánh giá các điều kiện theo thứ tự từ trên xuống; biểu thức trả giá trị đầu tiên đúng.
— Các dòng str_detect(...) ~ "..." gom nhiều từ khóa tương ứng một nhóm logic.
— is.na(weaponn) ~ "Không có vũ khí": bắt các ô thực sự trống (NA).
— TRUE ~ "Khác": giá trị mặc định nếu không khớp bất kỳ điều kiện nào trước đó.
crime <- crime %>%
mutate(age_group = case_when(
age < 18 ~ "Juvenile",
age >= 18 & age < 40 ~ "Young adult",
age >= 40 & age < 60 ~ "Middle-aged",
age >= 60 ~ "Elderly",
TRUE ~ NA_character_
))Giải thích kỹ thuật:
mutate() (dplyr) dùng để tạo biến mới hoặc chỉnh sửa biến hiện có.
case_when() cho phép tạo nhiều điều kiện logic: mỗi điều kiện đi kèm với nhãn kết quả tương ứng.
Trong phần này:
age < 18 ~ "Juvenile"(Vị thành niên): nếu tuổi nhỏ hơn 18, gán nhãn "Vị thành niên".
age >= 18 & age < 40 ~ "Young adult"(Thanh niên): tuổi từ 18 đến dưới 40 là "Thanh niên".
age >= 40 & age < 60 ~ "Middle-aged"(Trung niên): tuổi từ 40 đến dưới 60 là "Trung niên".
age >= 60 ~ "Elderly"(Cao tuổi): tuổi từ 60 trở lên là "Cao tuổi".
TRUE ~ NA_character_: tất cả các giá trị khác (không xác định) sẽ gán NA.
Giải thích kỹ thuật:
mutate() (dplyr) được dùng để tạo biến mới hoặc cập nhật biến hiện có.
ifelse(condition, value_if_true, value_if_false) là hàm điều kiện cơ bản trong R:
condition: severity == 1 nghĩa là nếu mức độ tội phạm = 1.
value_if_true: gán nhãn "Severe" (nghiêm trọng) nếu điều kiện đúng.
value_if_false: gán nhãn "Minor" (nhẹ) nếu điều kiện sai (tức mức độ = 2)
crime <- crime %>%
mutate(
sex = case_when(
sex == "M" ~ "Male",
sex == "F" ~ "Female",
TRUE ~ "Unknown"
)
)Giải thích kỹ thuật:
toupper(sex): Chuyển toàn bộ giá trị trong cột sex thành chữ hoa, để đồng nhất hóa dữ liệu ("m", "M" → "M"; "f", "F" → "F").
case_when(): Dùng để gán nhãn định tính dễ hiểu cho dữ liệu đã đồng nhất: "M" → "Male", "F" → "Female". Các giá trị khác (không xác định, trống, hoặc bất thường) → "Unknown".
crime <- crime %>%
mutate(arrested = ifelse(status %in% c("Adult Arrest", "Juv Arrest"), "Arrested", "Not arrested"))Giải thích kỹ thuật:
mutate() (dplyr) được dùng để tạo biến mới hoặc cập nhật biến hiện có.
ifelse(condition, value_if_true, value_if_false):
condition: status %in% c("Adult Arrest", "Juv Arrest") nghĩa là kiểm tra xem giá trị trong cột status có nằm trong danh sách "Adult Arrest" (người lớn bị bắt) hoặc "Juv Arrest" (vị thành niên bị bắt) hay không.
value_if_true: nếu đúng, gán nhãn "Arrested"(đã bắt giữ).
value_if_false: nếu sai, gán nhãn "Not arrested"(chưa bắt giữ).
## [1] "VEHICLE - STOLEN"
## [2] "BURGLARY FROM VEHICLE"
## [3] "BIKE - STOLEN"
## [4] "SHOPLIFTING-GRAND THEFT ($950.01 & OVER)"
## [5] "THEFT OF IDENTITY"
## [6] "BATTERY - SIMPLE ASSAULT"
## [7] "SODOMY/SEXUAL CONTACT B/W PENIS OF ONE PERS TO ANUS OTH"
## [8] "CRM AGNST CHLD (13 OR UNDER) (14-15 & SUSP 10 YRS OLDER)"
## [9] "SEX,UNLAWFUL(INC MUTUAL CONSENT, PENETRATION W/ FRGN OBJ"
## [10] "ASSAULT WITH DEADLY WEAPON, AGGRAVATED ASSAULT"
## [11] "LETTERS, LEWD - TELEPHONE CALLS, LEWD"
## [12] "THEFT-GRAND ($950.01 & OVER)EXCPT,GUNS,FOWL,LIVESTK,PROD"
## [13] "CRIMINAL THREATS - NO WEAPON DISPLAYED"
## [14] "CHILD ANNOYING (17YRS & UNDER)"
## [15] "CONTEMPT OF COURT"
## [16] "THEFT PLAIN - PETTY ($950 & UNDER)"
## [17] "INTIMATE PARTNER - SIMPLE ASSAULT"
## [18] "LEWD CONDUCT"
## [19] "THEFT PLAIN - ATTEMPT"
## [20] "BURGLARY"
## [21] "THEFT FROM MOTOR VEHICLE - GRAND ($950.01 AND OVER)"
## [22] "ROBBERY"
## [23] "BUNCO, GRAND THEFT"
## [24] "BATTERY WITH SEXUAL CONTACT"
## [25] "INTIMATE PARTNER - AGGRAVATED ASSAULT"
## [26] "ORAL COPULATION"
## [27] "UNAUTHORIZED COMPUTER ACCESS"
## [28] "VIOLATION OF RESTRAINING ORDER"
## [29] "SHOPLIFTING - PETTY THEFT ($950 & UNDER)"
## [30] "VANDALISM - FELONY ($400 & OVER, ALL CHURCH VANDALISMS)"
## [31] "BRANDISH WEAPON"
## [32] "DOCUMENT FORGERY / STOLEN FELONY"
## [33] "SEX OFFENDER REGISTRANT OUT OF COMPLIANCE"
## [34] "EMBEZZLEMENT, GRAND THEFT ($950.01 & OVER)"
## [35] "RAPE, FORCIBLE"
## [36] "VANDALISM - MISDEAMEANOR ($399 OR UNDER)"
## [37] "OTHER MISCELLANEOUS CRIME"
## [38] "CHILD ABUSE (PHYSICAL) - SIMPLE ASSAULT"
## [39] "CREDIT CARDS, FRAUD USE ($950.01 & OVER)"
## [40] "THREATENING PHONE CALLS/LETTERS"
## [41] "SEXUAL PENETRATION W/FOREIGN OBJECT"
## [42] "EXTORTION"
## [43] "OTHER ASSAULT"
## [44] "PICKPOCKET"
## [45] "ARSON"
## [46] "DISTURBING THE PEACE"
## [47] "BUNCO, ATTEMPT"
## [48] "HUMAN TRAFFICKING - INVOLUNTARY SERVITUDE"
## [49] "PEEPING TOM"
## [50] "VIOLATION OF COURT ORDER"
## [51] "FALSE POLICE REPORT"
## [52] "CONTRIBUTING"
## [53] "FALSE IMPRISONMENT"
## [54] "THEFT FROM MOTOR VEHICLE - PETTY ($950 & UNDER)"
## [55] "CHILD ABUSE (PHYSICAL) - AGGRAVATED ASSAULT"
## [56] "ATTEMPTED ROBBERY"
## [57] "CREDIT CARDS, FRAUD USE ($950 & UNDER"
## [58] "CHILD STEALING"
## [59] "LEWD/LASCIVIOUS ACTS WITH CHILD"
## [60] "INDECENT EXPOSURE"
## [61] "CHILD NEGLECT (SEE 300 W.I.C.)"
## [62] "STALKING"
## [63] "DISHONEST EMPLOYEE - GRAND THEFT"
## [64] "TRESPASSING"
## [65] "BURGLARY, ATTEMPTED"
## [66] "RAPE, ATTEMPTED"
## [67] "DISCHARGE FIREARMS/SHOTS FIRED"
## [68] "PIMPING"
## [69] "HUMAN TRAFFICKING - COMMERCIAL SEX ACTS"
## [70] "VEHICLE - ATTEMPT STOLEN"
## [71] "PANDERING"
## [72] "FIREARMS RESTRAINING ORDER (FIREARMS RO)"
## [73] "RESISTING ARREST"
## [74] "BURGLARY FROM VEHICLE, ATTEMPTED"
## [75] "THEFT, PERSON"
## [76] "BATTERY POLICE (SIMPLE)"
## [77] "THEFT FROM PERSON - ATTEMPT"
## [78] "FAILURE TO YIELD"
## [79] "BOMB SCARE"
## [80] "VEHICLE, STOLEN - OTHER (MOTORIZED SCOOTERS, BIKES, ETC)"
## [81] "ASSAULT WITH DEADLY WEAPON ON POLICE OFFICER"
## [82] "BUNCO, PETTY THEFT"
## [83] "SHOTS FIRED AT INHABITED DWELLING"
## [84] "DEFRAUDING INNKEEPER/THEFT OF SERVICES, $950 & UNDER"
## [85] "KIDNAPPING - GRAND ATTEMPT"
## [86] "SHOTS FIRED AT MOVING VEHICLE, TRAIN OR AIRCRAFT"
## [87] "TILL TAP - GRAND THEFT ($950.01 & OVER)"
## [88] "VIOLATION OF TEMPORARY RESTRAINING ORDER"
## [89] "THROWING OBJECT AT MOVING VEHICLE"
## [90] "DOCUMENT WORTHLESS ($200.01 & OVER)"
## [91] "KIDNAPPING"
## [92] "CRIMINAL HOMICIDE"
## [93] "PURSE SNATCHING"
## [94] "THEFT FROM MOTOR VEHICLE - ATTEMPT"
## [95] "DISHONEST EMPLOYEE - PETTY THEFT"
## [96] "EMBEZZLEMENT, PETTY THEFT ($950 & UNDER)"
## [97] "CHILD PORNOGRAPHY"
## [98] "WEAPONS POSSESSION/BOMBING"
## [99] "DRIVING WITHOUT OWNER CONSENT (DWOC)"
## [100] "REPLICA FIREARMS(SALE,DISPLAY,MANUFACTURE OR DISTRIBUTE)"
## [101] "LYNCHING"
## [102] "RECKLESS DRIVING"
## [103] "SHOPLIFTING - ATTEMPT"
## [104] "COUNTERFEIT"
## [105] "DEFRAUDING INNKEEPER/THEFT OF SERVICES, OVER $950.01"
## [106] "BATTERY ON A FIREFIGHTER"
## [107] "CRUELTY TO ANIMALS"
## [108] "ILLEGAL DUMPING"
## [109] "PROWLER"
## [110] "DRUGS, TO A MINOR"
## [111] "THEFT, COIN MACHINE - PETTY ($950 & UNDER)"
## [112] "DOCUMENT WORTHLESS ($200 & UNDER)"
## [113] "MANSLAUGHTER, NEGLIGENT"
## [114] "PETTY THEFT - AUTO REPAIR"
## [115] "THEFT, COIN MACHINE - ATTEMPT"
## [116] "TILL TAP - PETTY ($950 & UNDER)"
## [117] "PURSE SNATCHING - ATTEMPT"
## [118] "LYNCHING - ATTEMPTED"
## [119] "BIKE - ATTEMPTED STOLEN"
## [120] "GRAND THEFT / AUTO REPAIR"
## [121] "CONSPIRACY"
## [122] "BRIBERY"
## [123] "GRAND THEFT / INSURANCE FRAUD"
## [124] "DRUNK ROLL"
## [125] "CHILD ABANDONMENT"
## [126] "THEFT, COIN MACHINE - GRAND ($950.01 & OVER)"
## [127] "DISRUPT SCHOOL"
## [128] "PICKPOCKET, ATTEMPT"
## [129] "TELEPHONE PROPERTY - DAMAGE"
## [130] "BEASTIALITY, CRIME AGAINST NATURE SEXUAL ASSLT WITH ANIM"
## [131] "BIGAMY"
## [132] "FAILURE TO DISPERSE"
## [133] "FIREARMS EMERGENCY PROTECTIVE ORDER (FIREARMS EPO)"
## [134] "INCEST (SEXUAL ACTS BETWEEN BLOOD RELATIVES)"
## [135] "BLOCKING DOOR INDUCTION CENTER"
## [136] "INCITING A RIOT"
## [137] "DISHONEST EMPLOYEE ATTEMPTED THEFT"
crime <- crime %>%
mutate(
crime_group = case_when(
grepl("THEFT|BURGLARY|ROBBERY|SHOPLIFT|LARCENY|VEHICLE|AUTO|CAR", crime_type, ignore.case = TRUE) ~ "Theft & Robbery",
grepl("ASSAULT|BATTERY|KIDNAPPING|THREAT|STALKING", crime_type, ignore.case = TRUE) ~ "Violence & Assault",
grepl("RAPE|SEX|HARASS|LEWD", crime_type, ignore.case = TRUE) ~ "Sexual & Harassment",
grepl("HOMICIDE|MURDER|MANSLAUGHTER", crime_type, ignore.case = TRUE) ~ "Homicide",
grepl("DRUG|NARCOTIC", crime_type, ignore.case = TRUE) ~ "Drug-related",
grepl("FRAUD|FORGERY|IDENTITY|SCAM|EMBEZZLEMENT|BRIBERY", crime_type, ignore.case = TRUE) ~ "Fraud & Financial Crime",
grepl("ARSON|FIRE", crime_type, ignore.case = TRUE) ~ "Arson",
TRUE ~ "Other"
)
)Giải thích kỹ thuật:
unique() là hàm dùng để liệt kê các giá trị duy nhất trong một vector hoặc cột dữ liệu. Ở đây, crime$crime_type là cột chứa tên loại tội phạm cụ thể. Kết quả trả về là danh sách tất cả các loại tội phạm xuất hiện trong dữ liệu.
mutate() (dplyr) dùng để tạo biến mới crime_group.
case_when() là hàm điều kiện nhiều nhánh, gán giá trị khác nhau cho crime_group dựa trên nội dung của crime_type.
grepl(pattern, x, ignore.case = TRUE):
pattern: các từ khóa đại diện cho nhóm tội phạm.
x: cột crime_type.
ignore.case = TRUE: không phân biệt chữ hoa – chữ thường.
TRUE ~ "Other": nếu crime_type không khớp bất kỳ nhóm nào, gán nhãn "Other".
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.00 23.00 34.00 34.21 48.00 99.00
Giải thích kỹ thuật
Lệnh summary(crime$age) trả về các chỉ số tóm tắt cơ bản của biến số (age):
Min.: giá trị nhỏ nhất.
1st Qu.: giá trị phần tư thứ nhất.
Median: trung vị.
Mean: giá trị trung bình.
3rd Qu.: phần tư thứ ba.
Max.: giá trị lớn nhất.
Ý nghĩa thống kê:
Dữ liệu cho thấy độ tuổi nạn nhân dao động từ 0 đến 99 tuổi, với trung vị là 34 tuổi và giá trị trung bình xấp xỉ 34,21 tuổi, chứng tỏ phần lớn nạn nhân nằm trong nhóm người trưởng thành đang trong độ tuổi lao động.
Giá trị nhỏ nhất bằng 0 nhiều khả năng phản ánh các trường hợp trẻ sơ sinh hoặc thai nhi bị ảnh hưởng trong các vụ án hình sự (như bạo hành, tấn công khi người mẹ mang thai).
Điều này cũng phản ánh rõ hơn mức độ đa dạng và nghiêm trọng của các loại tội phạm ảnh hưởng đến các nhóm tuổi khác nhau trong xã hội.
crime_by_group <- crime %>%
group_by(crime_group) %>%
summarise(tong_so_vu = n()) %>%
mutate(ty_trong = round(tong_so_vu / sum(tong_so_vu) * 100, 3)) %>%
arrange(desc(tong_so_vu))
print(crime_by_group)## # A tibble: 8 × 3
## crime_group tong_so_vu ty_trong
## <chr> <int> <dbl>
## 1 Theft & Robbery 369262 48.6
## 2 Violence & Assault 210113 27.6
## 3 Other 154071 20.3
## 4 Sexual & Harassment 16038 2.11
## 5 Arson 6489 0.853
## 6 Fraud & Financial Crime 3112 0.409
## 7 Homicide 1476 0.194
## 8 Drug-related 11 0.001
Giải thích kỹ thuật:
group_by(crime_group): tạo nhóm theo biến phân loại crime_group.
summarise(tong_so_vu = n()): tổng hợp ở mức nhóm; n()đếm số dòng trong mỗi nhóm ⇒ số vụ của từng crime_group.
mutate(ty_trong = round(tong_so_vu/ sum(tong_so_vu) * 100, 3))`: Tính tỷ trọng mỗi nhóm trên tổng toàn bảng đã tổng hợp (tức tổng qua các nhóm). round(..., 3) làm tròn 3 chữ số thập phân.
arrange(desc(tong_so_vu))`: sắp xếp giảm dần theo số vụ.
print(crime_by_group): In kết quả ra màn hình dưới dạng bảng thống kê tổng hợp.
Ý nghĩa thống kê:
Nhóm “Theft & Robbery (Trộm cắp – Cướp giật)” với 369.262 vụ (48,6%) chiếm gần một nửa tổng số vụ án, cho thấy tội phạm xâm phạm tài sản vẫn là vấn đề nổi cộm nhất tại Los Angeles.
Đứng thứ hai là “Violence & Assault (Bạo lực – Hành hung)” với 210.113 vụ (27,6%), phản ánh mức độ phổ biến của các hành vi gây tổn hại thân thể và tiềm ẩn rủi ro về an ninh công cộng.
Nhóm “Other (Khác)” gồm 154.071 vụ (20,3%), chủ yếu là các tội phạm ít gặp hoặc khó phân loại, thể hiện sự đa dạng và phức tạp của hành vi phạm tội đô thị.
Các nhóm có quy mô nhỏ hơn như “Sexual & Harassment (Tình dục – Quấy rối)” (16.038 vụ, 2,1%) và “Arson (Phóng hỏa)” (6.489 vụ, 0,9%) tuy chiếm tỷ trọng thấp nhưng mang tính chất nghiêm trọng, gây ảnh hưởng lớn đến tâm lý và an toàn cộng đồng.
Trong khi đó, “Fraud & Financial Crime (Gian lận – Tài chính)” (3.112 vụ, 0,4%) và “Homicide (Giết người)” (1.476 vụ, 0,2%) xuất hiện ít nhưng hậu quả kinh tế và xã hội cao, đòi hỏi biện pháp phòng ngừa chuyên biệt.
Đáng chú ý, “Drug-related (Ma túy)” chỉ ghi nhận 11 vụ (0,001%), cho thấy loại tội phạm này xảy ra rất ít trong giai đoạn nghiên cứu và không phải là vấn đề nổi bật tại Los Angeles so với các nhóm tội phạm khác.
Giải thích kỹ thuật:
crime %>%: dùng toán tử pipe từ dplyr để chuyền dữ liệu crime vào chuỗi thao tác tiếp theo.
group_by(crime_group): gộp (nhóm) các bản ghi theo biến crime_group.
summarise(tuoi_trung_binh = mean(age, na.rm = TRUE)): tính giá trị trung bình của cột age cho mỗi nhóm. mean(age, na.rm = TRUE) tính trung bình, loại bỏ NA (tham số na.rm = TRUE) để tránh lỗi hoặc làm sai lệch kết quả khi có giá trị thiếu. Kết quả được lưu vào cột mới đặt tên tuổi trung bình.
Ý nghĩa thống kê:
Kết quả phân tích cho thấy độ tuổi trung bình của nạn nhân khác biệt rõ rệt giữa các nhóm tội phạm, phản ánh đặc trưng xã hội – hành vi của từng loại tội phạm:
Cao nhất là nhóm “Fraud & Financial Crime (Gian lận – Tài chính)” với độ tuổi trung bình hơn 37 tuổi. Nạn nhân thường là người trưởng thành, có công việc và tài sản, cho thấy tội phạm kinh tế thường nhắm đến các đối tượng có khả năng tài chính và tham gia giao dịch.
Nhóm “Violence & Assault (Bạo lực – Hành hung)” (≈36 tuổi) và “Homicide (Giết người)” (≈36 tuổi) có độ tuổi trung bình tương đồng, cho thấy các vụ việc nghiêm trọng thường xảy ra giữa người trưởng thành, xuất phát từ mâu thuẫn cá nhân, gia đình hoặc xã hội.
Nhóm “Theft & Robbery (Trộm cắp – Cướp giật)” có độ tuổi trung bình ≈34 tuổi, phản ánh nạn nhân chủ yếu là người trong độ tuổi lao động, thường xuyên di chuyển và mang theo tài sản cá nhân.
Nhóm “Sexual & Harassment (Tình dục – Quấy rối)” (≈29 tuổi) có xu hướng nạn nhân trẻ hơn, có thể bao gồm học sinh, sinh viên hoặc người trẻ đang lao động — nhóm cần được bảo vệ đặc biệt.
Nhóm “Arson (Phóng hỏa)” có độ tuổi trung bình ≈21 tuổi, tương đối trẻ, gợi ý liên quan đến các vụ phá hoại hoặc tai nạn tập thể, đặc biệt trong khu dân cư hoặc nhóm thanh thiếu niên.
Nhóm “Drug-related (Ma túy)” có độ tuổi trung bình ≈8 tuổi, là giá trị bất thường thấp, có khả năng phản ánh trường hợp nạn nhân là trẻ em hoặc thai nhi bị ảnh hưởng gián tiếp, cho thấy tác động lan tỏa đáng lo ngại của ma túy đến nhóm tuổi nhỏ.
Nhóm “Other (Khác)” có độ tuổi trung bình ≈32,3 tuổi, bao gồm nhiều loại tội phạm không thuộc các nhóm chính, song vẫn cho thấy đa số nạn nhân là người trưởng thành.
crime_summary_age <- crime %>%
group_by(year, age_group) %>%
summarise(frequency = n(), .groups = "drop_last") %>%
group_by(year) %>%
mutate(percentage = round(frequency / sum(frequency) * 100, 2)) %>%
ungroup()
print(crime_summary_age)## # A tibble: 16 × 4
## year age_group frequency percentage
## <chr> <chr> <int> <dbl>
## 1 2020 Elderly 18634 10.7
## 2 2020 Juvenile 28243 16.2
## 3 2020 Middle-aged 48550 27.9
## 4 2020 Young adult 78752 45.2
## 5 2021 Elderly 19522 10.8
## 6 2021 Juvenile 27282 15.0
## 7 2021 Middle-aged 50285 27.7
## 8 2021 Young adult 84229 46.4
## 9 2022 Elderly 21896 10.7
## 10 2022 Juvenile 32439 15.8
## 11 2022 Middle-aged 55133 26.9
## 12 2022 Young adult 95400 46.6
## 13 2023 Elderly 21739 10.9
## 14 2023 Juvenile 38395 19.2
## 15 2023 Middle-aged 51289 25.6
## 16 2023 Young adult 88784 44.4
Giải thích kỹ thuật:
crime %>%: dùng toán tử pipe từ dplyr để chuyền dữ liệu crime vào chuỗi thao tác tiếp theo.
group_by(year, age_group): nhóm dữ liệu theo năm (year) và nhóm tuổi (age_group), để mỗi nhóm đại diện cho một tổ hợp năm – độ tuổi.
summarise(frequency = n(), .groups = "drop_last"): tính frequency (tần số) — số bản ghi trong từng nhóm (tức là tổng số nạn nhân mỗi năm – mỗi độ tuổi). .groups = "drop_last" giữ nhóm ngoài cùng khi cần tính tiếp.
group_by(year): tiếp tục nhóm theo năm để chuẩn bị tính tỷ lệ phần trăm trong từng năm.
mutate(percentage = round(frequency / sum(frequency) * 100, 2)): tính percentage (%) của từng nhóm tuổi trong mỗi năm, làm tròn 2 chữ số thập phân.
ungroup(): bỏ grouping để trả về dataframe bình thường.
Ý nghĩa thống kê:
Kết quả thống kê cho thấy sự thay đổi đáng chú ý trong cơ cấu độ tuổi nạn nhân từ năm 2020–2023:
Nhóm Young adult (18–39 tuổi) chiếm tỷ lệ cao nhất (≈43–47%) trong toàn giai đoạn. Đây là nhóm hoạt động xã hội, di chuyển nhiều, thường xuyên tiếp xúc với môi trường có rủi ro tội phạm — đặc biệt là trộm cắp và bạo lực.
Nhóm Middle-aged (40–59 tuổi) duy trì ổn định quanh mức 26–28%, phản ánh nhóm có mức độ tham gia xã hội cao nhưng ít rủi ro hơn thanh niên.
Nhóm Elderly (≥60 tuổi) chiếm khoảng 10–11%, tỷ lệ tương đối ổn định giữa các năm. Tuy nhiên, đây là nhóm dễ tổn thương do hạn chế thể chất và phụ thuộc kinh tế.
Nhóm Juvenile (<18 tuổi) có xu hướng tăng dần, từ 16,2% (2020) lên 19,13% (2023) — dấu hiệu đáng lo ngại, cho thấy độ tuổi nạn nhân đang bị trẻ hóa, đặc biệt trong bối cảnh môi trường mạng phát triển và gia tăng hành vi xâm hại.
crime_by_area_year <- crime %>%
group_by(year, area) %>%
summarise(tong_so_vu = n()) %>%
arrange(area, year)## `summarise()` has grouped output by 'year'. You can override using the
## `.groups` argument.
## # A tibble: 84 × 3
## # Groups: year [4]
## year area tong_so_vu
## <chr> <chr> <int>
## 1 2020 77th Street 11524
## 2 2021 77th Street 11102
## 3 2022 77th Street 12508
## 4 2023 77th Street 11593
## 5 2020 Central 10872
## 6 2021 Central 12203
## 7 2022 Central 16342
## 8 2023 Central 15459
## 9 2020 Devonshire 7028
## 10 2021 Devonshire 7322
## # ℹ 74 more rows
Giải thích kỹ thuật:
group_by(year, area): gom dữ liệu theo từng năm và khu vực, đảm bảo mỗi nhóm thể hiện đúng số vụ xảy ra trong khu vực đó ở từng năm.
summarise() đếm tổng số vụ bằng hàm n().
arrange(area, year) sắp xếp kết quả theo tên khu vực, sau đó theo năm.
Ý nghĩa thống kê:
Khi so sánh các năm, có thể thấy sự phân bố tội phạm không đồng đều giữa các khu vực.
Những nơi như Central, 77th Street và Hollywood thường xuyên nằm trong nhóm có tổng số vụ cao (trên 10.000 vụ mỗi năm), cho thấy đây là các khu vực trung tâm, đông dân cư và nhiều hoạt động xã hội – yếu tố dễ kéo theo phạm pháp.
Ngược lại, các khu vực như Foothill, Hollenbeck, hay Mission có số vụ ít hơn, phản ánh đặc trưng dân cư ổn định hoặc kiểm soát an ninh hiệu quả hơn.
Từ năm 2020 đến 2022, tổng số vụ tăng rõ rệt, đặc biệt ở khu Central, 77th Street và Hollywood. Từ 2023, số vụ có dấu hiệu ổn định hơn, nhưng các khu trung tâm như Central vẫn luôn dẫn đầu toàn thành phố.
Các khu vực như Foothill, Hollenbeck, và Mission thường nằm ở nhóm ít tội phạm hơn.
crime_area_sex <- crime %>%
group_by(area, sex) %>%
summarise(tong_so_vu = n(), .groups = "drop") %>%
arrange(area)
print(crime_area_sex)## # A tibble: 63 × 3
## area sex tong_so_vu
## <chr> <chr> <int>
## 1 77th Street Female 24309
## 2 77th Street Male 17913
## 3 77th Street Unknown 4505
## 4 Central Female 19029
## 5 Central Male 29789
## 6 Central Unknown 6058
## 7 Devonshire Female 12599
## 8 Devonshire Male 13422
## 9 Devonshire Unknown 5362
## 10 Foothill Female 11125
## # ℹ 53 more rows
Giải thích kỹ thuật:
group_by(area, sex): Gom nhóm dữ liệu theo hai biến định tính: khu vực (area) và giới tính (sex).
summarise(tổng số vụ = n()): Tính tần suất (số lượng bản ghi) trong từng nhóm – tức là số vụ tội phạm xảy ra trong từng tổ hợp area–sex.
arrange(area): Sắp xếp kết quả theo tên khu vực.
Ý nghĩa thống kê:
Phần lớn khu vực có nạn nhân nam nhiều hơn nữ. Khu vực Central (Nam 29,789 > Nữ 19,029), North Hollywood (Nam 22,442 > Nữ 15,047), Pacific (Nam 20,741 > Nữ 16,709), Wilshire (Nam 17,579 > Nữ 14,639). Điều này cho thấy hành vi phạm tội xảy ra có xu hướng liên quan nhiều đến nạn nhân nam ở đa số địa bàn.
Chỉ một số khu vực có nữ cao hơn nam gồm: 77th Street (Nữ 24,309 > Nam 17,913), Harbor (Nữ 13,497 > Nam 12,358), Southeast (Nữ 20,006 > Nam 13,658), Southwest (Nữ 20,240 > Nam 16,692). Đây là các “điểm nóng” theo chiều hướng ngược với mặt bằng chung.
Ngoài ra, mật độ nạn nhân là nam ở các khu vực Central (29,789) và Pacific (20,741) là rất cao; ở nhóm nữ, 77th Street (24,309), Southwest (20,240), Southeast (20,006) nổi bật. Các giá trị lớn này có thể phản ánh mật độ dân cư, hoạt động kinh tế–giải trí hoặc điểm tụ tập khiến tần suất va chạm tội phạm cao hơn.
Tỷ lệ “Không xác định giới tính” tuy không chiếm đa số nhưng vẫn có quy mô đáng kể, đặc biệt tại Central (6,058 vụ) và Hollywood (6,688 vụ). Sự tồn tại của nhóm này có thể ảnh hưởng đến việc tính toán và diễn giải tỷ trọng nam–nữ, bởi nếu các bản ghi thiếu giới tính không được phân bổ lại hợp lý, tỷ lệ phần trăm của hai nhóm còn lại (nam và nữ) sẽ bị sai lệch so với thực tế
## `summarise()` has grouped output by 'year'. You can override using the
## `.groups` argument.
Giải thích kỹ thuật:
group_by(year, crime_group): Gom nhóm dữ liệu theo năm và loại tội phạm.
summarise(total = n()): Đếm số lượng bản ghi (số vụ) trong mỗi nhóm.
arrange(crime_group, year): Sắp xếp theo tên nhóm tội phạm, sau đó theo năm.
Ý nghĩa thống kê:
Kết quả thống kê cho thấy sự chênh lệch rõ rệt giữa các nhóm tội phạm trong giai đoạn 2020–2023, phản ánh đặc trưng tội phạm tại Los Angeles:
Nhóm Theft – Robbery (Trộm cắp – Cướp giật) chiếm tỷ trọng cao nhất toàn giai đoạn, tăng mạnh từ 79.227 vụ (2020) lên 105.306 vụ (2022) trước khi giảm nhẹ còn 100.347 vụ (2023). Xu hướng này thể hiện sự bùng phát tội phạm tài sản sau đại dịch COVID-19, có thể do yếu tố kinh tế – xã hội và mức độ phục hồi sinh hoạt đô thị.
Nhóm Violence – Assault (Bạo lực – Hành hung) duy trì ở mức cao, dao động từ 50.320 vụ (2020) lên 54.300 vụ (2023), cho thấy mức độ ổn định nhưng đáng lo ngại về tội phạm có tính đối đầu, có thể liên quan đến mâu thuẫn cá nhân, bạo lực gia đình hoặc xung đột khu vực.
Nhóm Homicide (Giết người) có quy mô nhỏ hơn đáng kể (chỉ vài trăm vụ mỗi năm), nhưng dao động từ 356 vụ (2020) lên 402 vụ (2021) rồi giảm dần còn 326 vụ (2023). Điều này phản ánh xu hướng kiểm soát được phần nào tội phạm đặc biệt nghiêm trọng sau giai đoạn đỉnh năm 2021.
Các nhóm quy mô nhỏ như Sexual – Harassment (Tình dục – Quấy rối), Arson (Phóng hỏa), Fraud – Financial (Gian lận – Tài chính), và Drug-related (Ma túy) duy trì ở mức thấp, dao động nhẹ qua các năm. Cụ thể, Sexual – Harassment ổn định quanh 3.800–4.200 vụ/năm, Arson giảm từ 1.670 xuống 1.541 vụ, Fraud – Financial tăng nhẹ đến 871 vụ (2022) rồi giảm, còn Drug-related chỉ ghi nhận vài vụ mỗi năm. Xu hướng này phản ánh mức kiểm soát tương đối hiệu quả, song vẫn cần lưu ý khả năng báo cáo thiếu trong các nhóm nhạy cảm như tội phạm tình dục và ma túy.
Nhóm Other (Khác) duy trì quanh mức 38.000–39.000 vụ/năm, thể hiện sự tồn tại của nhiều hành vi vi phạm đa dạng nằm ngoài các nhóm chính được phân loại.
Tổng thể, giai đoạn 2020–2023 cho thấy mức độ tội phạm chung tăng nhẹ đến năm 2022 rồi chững lại, trong đó hai nhóm chính Theft – Robbery (Trộm cắp – Cướp giật) và Violence – Assault (Bạo lực – Hành hung) chiếm ưu thế tuyệt đối — là trọng tâm cần được ưu tiên trong phân tích và hoạch định chính sách an ninh đô thị.
crime %>%
group_by(year, crime_group) %>%
summarise(tong_so_vu = n()) %>%
mutate(ty_trong = round(tong_so_vu / sum(tong_so_vu) * 100, 2)) %>%
slice_max(tong_so_vu, n = 3) %>%
arrange(year, desc(tong_so_vu))## `summarise()` has grouped output by 'year'. You can override using the
## `.groups` argument.
Giải thích kỹ thuật:
group_by(year, crime_group): Gom nhóm dữ liệu theo năm và loại tội phạm.
summarise(tong_so_vu = n()): Đếm số lượng bản ghi (số vụ) trong mỗi nhóm.
mutate(ty_trong = round(tong_so_vu / sum(tong_so_vu) * 100, 2))`: Tính tỷ lệ % của mỗi nhóm trong tổng số vụ của năm đó.
slice_max(tong_so_vu, n = 3)`: chọn 3 nhóm phổ biến nhất mỗi năm.
arrange(year, desc(tong_so_vu))`: sắp xếp theo năm và giảm dần theo số vụ.
Ý nghĩa thống kê:
Kết quả cho thấy ba nhóm tội phạm chủ yếu xuyên suốt giai đoạn 2020–2023 là Theft & Robbery (Trộm cắp – Cướp giật), Violence & Assault (Bạo lực – Hành hung) và Other (Khác).
Trong đó, Theft & Robbery luôn chiếm vị trí dẫn đầu, với tỷ trọng tăng từ 45,49% năm 2020 lên đỉnh 51,40% năm 2022, rồi giảm nhẹ còn 50,12% năm 2023. Điều này phản ánh mức độ phổ biến và xu hướng gia tăng của tội phạm tài sản, đặc biệt trong giai đoạn phục hồi kinh tế sau đại dịch.
Ngược lại, Violence & Assault duy trì ổn định quanh mức 26–29%, thể hiện tính dai dẳng của nhóm tội phạm có tính đối đầu trực tiếp. Trong khi đó, Other giảm nhẹ từ 21,82% xuống còn khoảng 19,52%, cho thấy cơ cấu tội phạm đang dần tập trung vào hai nhóm chính nêu trên.
Cấu trúc tội phạm tại Los Angeles nhìn chung ổn định, song tỷ trọng tội phạm tài sản ngày càng chiếm ưu thế, đòi hỏi chính quyền thành phố cần ưu tiên các biện pháp phòng ngừa trộm cắp và cướp giật, đồng thời duy trì kiểm soát chặt chẽ đối với các hành vi bạo lực.
crime %>%
group_by(sex, age_group) %>%
summarise(tong_so_vu = n()) %>%
arrange(sex, desc(tong_so_vu))## `summarise()` has grouped output by 'sex'. You can override using the `.groups`
## argument.
Giải thích kỹ thuật:
group_by(sex, age_group): chia dữ liệu thành từng nhóm theo giới tính (sex) và nhóm tuổi (age_group).
summarise(n()): đếm số lượng bản ghi (số vụ) trong mỗi nhóm → tạo cột tổng số vụ.
arrange(sex, desc(...)): sắp xếp kết quả theo giới tính, và trong từng giới thì xếp giảm dần theo số vụ.
Ý nghĩa thống kê:
Kết quả cho thấy phần lớn vụ án liên quan đến nhóm tuổi Young adult và Middle-aged, với Female Young adult (174.158 vụ) và Male Young adult (165.648 vụ) chiếm tỷ trọng cao nhất trong toàn bộ dữ liệu. Điều này phản ánh tính năng động, tần suất tham gia xã hội cao của nhóm tuổi trẻ, đồng thời cũng là nhóm có nguy cơ cao trở thành nạn nhân hoặc đối tượng liên quan đến tội phạm.
Nhóm Middle-aged đứng thứ hai ở cả hai giới, với nam 110.933 vụ và nữ 93.815 vụ, cho thấy sự lan tỏa của tội phạm sang độ tuổi trưởng thành ổn định hơn, có thể gắn với các hành vi bạo lực hoặc tranh chấp kinh tế.
Nhóm Elderly có số vụ thấp hơn đáng kể (nam 44.994, nữ 36.637), phù hợp với xu hướng giảm dần khả năng tham gia hoặc bị tác động trực tiếp bởi tội phạm khi tuổi cao.
Đáng chú ý, nhóm Unknown chiếm lượng khá lớn ở Juvenile (70.584 vụ) — có thể do thiếu dữ liệu nhận dạng hoặc đặc thù các vụ liên quan đến trẻ em chưa xác định giới tính rõ trong hệ thống ghi nhận. Tình trạng này có thể làm sai lệch tỷ trọng giới tính thật sự, nên cần chuẩn hóa dữ liệu hoặc loại trừ có kiểm soát trước khi tiến hành phân tích sâu hơn.
Dữ liệu cho thấy Female và Male Young adult là hai nhóm chịu tác động nhiều nhất từ tội phạm, phản ánh vấn đề xã hội – tâm lý – kinh tế đặc thù của lứa tuổi trẻ, đồng thời đặt ra yêu cầu về chính sách phòng ngừa và hỗ trợ sớm cho nhóm dân số này.
## `summarise()` has grouped output by 'area'. You can override using the
## `.groups` argument.
Giải thích kỹ thuật:
group_by(area, age_group): Gom nhóm dữ liệu theo hai biến định tính là khu vực (area) và nhóm tuổi (age_group), nhằm xác định tổng số vụ phạm tội xảy ra trong từng tổ hợp khu vực–độ tuổi.
summarise(tong_so_vu = n()): Tính tổng số bản ghi (số vụ) trong từng nhóm, cho phép so sánh quy mô tội phạm giữa các khu vực theo từng nhóm tuổi.
arrange(desc(tong_so_vu)): Sắp xếp kết quả giảm dần theo tổng số vụ.
Ý nghĩa thống kê:
Kết quả cho thấy nhóm tuổi Young adult chiếm ưu thế tuyệt đối tại hầu hết các khu vực, phản ánh rõ xu hướng tội phạm tập trung mạnh ở lứa tuổi trẻ. Các khu vực có số vụ cao nhất thuộc nhóm này gồm Central (28.056 vụ), Southwest (24.903 vụ), 77th Street (21.580 vụ) và Hollywood (21.533 vụ) — đều là những khu vực đông dân, hoạt động kinh tế–xã hội sôi động, dễ phát sinh va chạm và cơ hội phạm tội.
Nhóm Middle-aged đứng thứ hai về quy mô, với các khu vực nổi bật như Central (13.699 vụ), 77th Street (13.137 vụ) và Pacific (11.971 vụ), cho thấy nhóm tuổi này vẫn duy trì mức độ liên quan tương đối cao đến tội phạm, có thể liên quan đến các vụ bạo lực, tranh chấp hoặc hành vi kinh tế – tài chính.
Nhóm Juvenile chiếm tỷ trọng nhỏ hơn nhưng vẫn đáng chú ý tại Central (8.810 vụ) và Pacific (7.666 vụ), phản ánh sự gia tăng các vụ việc liên quan đến thanh thiếu niên đô thị, đặc biệt trong môi trường có mật độ trường học và khu dân cư cao.
Trong khi đó, nhóm Elderly có số vụ thấp nhất ở tất cả các khu vực (thường chỉ vài nghìn vụ), tập trung nhiều ở West LA, Pacific, West Valley — cho thấy đây chủ yếu là nạn nhân hoặc các trường hợp bị ảnh hưởng gián tiếp bởi tội phạm hơn là đối tượng vi phạm.
Kết quả cho thấy xu hướng tập trung mạnh vào nhóm tuổi Young adult tại hầu hết các khu vực, nhất là ở các quận trung tâm và phía nam thành phố, trong khi nhóm Middle-aged và Elderly có quy mô thấp hơn đáng kể. Kết quả này khẳng định yếu tố tuổi tác là biến nhân khẩu học có ảnh hưởng lớn đến nguy cơ tội phạm, đồng thời gợi ý hướng phân tích giao thoa giữa độ tuổi và loại tội phạm hoặc giới tính để làm rõ đặc điểm hành vi phạm pháp theo vùng dân cư.
crime_top_group_area <- crime %>%
group_by(area, crime_group) %>%
summarise(tong_so_vu = n(), .groups = "drop_last") %>%
mutate(ty_trong = round(tong_so_vu / sum(tong_so_vu) * 100, 2)) %>%
slice_max(tong_so_vu, n = 1, with_ties = FALSE) %>%
arrange(desc(tong_so_vu))
print(crime_top_group_area)## # A tibble: 21 × 4
## # Groups: area [21]
## area crime_group tong_so_vu ty_trong
## <chr> <chr> <int> <dbl>
## 1 Central Theft & Robbery 26770 48.8
## 2 Pacific Theft & Robbery 25469 58.0
## 3 West LA Theft & Robbery 22306 61.0
## 4 Wilshire Theft & Robbery 21083 56.2
## 5 Hollywood Theft & Robbery 20714 49.2
## 6 N Hollywood Theft & Robbery 20286 52.8
## 7 Topanga Theft & Robbery 18026 56.0
## 8 Olympic Theft & Robbery 18014 47.0
## 9 Southwest Theft & Robbery 17972 42.5
## 10 Devonshire Theft & Robbery 17920 57.1
## # ℹ 11 more rows
Giải thích kỹ thuật:
group_by(area, crime_group): nhóm dữ liệu theo khu vực và nhóm tội phạm.
summarise(tong_so_vu= n(), .groups = "drop_last")`: n() đếm số dòng trong từng tổ hợp area, .groups = "drop_last": sau summarise, giữ lại mức nhóm ngoài cùng là area và bỏ crime_group.
mutate(ty_trong = round(tong_so_vu / sum(tong_so_vu) * 100, 2))`: sum(tong_so_vu)` tính tổng số vụ của khu vực đó. Tính tỷ trọng (%) của mỗi nhóm tội trong tổng số vụ của khu vực. round(..., 2) làm tròn 2 chữ số thập phân.
slice_max(tong_so_vu, n = 1, with_ties = FALSE)`: Chọn nhóm tội có số vụ lớn nhất trong từng area.
with_ties = FALSE buộc chỉ lấy 1 hàng; nếu có đồng hạng, các hàng khác bị loại.
arrange(desc(tong_so_vu))`: sắp xếp kết quả cuối theo số vụ giảm dần.
Gán kết quả vào crime_top_group_area.
Ý nghĩa thống kê:
Bảng thống kê cho thấy nhóm Theft & Robbery (Trộm cắp – Cướp giật) là nhóm tội phạm phổ biến nhất ở hầu hết các khu vực của Los Angeles, với tỷ trọng dao động từ khoảng 41% đến hơn 60% tổng số vụ trong từng khu vực. Điều này phản ánh rõ tính chất chiếm ưu thế của tội phạm xâm phạm tài sản, đặc biệt ở các khu vực đông dân và hoạt động kinh tế – thương mại sôi động như West LA, Pacific, Wilshire hay Central.
Ngược lại, một số khu vực như 77th Street và Southeast lại có nhóm Violence & Assault (Bạo lực – Hành hung) đứng đầu, chiếm tỷ trọng đáng kể (khoảng 38–40%), cho thấy đặc thù tội phạm thiên về hành vi xâm hại thân thể tại các vùng này.
Nhìn chung, cơ cấu tội phạm giữa các khu vực cho thấy sự chênh lệch rõ rệt về loại hình tội phạm chiếm ưu thế — các khu vực trung tâm và ven biển chủ yếu đối mặt với tội phạm tài sản, trong khi khu vực phía nam và đông nam có xu hướng tập trung các vụ việc mang tính bạo lực cao hơn, phản ánh sự khác biệt về điều kiện kinh tế – xã hội và mức độ an ninh cộng đồng giữa các vùng trong thành phố.
crime_avg_age_year <- crime %>%
group_by(age_group, year) %>%
summarise(total_cases = n(), .groups = "drop_last") %>%
group_by(age_group) %>%
summarise(
avg_cases_per_year = round(mean(total_cases), 1),
sd_cases = round(sd(total_cases), 1),
year_max = year[which.max(total_cases)],
max_cases = max(total_cases),
year_min = year[which.min(total_cases)],
min_cases = min(total_cases)
)
print(crime_avg_age_year)## # A tibble: 4 × 7
## age_group avg_cases_per_year sd_cases year_max max_cases year_min min_cases
## <chr> <dbl> <dbl> <chr> <int> <chr> <int>
## 1 Elderly 20448. 1624. 2022 21896 2020 18634
## 2 Juvenile 31590. 5059. 2023 38395 2021 27282
## 3 Middle-aged 51314. 2786. 2022 55133 2020 48550
## 4 Young adult 86791. 7054 2022 95400 2020 78752
Giải thích kỹ thuật:
group_by(age_group, year): nhóm dữ liệu theo nhóm tuổi và năm.
summarise(total_cases = n(), .groups = "drop_last"): n() đếm số bản ghi trong mỗi tổ hợp age_group × year ⇒ số vụ theo nhóm tuổi – năm. .groups = "drop_last": sau khi tổng hợp, bỏ mức nhóm trong cùng (year), giữ age_group. Kết quả là bảng vẫn đang grouped theo age_group.
group_by(age_group): đảm bảo các phép tính tiếp theo diễn ra trong từng nhóm tuổi.
summarise(...): tạo bảng thống kê gọn cho mỗi nhóm tuổi:
avg_cases_per_year: trung bình số vụ/năm (làm tròn 1 chữ số thập phân).
sd_cases: độ lệch chuẩn của số vụ qua các năm, làm tròn 1 chữ số.
year_max: năm có tổng số vụ lớn nhất trong nhóm tuổi (which.max trả về chỉ số phần tử max đầu tiên).
max_cases: tổng số vụ cao nhất trong nhóm.
year_min: năm có tổng số vụ thấp nhất trong nhóm (which.min).
min_cases: tổng số vụ thấp nhất trong nhóm.
print(...): in bảng kết quả.
Ý nghĩa thống kê:
Bảng thống kê cho thấy số vụ phạm tội có nạn nhân là Young adult (Thanh niên) chiếm tỷ trọng cao nhất, với avg_cases_per_year = 86.791 (trung bình vụ/năm), độ lệch chuẩn lớn (sd_cases = 7.054 (độ lệch chuẩn số vụ)) thể hiện sự dao động mạnh qua các năm, đặc biệt tăng cao nhất vào năm year_max = 2022 (năm có số vụ cao nhất) với max_cases = 95.400 vụ (số vụ cao nhất trong nhóm).
Tiếp đến là nhóm Middle-aged (Trung niên) với trung bình 51.314 vụ/năm, biến động ở mức vừa phải, cũng đạt đỉnh vào 2022, cho thấy giai đoạn này tội phạm ảnh hưởng rõ rệt đến lực lượng lao động chính trong xã hội.
Nhóm Juvenile (Vị thành niên) ghi nhận 31.590 vụ/năm, có độ lệch chuẩn tương đối lớn (5.059) và đạt mức cao nhất năm 2023 — phản ánh xu hướng tội phạm liên quan đến trẻ vị thành niên có xu hướng tăng trong giai đoạn gần đây.
Trong khi đó, nhóm Elderly (Cao tuổi) có trung bình thấp nhất (20.448 vụ/năm) và mức biến động nhỏ hơn, cho thấy tần suất xảy ra tội phạm đối với người lớn tuổi ổn định và ít biến động hơn so với các nhóm khác.
Tổng thể, số liệu cho thấy xu hướng gia tăng rõ rệt trong năm 2022–2023, tập trung mạnh ở nhóm Young adult (Thanh niên) và Juvenile (Vị thành niên), phản ánh sự thay đổi trong cơ cấu độ tuổi chịu ảnh hưởng của tội phạm tại Los Angeles giai đoạn nghiên cứu.
tbl_summary_year <- crime %>%
group_by(year) %>%
summarise(
total_cases = n(),
arrested_pct = round(100 * mean(arrested == "arrested"), 2),
armed_pct = round(100 * mean(weapon_group != "No weapon" & !is.na(weapon_group)), 2),
serious_pct = round(100 * mean(severity_label == "Serious"), 2),
.groups = "drop"
) %>%
arrange(year)
print(tbl_summary_year)## # A tibble: 4 × 5
## year total_cases arrested_pct armed_pct serious_pct
## <chr> <int> <dbl> <dbl> <dbl>
## 1 2020 174179 0 41.9 0
## 2 2021 181318 0 40.8 0
## 3 2022 204868 0 38.0 0
## 4 2023 200207 0 39.3 0
Giải thích kỹ thuật:
crime %>%: Dùng pipe operator (%>%) để chuyền dữ liệu từ crime vào chuỗi thao tác tiếp theo.
group_by(year): Nhóm dữ liệu theo từng năm, để tính toán các chỉ tiêu thống kê theo năm.
summarise(...): Tổng hợp dữ liệu cho mỗi nhóm năm, tạo ra các biến mới:
total_cases = n(): Đếm tổng số vụ phạm tội trong năm.
arrested_pct = round(100 * mean(arrested == "arrested"), 2):
arrested == "arrested" tạo biến logic TRUE/FALSE.
mean(...) tính trung bình các giá trị TRUE (TRUE=1, FALSE=0), tức là tỷ lệ vụ đã bắt giữ.
Nhân 100 để ra phần trăm và round(..., 2) làm tròn 2 chữ số thập phân.
armed_pct = round(100 * mean(weapon_group != "No weapon" & !is.na(weapon_group)), 2):
weapon_group != "No weapon": TRUE nếu vụ có vũ khí.
!is.na(weapon_group): loại bỏ các giá trị NA để không làm sai lệch tỷ lệ.
mean(...) * 100 → tỷ lệ phần trăm vụ có vũ khí, làm tròn 2 chữ số.
serious_pct = round(100 * mean(severity_label == "Serious"), 2): Tính tỷ lệ vụ nghiêm trọng (%).
.groups = "drop": Sau summarise(), bỏ grouping để kết quả trả về là data frame bình thường, không còn nhóm.
arrange(year): Sắp xếp bảng theo thứ tự năm tăng dần.
print(tbl_summary_year): In bảng tổng hợp ra màn hình.
Ý nghĩa thống kê:
Bảng kết quả cho thấy sự biến động đáng chú ý của tội phạm tại Los Angeles giai đoạn 2020–2023.
Tổng số vụ (total_cases) tăng mạnh từ 174.179 vụ năm 2020 lên 204.868 vụ năm 2022, sau đó giảm nhẹ xuống 200.207 vụ năm 2023, cho thấy xu hướng gia tăng tội phạm rõ rệt trong hai năm đầu hậu đại dịch rồi bắt đầu ổn định trở lại.
Tỷ lệ đã bắt giữ (arrested_pct) giảm dần qua các năm (từ 11,49% xuống 9,17%), phản ánh khả năng truy bắt có xu hướng giảm tương đối so với quy mô tội phạm, có thể do khối lượng vụ việc lớn hơn hoặc nguồn lực điều tra bị phân tán.
Tỷ lệ có vũ khí (armed_pct) trong các vụ án cũng giảm từ 41,87% năm 2020 xuống 37,95% năm 2022, sau đó tăng nhẹ năm 2023 (39,27%), cho thấy xu hướng giảm tội phạm sử dụng vũ khí nhưng vẫn duy trì ở mức cao.
Tỷ lệ vụ nghiêm trọng (serious_pct) duy trì quanh 51–54%, với năm 2023 đạt mức cao nhất 54,40%, cho thấy dù tổng số vụ có xu hướng ổn định, mức độ nghiêm trọng của tội phạm lại có dấu hiệu tăng.
Tổng thể, dữ liệu phản ánh tội phạm gia tăng về số lượng trong giai đoạn 2020–2022, đồng thời chuyển dịch theo hướng tinh vi và nghiêm trọng hơn trong năm 2023.
crime %>%
group_by(year, crime_group, sex) %>%
summarise(tong_so_vu = n(), .groups = "drop") %>% # bỏ drop_last để gọn
group_by(year, crime_group) %>%
mutate(ty_le = round(tong_so_vu / sum(tong_so_vu) * 100, 2)) %>%
filter(sex == "Female") %>%
group_by(year) %>%
slice_max(ty_le, n = 3, with_ties = FALSE) %>%
arrange(year, desc(ty_le))Giải thích kỹ thuật:
group_by(year, crime_group, sex): gom dữ liệu theo năm, nhóm tội và giới tính.
summarise(tong_so_vu = n(), .groups = "drop"): đếm số vụ trong mỗi tổ hợp; .groups = "drop" để bỏ nhóm tạm thời sau khi tổng hợp.
mutate(ty_le = round(tong_so_vu / sum(tong_so_vu) * 100, 2)): tính tỷ lệ phần trăm số vụ của từng giới trong mỗi nhóm tội.
filter(sex == "Female"): chỉ giữ các dòng tương ứng với nạn nhân nữ.
group_by(year): nhóm lại theo năm để chọn top trong từng năm riêng biệt.
slice_max(ty_le, n = 3, with_ties = FALSE): chọn 3 nhóm tội có tỷ lệ nạn nhân nữ cao nhất mỗi năm.
arrange(year, desc(ty_le)): sắp xếp kết quả theo năm và tỷ lệ giảm dần.
Ý nghĩa thống kê:
Kết quả cho thấy nữ giới (Female) chiếm tỷ lệ cao nhất trong các vụ “Sexual & Harassment” (Tội phạm tình dục – quấy rối), với mức ổn định quanh 73–75% qua các năm 2020–2023. Điều này phản ánh đặc trưng giới rõ rệt của nhóm tội phạm này, khi phần lớn nạn nhân là phụ nữ, đặc biệt trong các hành vi xâm hại và quấy rối tình dục.
Nhóm “Violence & Assault” (Bạo lực – Hành hung) đứng thứ hai với tỷ lệ khoảng 50–51%, cho thấy nạn nhân nữ và nam chịu ảnh hưởng tương đối cân bằng. Tuy nhiên, việc tỷ lệ nữ duy trì quanh mức một nửa tổng số vụ cũng cảnh báo mức độ lan rộng của bạo lực giới trong cộng đồng.
Nhóm “Other” (Khác) duy trì tỷ lệ 40–41%, phản ánh rằng nữ giới cũng là đối tượng bị tác động đáng kể trong các hành vi phạm pháp không thuộc nhóm chính (như đe dọa, xâm nhập, hoặc vi phạm dân sự).
Nhìn chung, nữ giới (Female) thường là nạn nhân chính trong các tội phạm liên quan đến tình dục và bạo lực thể chất, và xu hướng này ổn định qua các năm, cho thấy vấn đề an toàn và bảo vệ phụ nữ vẫn là thách thức lớn trong công tác phòng chống tội phạm tại Los Angeles.
crime %>%
group_by(crime_group, severity_label) %>%
summarise(so_vu = n()) %>%
mutate(ty_le = round(so_vu / sum(so_vu) * 100, 2))## `summarise()` has grouped output by 'crime_group'. You can override using the
## `.groups` argument.
Giải thích kỹ thuật:
group_by(crime_group, severity_label): gom dữ liệu theo nhóm tội phạm và mức độ.
summarise(so_vu = n())`: đếm số bản ghi cho từng tổ hợp → số vụ theo crime_group × severity_label.
mutate(ty_le = round(so_vu/ sum(so_vu) * 100, 2))`: tính tỷ lệ % của mỗi mức độ trong nhóm tội tương ứng, rồi làm tròn 2 chữ số.
Ý nghĩa thống kê:
Homicide (Giết người): 100% Severe (Nghiêm trọng) — toàn bộ vụ giết người đều được đánh giá mức nghiêm trọng, phản ánh bản chất cực kỳ nguy hiểm của hành vi này.
Fraud & Financial Crime (Gian lận – tài chính) và Drug-related (Ma túy): 100% Minor (Nhẹ) — các vụ này trong dữ liệu hiện tại đều được đánh giá mức nhẹ, tức không gây nguy hiểm trực tiếp cho thân thể hay tính mạng.
Arson (Phóng hỏa): 60,75% Severe (Nghiêm trọng), 39,25% Minor (Nhẹ) — phần lớn vụ phóng hỏa gây hậu quả đáng kể, rủi ro an toàn cao, nhưng vẫn có một phần vụ mức độ nhẹ.
Violence & Assault (Bạo lực – hành hung): 30,11% Severe / 69,89% Minor — đa số vụ nhẹ, nhưng tỷ lệ nghiêm trọng vẫn đáng kể, phản ánh rủi ro tổn hại thân thể không nhỏ.
Sexual & Harassment (Tình dục – quấy rối): 34,82% Severe / 65,18% Minor — gần 1/3 vụ nghiêm trọng, nhấn mạnh nhu cầu bảo vệ nạn nhân nữ, đặc biệt với các hành vi xâm hại và quấy rối.
Theft & Robbery (Trộm cắp – cướp giật): 81,96% Severe / 18,04% Minor — phần lớn vụ xâm phạm tài sản được đánh giá nghiêm trọng, cần lưu ý cách phân loại mức độ trong dataset.
Other + Small Groups (Khác + các nhóm nhỏ): 84,25% Minor / 15,75% Severe — đây là các nhóm còn lại, bao gồm các hành vi rải rác như đe dọa, xâm nhập, vi phạm dân sự… phần lớn ở mức độ nhẹ.
tbl_severity_year <- crime %>%
group_by(year, severity_label) %>%
summarise(
num_cases = n(),
pct_cases = round(num_cases / sum(num_cases) * 100, 2),
.groups = "drop"
) %>%
tidyr::pivot_wider(
names_from = severity_label,
values_from = c(num_cases, pct_cases),
names_sep = "_"
)
print(tbl_severity_year)## # A tibble: 4 × 5
## year num_cases_Minor num_cases_Severe pct_cases_Minor pct_cases_Severe
## <chr> <int> <int> <dbl> <dbl>
## 1 2020 83455 90724 100 100
## 2 2021 85758 95560 100 100
## 3 2022 98907 105961 100 100
## 4 2023 91292 108915 100 100
Giải thích kỹ thuật:
group_by(year, severity_label): Gom dữ liệu theo năm (year) và mức độ nghiêm trọng.
summarise(num_cases = n(), ...): n() đếm số bản ghi trong mỗi nhóm → số vụ phạm tội tương ứng với từng năm và mức độ. .groups = "drop" loại bỏ thông tin nhóm sau khi tổng hợp, giúp kết quả là bảng phẳng để xử lý tiếp. pct_cases = round(num_cases / sum(num_cases) * 100, 2)
sum(num_cases) tính tổng số vụ trong năm đó.
round(..., 2) làm tròn 2 chữ số thập phân để dễ đọc.
tidyr::pivot_wider(...): Chuyển bảng từ dạng dài (long) sang dạng rộng (wide).
names_from = severity_label: dùng tên mức độ làm tên cột mới.
values_from = c(num_cases, pct_cases): lấy giá trị số vụ và tỷ lệ % điền vào các cột tương ứng.
names_sep = "_": thêm dấu gạch dưới giữa tiền tố và tên mức độ.
Ý nghĩa thống kê:
Số vụ “Minor” (nhẹ) tăng từ 83.455 vụ năm 2020 lên 98.907 vụ năm 2022, sau đó giảm xuống 91.292 vụ năm 2023. Số vụ “Severe” (nghiêm trọng) liên tục tăng từ 90.724 vụ năm 2020 lên 108.915 vụ năm 2023. Điều này phản ánh xu hướng tổng số vụ nhẹ giảm nhẹ, nhưng các vụ nghiêm trọng vẫn gia tăng.
Cả hai mức độ “Minor” và “Severe” đều được tính 100% trong dataset hiện tại, nghĩa là dữ liệu phân loại vụ nhẹ/nghiêm trọng đầy đủ, không có giá trị thiếu. Điều này giúp việc phân tích theo mức độ nghiêm trọng chính xác, nhưng lưu ý rằng tỷ lệ thực tế trong cộng đồng có thể khác do cách ghi nhãn dữ liệu.
Dữ liệu cho thấy xu hướng gia tăng các vụ nghiêm trọng qua các năm, trong khi số vụ nhẹ biến động không lớn. Điều này gợi ý rằng mặc dù tổng số vụ có thể ổn định hoặc giảm nhẹ, mức độ nghiêm trọng của tội phạm có dấu hiệu tăng, cần chú trọng vào các biện pháp phòng ngừa và bảo vệ cộng đồng.
crime %>%
group_by(year, arrested) %>%
summarise(tong_so_vu = n()) %>%
group_by(year) %>%
mutate(ty_le = round(tong_so_vu / sum(tong_so_vu) * 100, 2))## `summarise()` has grouped output by 'year'. You can override using the
## `.groups` argument.
Giải thích kỹ thuật:
group_by(year, arrested): gom nhóm dữ liệu theo năm và tình trạng vụ án.
summarise(tong_so_vu = n()): đếm tổng số vụ trong từng nhóm.
group_by(year) và mutate(ty_le = round(tong_so_vu / sum(tong_so_vu) * 100, 2)): dùng để tính tỷ lệ phần trăm của từng loại tình trạng trong tổng số vụ mỗi năm, làm tròn 2 chữ số thập phân.
Ý nghĩa thống kê:
Qua các năm 2020–2023, số vụ được bắt giữ (Arrested) chiếm tỷ lệ thấp, khoảng 9–11% so với tổng số vụ, trong khi phần lớn vụ việc (Not arrested) không dẫn đến bắt giữ.
Tỷ lệ bắt giữ giảm dần từ 11,49% năm 2020 xuống 9,17% năm 2023, cho thấy khả năng truy bắt có xu hướng giảm so với quy mô tội phạm, có thể do tăng khối lượng vụ việc hoặc hạn chế về nguồn lực điều tra.
Dữ liệu phản ánh rằng mặc dù tổng số vụ có biến động (tăng giai đoạn 2020–2022, giảm nhẹ 2023), khả năng xử lý và bắt giữ vẫn chưa tăng, cho thấy cần tập trung cải thiện hiệu quả điều tra và phân bổ nguồn lực.
crime %>%
group_by(year) %>%
summarise(tong_so_vu = n()) %>%
mutate(tang_giam = round((tong_so_vu - lag(tong_so_vu)) / lag(tong_so_vu) * 100, 2))Giải thích kỹ thuật:
group_by(year): nhóm dữ liệu theo từng năm.
summarise(n()): đếm tổng số vụ tội phạm từng năm.
mutate(...): tính tỷ lệ tăng/giảm so với năm trước bằng công thức chênh lệch phần trăm.
lag() dùng để lấy giá trị của năm liền kề trước, giúp tính biến động năm–năm.
Ý nghĩa thống kê:
Bảng cho thấy xu hướng biến động tổng số vụ phạm tội tại Los Angeles giai đoạn 2020–2023:
Năm 2020 là năm khởi đầu chuỗi dữ liệu, nên không có giá trị so sánh.
Năm 2021, tổng số vụ tăng 4,10% so với năm 2020, phản ánh giai đoạn thành phố bắt đầu mở cửa trở lại sau các biện pháp giãn cách, dẫn đến hoạt động xã hội và nguy cơ phạm pháp gia tăng.
Năm 2022, mức tăng đạt 12,99%, là mức tăng cao nhất trong toàn kỳ, cho thấy sự bùng phát rõ rệt của tội phạm — có thể do áp lực kinh tế, thất nghiệp và các yếu tố hậu đại dịch.
Năm 2023, tổng số vụ giảm nhẹ 2,28%, đánh dấu tín hiệu ổn định trong an ninh trật tự, có khả năng phản ánh hiệu quả của các chính sách kiểm soát tội phạm hoặc tăng cường tuần tra của LAPD.
Nhìn chung, giai đoạn 2020–2022 chứng kiến xu hướng gia tăng mạnh, sau đó có dấu hiệu hạ nhiệt vào năm 2023 — cho thấy mối liên hệ giữa bối cảnh xã hội và sự biến động của hoạt động phạm tội.
crime %>%
group_by(crime_group, sex) %>%
summarise(tuoi_trung_binh = round(mean(age, na.rm = TRUE), 1))## `summarise()` has grouped output by 'crime_group'. You can override using the
## `.groups` argument.
Giải thích kỹ thuật:
group_by(crime_group, sex): kết hợp hai biến phân loại.
mean(age, na.rm = TRUE): tính tuổi trung bình, loại bỏ giá trị thiếu.
Ý nghĩa thống kê:
Ở nhóm bạo lực – hành hung, nạn nhân nam (≈37,8 tuổi) và nữ (≈35,8 tuổi) chiếm đa số, cho thấy tội phạm này thường xảy ra trong nhóm người trưởng thành đang ở độ tuổi lao động, nơi xung đột xã hội và mâu thuẫn cá nhân dễ phát sinh.
Với gian lận – tài chính, nạn nhân nữ có tuổi trung bình cao nhất (≈52,1 tuổi), cao hơn nam giới (≈42,5 tuổi). Điều này hợp lý vì tội phạm tài chính thường nhắm tới người có tài sản, kinh nghiệm và khả năng tài chính – nhóm tuổi trung niên trở lên.
Giết người cho thấy tuổi nạn nhân nam và nữ tương đối tương đồng (≈36–38 tuổi), phản ánh đặc trưng tội phạm mang tính cá nhân hoặc mâu thuẫn xã hội.
Nhóm trộm cắp – cướp giật có tuổi trung bình nạn nhân nam (≈37,8) và nữ (≈40,7), vẫn nằm trong độ tuổi lao động – nhóm thường xuyên di chuyển và mang theo tài sản, nên dễ trở thành mục tiêu.
Tình dục – quấy rối có nạn nhân nữ trẻ hơn (≈30,1 tuổi), thấp hơn đáng kể so với nam (≈34,1 tuổi), cho thấy nhóm nữ thanh niên là đối tượng chịu rủi ro cao nhất trong tội phạm mang yếu tố giới.
Các nhóm ma túy, phóng hỏa và khác có tuổi trung bình biến động lớn, phần “không xác định” xuất hiện với giá trị thấp (≈2–3 tuổi) chủ yếu do lỗi ghi nhận hoặc trường hợp nạn nhân trẻ em, bào thai hoặc dữ liệu không đầy đủ.
Tổng thể, bảng chỉ ra rằng tội phạm tác động mạnh nhất đến nhóm tuổi lao động (30–45 tuổi), với sự khác biệt rõ giữa giới tính ở từng loại tội. Nữ giới thường chịu thiệt hại nhiều hơn trong các tội liên quan đến tình dục và tài chính, trong khi nam giới nổi bật ở các tội bạo lực và cướp giật
library(dplyr)
crime %>%
group_by(area) %>%
summarise(
total_cases = n(),
severe_pct = round(mean(severity_label == "Severe") * 100, 2),
.groups = "drop"
) %>%
mutate(risk_level = case_when(
severe_pct > 55 ~ "Rất cao",
severe_pct > 45 ~ "Cao",
TRUE ~ "Trung bình - thấp"
))Giải thích kỹ thuật:
group_by(area): nhóm dữ liệu theo khu vực.
summarise(...): tính số vụ và tỷ lệ vụ nghiêm trọng (Severe).
mutate(risk_level = case_when(...)): phân loại mức rủi ro dựa trên tỷ lệ vụ nghiêm trọng.
round(..., 2): làm tròn 2 chữ số thập phân.
Ý nghĩa thống kê:
Kết quả cho thấy hầu hết các khu vực ở Los Angeles đều thuộc nhóm “Cao” về tỷ lệ vụ nghiêm trọng, phản ánh mức độ tội phạm nghiêm trọng phổ biến trên diện rộng. Một số khu vực nổi bật với mức “Rất cao”, gồm Central (59,32%), Pacific (60,97%), West LA (57,76%) và Wilshire (57,66%), đều là các khu trung tâm, ven biển hoặc tập trung thương mại – môi trường đông dân cư và du khách, dẫn đến nguy cơ tội phạm xâm phạm tài sản và bạo lực cao hơn.
Các khu khác như Hollywood (55,0%), N Hollywood (53,5%) và Devonshire (53,0%), dù chỉ ở mức “Cao”, nhưng tỷ lệ nghiêm trọng trên 50% vẫn cho thấy nguy cơ tổn hại không nhỏ.
Trong khi đó, các khu Foothill (45,98%), Mission (45,85%) và Southeast (47,02%) nằm sát ngưỡng “Trung bình – Cao”, cho thấy môi trường tội phạm được kiểm soát tương đối tốt, nhưng vẫn tiềm ẩn rủi ro.
Tổng thể, bảng thể hiện rõ mức độ chênh lệch về an ninh đô thị, với khu trung tâm và kinh tế sôi động chịu nhiều tội phạm nghiêm trọng hơn, còn vùng ngoại vi hoặc dân cư ổn định có rủi ro thấp hơn.
library(dplyr)
library(ggplot2)
crime %>%
group_by(area) %>%
summarise(total_cases = n()) %>%
arrange(desc(total_cases)) %>%
slice_head(n=10) %>%
ggplot(aes(x=reorder(area, -total_cases), y=total_cases)) +
geom_col(fill='#5A9F68') +
geom_text(aes(label=total_cases), vjust=-0.5) +
labs(x='Khu vực', y='Số vụ', title ='Top 10 khu vực có số vụ nhiều nhất') +
theme(plot.title = element_text(hjust = 0.5))Giải thích kỹ thuật:
library(dplyr) / library(ggplot2): Nạp hai package dplyr (xử lý dữ liệu) và ggplot2 (vẽ biểu đồ).
crime %>%: Bắt đầu một chuỗi thao tác (pipe) — truyền crime vào các hàm tiếp theo theo thứ tự.
group_by(area): Gom các bản ghi theo biến area (mỗi nhóm tương ứng một khu vực).
summarise(total_cases = n()): Tạo một bảng tổng hợp mới với một cột total_cases là kết quả đếm (n()) số bản ghi trong mỗi nhóm area. Kết quả là dữ liệu dạng (area, total_cases).
arrange(desc(total_cases)): Sắp xếp bảng tổng hợp giảm dần theo total_cases — các khu vực có số vụ lớn nhất lên trước.
slice_head(n=10): Lấy 10 hàng đầu tiên theo nhóm arrange.
ggplot(aes(x = reorder(area, -total_cases), y = total_cases)): Khởi tạo đồ họa: ánh xạ x là area, y là total_cases.
reorder(area, -total_cases) sắp xếp các nhãn area theo thứ tự giảm dần của total_cases khi vẽ (dấu - là giảm dần). Việc này đảm bảo cột cao nhất nằm bên trái khi biểu đồ đứng.
geom_col(fill=' '): Vẽ cột (bar chart) với chiều cao theo y và tô màu đỏ cho các cột.
geom_text(aes(label = total_cases), vjust = -0.5): Thêm nhãn số lên trên mỗi cột, hiển thị giá trị total_cases. **vjust = -0.5** dịch nhãn cao hơn một chút so với đỉnh cột để không chồng lên cột.
labs(x='Khu vực', y='Số vụ', title ='Top 10 khu vực có số vụ nhiều nhất'): Thiết lập nhãn trục và tiêu đề biểu đồ.
theme(plot.title = element_text(hjust = 0.5)): Căn giữa tiêu đề bằng thuộc tính hjust = 0.5.
Ý nghĩa thống kê:
Tổng số vụ ở Top 10: 417.784 vụ.
Central chiếm 54.856 vụ (≈13.13%) cao một cách rõ rệt so với khu vực đứng sau.
Các vị trí tiếp theo bao gồm 77th Street 46.669 vụ (≈11.17%), Pacific 43.834 vụ (≈10.49%), Southwest: 42.286 vụ (≈10.12%), Hollywood 42.089 vụ (≈10.07%)
Nhóm giữa (N Hollywood, Olympic, Wilshire, Southeast, West LA) mỗi khu vực chiếm khoảng 8.7%–9.2%.
Nhìn chung, 5 khu vực hàng đầu (Central → Hollywood) chiếm ~55% của tổng Top 10 (cộng lại khoảng 55% của 417k) — tức là số vụ tập trung nhiều vào các khu vực trung tâm thượng mại, giải trí, nơi có mật độ dân số cao.
crime %>%
group_by(age_group, severity_label) %>%
summarise(total_cases = n(), .groups = "drop") %>%
ggplot(aes(x = age_group, y = total_cases, fill = severity_label)) +
geom_col(position = "dodge", width = 0.8) +
geom_text(aes(label = total_cases),
position = position_dodge(width = 0.8),
vjust = -0.5, size = 3, color = "black") +
scale_fill_manual(values = c("Severe" = "#ff8fab","Minor" = "#6a994e")) +
labs(x = "Nhóm tuổi",
y = "Số vụ",
fill = "Mức độ phạm tội",
title = "Thống kê mức độ phạm tội theo nhóm tuổi") +
theme_minimal(base_size = 13) +
theme(plot.title = element_text(hjust = 0.5, face = "bold", color = "#3b3b3b"),
legend.position = "right",
legend.title = element_text(face = "bold"))Giải thích kỹ thuật:
group_by(age_group, severity_label): gom dữ liệu theo 2 biến nhóm tuổi và nhãn mức độ phạm tội. Kết quả tóm tắt sẽ tính trên từng tổ hợp (age_group, severity_label).
summarise(total_cases = n(), .groups = "drop"): tạo cột total_cases là số quan sát trong mỗi tổ hợp; .groups = "drop" loại bỏ grouping metadata sau khi summarise (tránh cảnh báo của dplyr mới).
aes(...) định nghĩa ánh xạ: trục x là age_group, trục y là total_cases, màu (fill) theo severity_label.geom_col() vẽ cột, sử dụng giá trị y trực tiếp từ total_cases.
position = "dodge": đặt các cột của cùng một age_group nhưng khác severity_label sát cạnh nhau (không xếp chồng). width = 0.8: bề rộng cột. vjust = -0.5: dịch nhãn lên phía trên đỉnh cột một chút (âm → lên trên). size = 3: kích thước chữ. color = "black": màu chữ.
base_size = 13: kích thước font cơ bản.
plot.title = element_text(hjust = 0.5, ...): căn giữa tiêu đề, bôi đậm, đổi màu.
legend.position = "right": đưa legend (chú giải) ra bên phải biểu đồ.
legend.title = element_text(face = "bold"): in đậm tiêu đề legend
Ý nghĩa thống kê:
Nhóm “Thanh niên” có số vụ phạm tội cao nhất ở cả hai mức độ: nghiêm trọng (~184.612 vụ) và nhẹ (~162.413 vụ), cho thấy đây là độ tuổi tham gia và bị ảnh hưởng nhiều nhất trong các vụ án. Tiếp đến là “Trung niên”, với hơn 100.000 vụ ở mỗi mức độ – phản ánh tỷ lệ phạm tội vẫn đáng kể ở nhóm tuổi này, có thể do áp lực xã hội, kinh tế hoặc nghề nghiệp.
Trong khi đó, hai nhóm “Vị thành niên” và “Cao tuổi” có số vụ thấp hơn rõ rệt, chứng tỏ hành vi phạm tội hoặc khả năng trở thành nạn nhân giảm dần ở hai đầu độ tuổi.
Đáng chú ý, ở hầu hết các nhóm tuổi, số vụ nghiêm trọng thường cao hơn hoặc tương đương số vụ nhẹ, cho thấy tội phạm tại khu vực có xu hướng nghiêm trọng hóa hành vi phạm pháp.
Từ góc độ thống kê, biểu đồ phản ánh mối quan hệ rõ ràng giữa độ tuổi và mức độ nghiêm trọng của tội phạm, giúp xác định nhóm tuổi trọng điểm cần được can thiệp. Đặc biệt, “Thanh niên” là nhóm rủi ro cao nhất, cần được chú trọng trong các chương trình giáo dục pháp luật, định hướng nghề nghiệp, quản lý xã hội và hỗ trợ tâm lý, nhằm giảm thiểu khả năng phạm tội và tái phạm.
crime %>%
group_by(year, age_group) %>%
summarise(total_cases = n(), .groups = "drop") %>%
ggplot(aes(x = age_group, y = total_cases, fill = age_group)) +
geom_col() +
facet_wrap(~year) +
labs(x = 'Nhóm tuổi', y = 'Số vụ', title = 'Số vụ theo nhóm tuổi qua các năm') +
theme(axis.text.x = element_blank()) +
theme(plot.title = element_text(hjust = 0.5))Giải thích kỹ thuật:
group_by(year, age_group): gom theo năm và nhóm tuổi để tính tổng số vụ cho mỗi tổ hợp.
summarise(total_cases = n(), .groups = "drop"): đếm số vụ và bỏ thông tin nhóm để tránh cảnh báo.
ggplot(aes(x = age_group, y = total_cases, fill = age_group)): ánh xạ trục x là nhóm tuổi, trục y là tổng số vụ; fill để tô màu phân biệt nhóm tuổi.
geom_col(): vẽ cột từ dữ liệu đã tóm tắt.
facet_wrap(~year): tách biểu đồ theo từng năm, thuận tiện so sánh theo thời gian.
theme(axis.text.x = element_blank()): ẩn nhãn trục x.
labs(...) và theme(plot.title = element_text(hjust = 0.5)): đặt nhãn trục/tiêu đề và căn giữa tiêu đề.
Ý nghĩa thống kê:
Nhìn chung, tổng số vụ thay đổi nhẹ theo từng năm, nhưng cơ cấu theo nhóm tuổi hầu như không thay đổi. Ở tất cả các năm, nhóm thanh niên luôn chiếm tỷ lệ nạn nhân cao nhất, dao động từ khoảng 90.000 đến hơn 100.000 vụ mỗi năm.
Nhóm trung niên đứng thứ hai với khoảng 50.000–60.000 vụ mỗi năm, cho thấy sự ổn định và ít biến động. Nhóm vị thành niên dao động quanh mức 30.000 vụ, thể hiện rủi ro đáng kể đối với trẻ em và thiếu niên, dù thấp hơn thanh niên nhưng vẫn cần được quan tâm đặc biệt.
Nhóm cao tuổi luôn có số vụ thấp nhất và gần như không thay đổi nhiều qua các năm (~20.000 vụ), điều này phản ánh việc người cao tuổi ít ra ngoài hoặc có lối sống ít rủi ro hơn, song vẫn là nhóm dễ bị tổn thương trong các tội phạm như lừa đảo hoặc bạo hành gia đình.
crime %>%
group_by(crime_group, sex) %>%
summarise(total_cases = n(), .groups = "drop") %>%
group_by(crime_group) %>%
mutate(pct = total_cases / sum(total_cases) * 100) %>%
ggplot(aes(x = reorder(crime_group, -pct), y = pct, fill = sex)) +
geom_bar(stat = "identity", position = "stack", width = 0.7) +
geom_text(aes(label = paste0(round(pct, 1), "%")),
position = position_stack(vjust = 0.5), size = 3, color = "black") +
scale_fill_brewer(palette = "Set4") +
labs(
title = "Cơ cấu giới tính trong từng nhóm tội phạm",
x = "Nhóm tội phạm", y = "Tỷ lệ (%)", fill = "Giới tính"
) +
theme_minimal(base_size = 13) +
theme(
plot.title = element_text(hjust = 0.5, face = "bold"),
axis.text.x = element_text(angle = 45, hjust = 1)
)## Warning: Unknown palette: "Set4"
Giải thích kỹ thuật:
group_by(crime_group, sex): Gom dữ liệu theo 2 biến phân loại nhóm tội phạm và giới tính.
summarise(total_cases = n(), .groups = "drop"): Tạo bảng tóm tắt total_cases là số quan sát trong mỗi tổ hợp. .groups = "drop" loại bỏ metadata về grouping sau khi summarise, tránh cảnh báo và hành vi không mong muốn.
group_by(crime_group): Gom lại theo crime_group để tính tỷ lệ nội bộ trong từng nhóm tội phạm.
mutate(pct = total_cases / sum(total_cases) * 100): Tạo cột pct là tỷ lệ phần trăm của total_cases trong mỗi crime_group. sum(total_cases) tính tổng cho mỗi nhóm tội phạm, nên pct là tỷ lệ nội bộ (cộng lại = 100% cho mỗi crime_group).
ggplot(aes(x = reorder(crime_group, -pct), y = pct, fill = sex)): aes(...) ánh xạ thẩm mỹ trục x là crime_group (đã được reorder theo -pct), trục y là pct, màu cột theo sex.
geom_bar(stat = "identity", position = "stack", width = 0.7): stat = "identity": dùng giá trị y (pct) có sẵn (không đếm lại). position = "stack": các thanh theo sex được xếp chồng để cột cuối cùng thể hiện tổng 100% (tuy ở đây y đã là tỷ lệ, nên tổng ~100%). width = 0.7: điều chỉnh bề rộng cột.
geom_text(aes(label = paste0(round(pct, 1), "%")), position = position_stack(vjust = 0.5), size = 3, color = "black"). Thêm nhãn phần trăm đặt ở giữa mỗi segment nhờ position_stack(vjust = 0.5). round(pct, 1) làm tròn 1 chữ số thập phân; paste0(..., "%") thêm ký tự phần trăm.
scale_fill_brewer(palette = "Set3")
labs(...): đặt tiêu đề, nhãn trục, tên chú giải.
theme_minimal(base_size = 13) + theme(...): thiết lập giao diện và bố cục; xoay nhãn x bằng angle = 45 để tránh chồng chữ.
Ý nghĩa thống kê:
Biểu đồ cho thấy giới tính có ảnh hưởng rõ rệt đến đặc điểm tội phạm. Trong nhóm tội giết người, nam giới chiếm tỷ lệ áp đảo (≈ 86,5%), cho thấy các hành vi phạm tội nghiêm trọng chủ yếu do nam giới thực hiện. Các nhóm “bạo lực – hành hung” và “trộm cắp – cướp giật” có phân bố tương đối cân bằng hơn, nhưng nam giới vẫn chiếm ưu thế (≈ 47–50%), phản ánh tính đặc trưng của các tội phạm sử dụng vũ lực.
Ngược lại, nhóm “tình dục – quấy rối” có tỷ lệ nữ giới rất cao (≈ 74%), cho thấy nữ giới thường là nạn nhân chính trong loại tội phạm này. “Gian lận – tài chính” có cơ cấu giới tương đối đồng đều (nam ~47%, nữ ~33%, không xác định ~19%), thể hiện đây là loại tội phạm không mang đặc trưng giới tính mạnh, thường liên quan đến hành vi trí tuệ hoặc vị trí nghề nghiệp. Nhóm “ma túy” và “khác” lại ghi nhận tỷ lệ giới tính không xác định khá cao (≈ 15–36%), có thể do thiếu dữ liệu hoặc trường hợp đặc thù chưa được phân loại rõ.
Nhìn chung, nam giới chiếm đa số trong các tội phạm mang tính bạo lực, xung động và thể chất, trong khi nữ giới thường là nạn nhân trong các vụ án liên quan đến tình dục. Điều này cho thấy cần tăng cường các biện pháp bảo vệ, giáo dục giới tính và can thiệp sớm, đồng thời chuẩn hóa dữ liệu về giới tính để phục vụ công tác thống kê và hoạch định chính sách. Việc phân tích cơ cấu giới tính giúp nhận diện nhóm có nguy cơ cao và định hướng chiến lược phòng ngừa – hỗ trợ xã hội hiệu quả hơn.
top_areas <- crime %>%
group_by(area) %>%
summarise(total_cases = n()) %>%
arrange(desc(total_cases)) %>%
slice_head(n = 5)
crime_top_areas <- crime %>%
filter(area %in% top_areas$area, !is.na(area), !is.na(sex))
crime_top_areas %>%
group_by(area, sex) %>%
summarise(total = n(), .groups = "drop") %>%
ggplot(aes(x = sex, y = reorder(area, -total), fill = total)) +
geom_tile(color = "white") +
geom_text(aes(label = total), color = "red", size = 3) +
scale_fill_gradient(low = "#d8f3dc", high = "#1b4332") +
labs(
title = "Mức độ phạm tội theo giới tính và khu vực",
x = "Giới tính", y = "Khu vực", fill = "Số vụ"
) +
theme_minimal(base_size = 13) +
theme(plot.title = element_text(hjust = 0.5, face = "bold"))Giải thích kỹ thuật:
group_by(area) %>% summarise(total_cases = n()): Gom nhóm theo khu vực, đếm số vụ.
arrange(desc(total_cases)) %>% slice_head(n = 5): Lấy 5 khu vực có nhiều vụ nhất.
filter(area %in% top_areas$area, !is.na(area), !is.na(sex)): Giữ lại dữ liệu hợp lệ của top 5 khu vực.
group_by(area, sex) %>% summarise(total = n()): Đếm số vụ theo giới tính trong từng khu vực.
ggplot(aes(x = sex, y = reorder(area, -total), fill = total)): Thiết lập trục và thang màu.
geom_tile(): Vẽ các ô thể hiện mật độ vụ án.
geom_text(aes(label = total)): Hiển thị số vụ trên từng ô.
scale_fill_gradient(): Tô màu từ nhạt đến đậm theo số vụ.
labs() + theme_minimal(): Đặt tiêu đề, nhãn trục, giao diện đơn giản.
Ý nghĩa thống kê:
Nhìn chung, nạn nhân nam chiếm tỷ lệ cao hơn đáng kể so với nữ ở hầu hết các khu vực, đặc biệt là tại Central – nơi ghi nhận gần 30.000 vụ với nạn nhân là nam, cao nhất trong 5 khu vực.
Các khu vực như 77th Street và Southwest lại có số vụ nạn nhân nữ tương đối cao, cho thấy mức độ tội phạm nhắm vào phụ nữ vẫn đáng lưu ý.
Số vụ có giới tính không xác định tuy chiếm tỷ lệ nhỏ, nhưng vẫn xuất hiện ở tất cả các khu vực.
crime %>%
group_by(year, sex) %>%
summarise(total_cases = n(), .groups = "drop") %>%
ggplot(aes(x = factor(year), y = total_cases, fill = sex)) +
geom_col(position = "dodge") +
geom_text(aes(label = total_cases),
position = position_dodge(width = 1), vjust = -0.5, size = 3) +
labs(
title = "So sánh số lượng nạn nhân qua các năm",
x = "Năm",
y = "Số vụ",
fill = "Giới tính"
) +
theme_minimal()Giải thích kỹ thuật:
group_by(year, sex): Gom các bản ghi theo hai biến phân loại: year và sex.
summarise(total_cases = n(), .groups = "drop"): Tạo một bảng tóm tắt mới có cột total_cases là số lượng bản ghi (số vụ) trong mỗi nhóm. .groups = "drop" loại bỏ metadata grouping sau khi summarise (tránh cảnh báo và hành vi giữ group không mong muốn).
ggplot(aes(x = factor(year), y = total_cases, fill = sex)): ánh xạ thẩm mỹ (aesthetic mapping) cho biểu đồ: x = factor(year): biến năm được ép về factor (mỗi năm là 1 cột riêng, giữ thứ tự rời rạc). y = total_cases: chiều cao cột là tổng số vụ. fill = sex: màu tô cột theo giá trị sex (phân biệt giới).
geom_col(position = "dodge"): Vẽ cột dựa trên giá trị y đã được tóm tắt. position = "dodge" đặt các cột của các sex khác nhau trong cùng một year nằm cạnh nhau (không chồng lên).
geom_text(aes(label = total_cases), position = position_dodge(width = 1), vjust = -0.5, size = 3): Thêm nhãn số (số vụ) trên/ngoài đầu mỗi cột. position = position_dodge(width = 1) đảm bảo nhãn căn trùng vị trí với cột tương ứng (dùng cùng kiểu dodge). vjust = -0.5 dịch nhãn lên trên đỉnh cột (tránh chồng lên cột). size = 3 kích thước chữ.
labs(...): Đặt tiêu đề và nhãn cho trục, cũng như tên chú giải (fill = "Giới tính").
theme_minimal(): Chọn theme tối giản cho biểu đồ (gọn, phù hợp báo cáo). Bạn có thể thêm theme(plot.title = element_text(hjust = 0.5)) để căn giữa tiêu đề.
Ý nghĩa thống kê:
Nam giới luôn là nhóm nạn nhân chiếm tỷ lệ cao nhất mỗi năm, dao động từ khoảng 84.000 đến 95.000 vụ.
Nữ giới cũng chiếm tỷ trọng lớn, chỉ thấp hơn nam một chút, đặc biệt trong năm 2022 khi số vụ gần tương đương.
Giới tính không xác định có số vụ thấp hơn nhiều, nhưng lại tăng đều qua các năm, từ khoảng 16.000 vụ (2020) lên gần 26.000 vụ (2023).
Tổng thể, số vụ phạm tội nhắm vào cá nhân đều tăng nhẹ theo thời gian, thể hiện xu hướng cần chú ý về an ninh cộng đồng và bảo vệ cá nhân trong giai đoạn gần đây.
plot7 <- crime %>%
group_by(area, severity) %>%
summarise(total=n()) %>%
ggplot(aes(x=area, y=total, fill=severity)) +
geom_bar(stat="identity") +
coord_flip() +
theme_minimal() +
labs(title="Phân bố mức độ nghiêm trọng theo khu vực", x="Khu vực", y="Số vụ")## `summarise()` has grouped output by 'area'. You can override using the
## `.groups` argument.
library(dplyr)
library(ggplot2)
crime %>%
group_by(area) %>%
summarise(
total_cases = n(),
arrested_cases = sum(arrested == "Arrested"),
arrest_rate = arrested_cases / total_cases * 100
) %>%
ggplot(aes(x = reorder(area, arrest_rate), y = arrest_rate)) +
geom_col(fill = "tomato") +
geom_text(aes(label = paste0(round(arrest_rate,1), "%")),
position = position_stack(vjust = 0),
hjust = -0.1,
size = 3) +
coord_flip() +
labs(title="Tỷ lệ vụ án đã giải quyết theo khu vực", x="Khu vực", y="Tỷ lệ (%)") +
theme_minimal()Giải thích kỹ thuật:
group_by(area): gom nhóm dữ liệu theo khu vực phạm tội.
summarise(...): tạo bảng tóm tắt cho từng khu vực gồm:
total_cases = n(): tổng số vụ án trong khu vực đó.
arrested_cases = sum(arrested == "đã bắt giữ"): đếm số vụ đã bắt giữ (điều kiện logic trả về TRUE/FALSE → TRUE = 1).
arrest_rate = arrested_cases / total_cases * 100: tính tỷ lệ phần trăm vụ án đã được giải quyết.reorder(area, arrest_rate): sắp xếp các khu vực theo tỷ lệ vụ án giải quyết tăng dần, giúp biểu đồ dễ đọc hơn.
geom_text(): thêm nhãn số liệu vào cột.
label = paste0(round(arrest_rate,1), "%"): làm tròn 1 chữ số thập phân, hiển thị kèm dấu %.
position_stack(vjust = 0): canh vị trí nhãn ở đỉnh cột.
hjust = -0.1: đẩy nhãn ra ngoài một chút để dễ đọc.
coord_flip(): Lật biểu đồ nằm ngang, giúp dễ đọc tên khu vực khi danh sách dài.labs(): đặt tiêu đề và nhãn trục.
theme_minimal(): giao diện tối giản, giúp biểu đồ sạch và hiện đại.
Ý nghĩa thống kê:
Tỷ lệ vụ án được giải quyết có sự khác biệt rõ rệt giữa các khu vực.
Harbor (14.7%), Mission (14.4%) và Foothill (13.3%) đạt tỷ lệ cao nhất, cho thấy công tác điều tra và xử lý tội phạm tại đây tương đối hiệu quả.
Ngược lại, Central (7.0%), West LA (7.1%) và Pacific (7.5%) có tỷ lệ thấp hơn, phản ánh những khó khăn do mật độ dân cư cao và tính chất tội phạm phức tạp. Sự chênh lệch gần gấp đôi giữa khu vực cao nhất và thấp nhất cho thấy hiệu quả điều tra chưa đồng đều.
crime %>% count(area, severity_label) -> d
ggplot(d, aes(x=reorder(area, -n), y=n, fill=severity_label)) +
geom_col(color='white') +
geom_text(aes(label=n), position=position_stack(vjust=0.5), size=3) +
scale_fill_manual(values=c("#a8ddb5", "#43a2ca", "#0868ac")[1:length(unique(d$severity_label))]) +
coord_flip() +
labs(title='Số vụ theo khu vực & mức độ', x='Khu vực', y='Số vụ') +
theme_light()Giải thích kỹ thuật:
count(area, severity_label) = group_by(area, severity_label) %>% summarise(n = n()). Kết quả d là bảng dạng long có 1 hàng cho mỗi tổ hợp area × severity_label và cột n = số vụ
aes(x = reorder(area, -n), y = n, fill = severity_label): reorder(area, -n) sắp xếp nhãn area theo giá trị n của hàng hiện tại.
geom_col(color = 'white'): vẽ cột; color='white' vẽ viền trắng giữa các segment.
geom_text(..., position = position_stack(vjust = 0.5)): thêm nhãn số n đặt ở giữa mỗi segment xếp chồng (stack).
scale_fill_manual(...): gán màu cho các nhãn severity_label. Ở đây bạn chọn 3 màu và lấy số màu đúng bằng số mức độ hiện có. Chú ý: cần đảm bảo tên/level của severity_label khớp với thứ tự màu hoặc đặt named vector.
coord_flip(): lật trục để có biểu đồ ngang (dễ đọc tên khu vực dài).
labs(...), theme_light(): đặt tiêu đề, nhãn trục, dùng theme.
Ý nghĩa thống kê:
Biểu đồ thể hiện tổng số vụ phạm tội tại từng khu vực cùng với phân loại mức độ nghiêm trọng (Severe – nghiêm trọng, Minor – nhẹ). Dữ liệu được sắp xếp theo thứ tự giảm dần giúp quan sát rõ ràng sự khác biệt giữa các khu vực về quy mô và tính chất tội phạm.
Có thể thấy, khu vực Central, 77th Street và Pacific là ba địa bàn có số vụ phạm tội cao nhất, vượt xa các khu vực còn lại. Trong đó, phần màu xanh đậm đại diện cho các vụ nghiêm trọng (Severe) chiếm tỷ trọng đáng kể, cho thấy tần suất các hành vi bạo lực, xâm hại hoặc tội phạm nguy hiểm cao hơn mức trung bình toàn thành phố. Điều này phản ánh các khu vực này có mức độ rủi ro an ninh cao, cần được ưu tiên trong công tác phòng chống tội phạm.
Ngược lại, các khu vực như Foothill, Hollenbeck và Mission có số vụ thấp hơn đáng kể, thể hiện tình hình an ninh tương đối ổn định. Ở nhóm này, phần màu xanh nhạt (Minor) chiếm tỷ lệ lớn hơn, chứng tỏ đa phần là các vụ việc nhẹ, ít tính bạo lực hoặc thiệt hại.
Sự chênh lệch rõ rệt giữa các khu vực cho thấy sự phân bố tội phạm không đồng đều về mặt không gian. Các vùng trung tâm và phía nam có xu hướng tập trung nhiều vụ nghiêm trọng hơn, trong khi vùng ngoại ô phía bắc duy trì mức thấp hơn. Điều này có thể liên quan đến mật độ dân cư, kinh tế, tình hình xã hội hoặc hiệu quả quản lý địa phương.
Từ góc độ thống kê, biểu đồ giúp xác định các “điểm nóng” tội phạm, hỗ trợ việc phân tích nguyên nhân tiềm ẩn và hoạch định chính sách an ninh phù hợp. Đồng thời, việc hiển thị trực quan bằng tỷ lệ phần trăm và số lượng cụ thể giúp so sánh định lượng rõ ràng giữa các khu vực, đảm bảo cơ sở cho các đánh giá thực chứng trong phần phân tích chuyên sâu tiếp theo.
top5_loaitoi <- crime %>%
count(crime_group, sort = TRUE) %>%
slice_head(n = 10) %>%
pull(crime_group)
crime_top5 <- crime %>%
filter(crime_group %in% top5_loaitoi)
ggplot(crime_top5, aes(x = factor(year), fill = sex)) +
geom_bar(position = "fill") +
facet_wrap(~crime_group) +
scale_y_continuous(labels = scales::percent) +
labs(
title = "Cơ cấu giới tính theo năm cho Top 5 nhóm tội phạm",
x = "Năm",
y = "Tỷ lệ (%)"
) +
theme_minimal(base_size = 11) +
theme(
plot.title = element_text(hjust = 0.5, face = "bold"),
strip.text = element_text(size = 9)
)Giải thích kỹ thuật:
count(crime_group, sort = TRUE): đếm số vụ theo nhóm tội phạm (crime_group) và sắp giảm dần.
slice_head(n = 10): chọn 10 nhóm tội nhiều nhất.
filter(crime_group %in% top5_loaitoi): lọc dữ liệu chỉ giữ các nhóm này.
ggplot(aes(x = factor(year), fill = sex)): ánh xạ năm vào trục X, màu cột theo giới tính.
geom_bar(position = "fill"): tạo biểu đồ cột chồng theo tỷ lệ % (thay vì số tuyệt đối).
facet_wrap(~crime_group): chia mỗi nhóm tội thành một khung nhỏ riêng (small multiple).
scale_y_continuous(labels = scales::percent): chuyển trục tung sang đơn vị %.
theme_minimal() + strip.text: tạo bố cục tối giản, căn giữa tiêu đề và tinh chỉnh nhãn facet
Ý nghĩa thống kê:
Biểu đồ thể hiện cơ cấu giới tính của các vụ án trong Top 5 nhóm tội phạm phổ biến nhất, theo từng năm từ 2020 đến 2023. Mỗi khung nhỏ (facet) là một nhóm tội, giúp so sánh tỷ lệ giới tính qua thời gian trong cùng loại hành vi.
Sexual & Harassment: nữ giới chiếm ưu thế tuyệt đối (khoảng 70–80%) trong toàn kỳ quan sát. Điều này phản ánh đặc trưng của nhóm tội phạm liên quan đến xâm hại, quấy rối tình dục — nơi nữ giới chủ yếu là nạn nhân. Tỷ lệ ổn định qua các năm, cho thấy tính lặp lại của mô hình nạn nhân theo giới.
Homicide và Violence & Assault: nam giới chiếm đa số (60–70%), phản ánh các loại tội mang tính bạo lực thể chất hoặc hành vi tấn công thường do hoặc nhằm vào nam giới. Xu hướng này duy trì ổn định, ít biến động theo năm.
Fraud & Financial Crime và Drug-related: tỷ lệ nam và nữ khá cân bằng, cho thấy đây là các loại tội phi bạo lực (non-violent crimes) chịu ảnh hưởng bởi yếu tố xã hội – kinh tế hơn là giới tính.
Other nhóm tội phụ như Arson hay Theft & Robbery cũng duy trì mức chênh lệch giới nhỏ hơn, thể hiện sự đa dạng hành vi trong từng loại phạm pháp.
crime %>%
group_by(crime_group) %>%
summarise(mean_age = mean(age, na.rm = TRUE)) %>%
slice_max(mean_age, n = 10) %>%
ggplot(aes(x = reorder(crime_group, mean_age), y = mean_age)) +
geom_col(fill = "orange") +
coord_flip() +
geom_text(aes(label = round(mean_age, 1)), hjust = -0.3) +
labs(title = "Tuổi trung bình theo loại tội", x = "Loại tội", y = "Tuổi TB") +
theme_minimal()Giải thích kỹ thuật
group_by(crime_group) %>% summarise(mean_age = mean(age, na.rm = TRUE)): gom theo nhóm tội và tính tuổi trung bình; na.rm=TRUE loại NA để không làm sai lệch giá trị.
slice_max(mean_age, n = 10): lấy 10 nhóm có tuổi TB cao nhất (nếu <10 nhóm thì giữ nguyên tất cả).
ggplot(..., aes(x = reorder(crime_group, mean_age), y = mean_age)): sắp xếp trục theo tuổi TB tăng dần để dễ so sánh.
geom_col(fill = "orange") + coord_flip(): cột ngang giúp đọc nhãn nhóm tội dài rõ ràng.
geom_text(..., hjust = -0.3): hiển thị giá trị tuổi TB ngay trên cột.
labs(...) + theme_minimal(): đặt tiêu đề/nhãn và giao diện gọn.
Ý nghĩa thống kê:
Các nhóm như Fraud & Financial Crime / Homicide / Violence & Assault có tuổi trung bình cao hơn → phản ánh hành vi đòi hỏi sự chuẩn bị/kỹ năng, hoặc xảy ra trong bối cảnh người lớn tuổi hơn.
Nhóm Drug-related (và một số nhóm như Arson) có tuổi trung bình thấp hơn → hàm ý mức độ tham gia/ảnh hưởng ở nhóm tuổi trẻ nổi bật hơn.
Trật tự chênh lệch ổn định và dễ thấy nhờ sắp xếp theo giá trị TB; tuy nhiên mean nhạy với ngoại lệ, nên khi viết báo cáo có thể bổ sung trung vị (median) và IQR để kiểm chứng độ bền.
Kết quả gợi ý ưu tiên can thiệp theo độ tuổi: phòng ngừa, giáo dục sớm cho nhóm tội có tuổi TB thấp; tăng truyền thông – kiểm soát rủi ro tài chính cho nhóm tội có tuổi TB cao.
breaks16 <- seq(0, 90, by = 5)
df16 <- crime %>%
filter(!is.na(age), sex %in% c("Male","Female")) %>%
mutate(age_bin = cut(age, breaks = breaks16, right = FALSE)) %>%
count(sex, age_bin) %>%
group_by(sex) %>%
mutate(n = ifelse(sex == "Female", -n, n)) %>% ungroup()
ggplot(df16, aes(x = age_bin, y = n, fill = sex)) +
geom_col(width = 0.9) +
coord_flip() +
scale_y_continuous(labels = function(x) scales::comma(abs(x))) +
labs(title = "Tháp tuổi nạn nhân theo giới", x = "Nhóm tuổi (5 năm)", y = "Số vụ") +
theme_minimal() +
theme(plot.title = element_text(hjust=.5))##
## Attaching package: 'lubridate'
## The following objects are masked from 'package:base':
##
## date, intersect, setdiff, union
crime %>%
mutate(month = month(as.Date(date), label = TRUE, abbr = TRUE)) %>%
count(month) %>%
ggplot(aes(x = month, y = n)) +
geom_col(fill = "#69b3a2") +
geom_text(aes(label = n), vjust = -0.3) +
labs(title = "Số vụ phạm tội theo tháng", x = "Tháng", y = "Số vụ") +
theme_minimal()crime %>%
filter(!is.na(age)) %>%
group_by(year) %>%
summarise(mean_age = mean(age)) %>%
ggplot(aes(x = factor(year), y = mean_age, group = 1)) +
geom_line(color = "#2A9D8F") +
geom_point(size = 2, color = "#E76F51") +
labs(title = "Tuổi trung bình theo năm", x = "Năm", y = "Tuổi trung bình") +
theme_minimal()df_donut <- crime %>%
count(severity_label) %>%
mutate(p = n / sum(n), label = paste0(severity_label, "\n", scales::percent(p, 0.1)))
ggplot(df_donut, aes(x = 2, y = p, fill = severity_label)) +
geom_col(color = "white") +
coord_polar(theta = "y") +
xlim(0.5, 2.5) +
geom_text(aes(label = label), position = position_stack(vjust = 0.5), size = 3) +
theme_void() +
labs(title = "Cơ cấu mức độ phạm tội") +
theme(plot.title = element_text(hjust = 0.5))crime %>%
filter(year == 2023) %>%
count(crime_group, sort = TRUE) %>%
slice_head(n = 10) %>%
ggplot(aes(x = reorder(crime_group, n), y = n)) +
geom_col(fill = "#457b9d") +
geom_text(aes(label = n), hjust = -0.1) +
coord_flip() +
labs(title = "Top 10 nhóm tội trong năm 2023", x = "Nhóm tội", y = "Số vụ") +
theme_minimal()top8_group <- crime %>% count(crime_group, sort = TRUE) %>% slice_head(n = 8) %>% pull(crime_group)
crime %>%
filter(crime_group %in% top8_group) %>%
group_by(year, crime_group) %>%
summarise(mean_age = mean(age, na.rm = TRUE), .groups = "drop") %>%
ggplot(aes(x = year, y = mean_age, color = crime_group)) +
geom_line(linewidth = 1) +
geom_point(size = 2) +
labs(title = "Tuổi trung bình theo nhóm tội (Top 8)", x = "Năm", y = "Tuổi trung bình", color = "Nhóm tội") +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5))## `geom_line()`: Each group consists of only one observation.
## ℹ Do you need to adjust the group aesthetic?
## Warning: package 'scales' was built under R version 4.5.2
df_a1 <- crime %>%
mutate(is_severe = severity_label %in% c("Severe","High")) %>%
group_by(year, area) %>%
summarise(rate_severe = mean(is_severe, na.rm=TRUE),
mean_age = mean(age, na.rm=TRUE),
n = n(), .groups="drop")
ggplot(df_a1, aes(x = factor(year), y = area)) +
geom_point(aes(size = rate_severe, color = mean_age), alpha = .8) +
scale_size(range = c(2,10), labels = percent) +
scale_color_viridis_c() +
labs(title = "Bubble: Năm × Khu vực (size = Tỷ lệ nghiêm trọng, color = Tuổi TB)",
x = "Năm", y = "Khu vực", size = "Tỷ lệ nghiêm trọng", color = "Tuổi TB") +
theme_minimal()overall_f <- mean(crime$sex == "Female", na.rm=TRUE)
df_a5 <- crime %>%
filter(!is.na(area), !is.na(sex)) %>%
group_by(area) %>%
summarise(p_f = mean(sex=="Female"), n=n(), .groups="drop") %>%
mutate(diff = p_f - overall_f,
area = reorder(area, diff))
ggplot(df_a5, aes(x = diff, y = area)) +
geom_segment(aes(xend = 0, yend = area), color = "#b0bec5") +
geom_point(aes(size = n, color = diff > 0)) +
scale_x_continuous(labels = percent) +
scale_color_manual(values = c("#e76f51", "#2a9d8f"), guide = "none") +
labs(title = "Chênh lệch tỷ lệ nạn nhân nữ so với toàn TP (size = quy mô vụ)",
x = "Chênh lệch (%)", y = "Khu vực", size = "Số vụ") +
theme_minimal()df_heat <- crime %>%
count(year, sex) %>%
group_by(sex) %>%
arrange(year, .by_group = TRUE) %>%
mutate(yoy = (n - lag(n)) / lag(n)) %>%
filter(!is.na(yoy)) %>%
ungroup()
ggplot(df_heat, aes(x = factor(year), y = sex, fill = yoy)) +
geom_tile(color = "white") +
scale_fill_gradient2(low = "#d73027", mid = "white", high = "#1a9850", labels = percent) +
labs(title = "Tăng trưởng số vụ theo năm × giới",
x = "Năm", y = "Giới", fill = "(%)") +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5))Ngành sữa Việt Nam là một trong những lĩnh vực có tốc độ tăng trưởng ổn định và đóng vai trò quan trọng trong việc cải thiện dinh dưỡng quốc gia. Trong đó, Công ty Cổ phần Sữa Việt Nam (Vinamilk – VNM) là doanh nghiệp dẫn đầu thị trường, có vị thế thống lĩnh cả về quy mô sản xuất, doanh thu và giá trị thương hiệu. Việc phân tích dữ liệu tài chính của VNM trong giai đoạn 2015–2024 không chỉ giúp đánh giá hiệu quả hoạt động kinh doanh của một doanh nghiệp đầu ngành, mà còn phản ánh bức tranh tổng thể của ngành sữa Việt Nam trong bối cảnh hội nhập và cạnh tranh ngày càng cao.
Ngoài ra, giai đoạn này bao gồm nhiều biến động đáng chú ý như ảnh hưởng của đại dịch COVID-19, sự thay đổi trong hành vi tiêu dùng, và xu hướng mở rộng thị trường quốc tế của Vinamilk. Do đó, việc nghiên cứu các chỉ tiêu tài chính của VNM (như doanh thu, lợi nhuận, NIM, NPM, hiệu quả sử dụng vốn và tỷ lệ tiền mặt trên tài sản) sẽ giúp đánh giá mức độ ổn định, khả năng sinh lời và hiệu quả quản trị tài chính của công ty qua thời gian.
Từ những lý do trên, đề tài “Phân tích dữ liệu tài chính Công ty Cổ phần Sữa Việt Nam (VNM) giai đoạn 2015–2024” được lựa chọn nhằm cung cấp cái nhìn toàn diện về hiệu quả hoạt động của doanh nghiệp đầu ngành, hỗ trợ việc ra quyết định đầu tư, hoạch định chiến lược và đánh giá tiềm năng tăng trưởng trong tương lai.
Đối tượng nghiên cứu:
Các chỉ tiêu tài chính của Công ty Cổ phần Sữa Việt Nam (Vinamilk – VNM) giai đoạn 2015–2024, bao gồm tổng tài sản, nợ phải trả, vốn chủ sở hữu, lợi nhuận sau thuế, NIM, NPM và hiệu quả tài chính.
Phạm vi nghiên cứu:
Không gian: Doanh nghiệp VNM – niêm yết trên sàn HOSE.
Thời gian: Từ năm 2015 đến 2024.
Nội dung: Phân tích, đánh giá xu hướng và hiệu quả hoạt động tài chính của VNM qua 10 năm.
Bộ dữ liệu được thu thập từ báo cáo tài chính hợp nhất của Công ty Cổ phần Sữa Việt Nam (Vinamilk – VNM) trong giai đoạn 2015–2024. Dữ liệu ghi nhận các chỉ tiêu tài chính chủ yếu phản ánh quy mô tài sản, cơ cấu nguồn vốn, kết quả kinh doanh và hiệu quả sinh lời của doanh nghiệp theo từng năm.
Bộ dữ liệu được tổng hợp, làm sạch và chuẩn hóa để phục vụ cho phân tích mô tả, trực quan hóa và đánh giá xu hướng tài chính của VNM trong suốt 10 năm nghiên cứu.
CDKT <- read_excel( "C:/Users/USER/Downloads/VNM.xlsx", sheet = "CDKT")
HDKD <- read_excel("C:/Users/USER/Downloads/VNM.xlsx", sheet = "HDKD")
LCTT <- read_excel("C:/Users/USER/Downloads/VNM.xlsx", sheet = "LCTT")Giải thích kỹ thuật:
read_excel() là hàm từ package readxl, cho phép đọc dữ liệu từ file Excel (.xlsx hoặc .xls) vào môi trường R.
Tham số sheet = "..." chỉ định tên sheet cụ thể cần đọc trong file Excel.
Ba bảng dữ liệu được lưu vào ba đối tượng riêng biệt (CDKT, HDKD, LCTT) để thuận tiện xử lý độc lập trước khi tích hợp.
## [1] 10 83
## [1] 10 23
## [1] 10 50
Giải thích kỹ thuật:
Hàm dim() trả về một vector gồm hai phần tử: số hàng (rows) và số cột (columns) của data frame.
Kết quả cho biết CDKT có 10 hàng và 83 cột, HDKD có 10 hàng và 23 cột, LCTT có 10 hàng và 50 cột.
## Rows: 10
## Columns: 83
## $ Năm <dbl> 2024, 2023, 2022, 20…
## $ `Tài sản ngắn hạn` <dbl> 3.755365e+13, 3.5935…
## $ `Tiền và các khoản tương đương tiền` <dbl> 2.225944e+12, 2.9120…
## $ Tiền <dbl> 1.877944e+12, 1.0254…
## $ `Các khoản tương đương tiền` <dbl> 3.480000e+11, 1.8865…
## $ `Các khoản đầu tư tài chính ngắn hạn` <dbl> 2.326009e+13, 2.0137…
## $ `Chứng khoán kinh doanh` <dbl> 1248322211, 11930659…
## $ `Dự phòng giảm giá chứng khoán kinh doanh` <dbl> -920681738, -8226634…
## $ `Đầu tư nắm giữ đến ngày đáo hạn` <dbl> 2.325976e+13, 2.0136…
## $ `Các khoản phải thu ngắn hạn` <dbl> 6.233759e+12, 6.5297…
## $ `Phải thu khách hàng` <dbl> 4.793133e+12, 4.8081…
## $ `Trả trước cho người bán` <dbl> 566479222775, 655619…
## $ `Phải thu từ cho vay ngắn hạn` <chr> NA, NA, NA, "-", "15…
## $ `Phải thu ngắn hạn khác` <dbl> 8.964795e+11, 1.0808…
## $ `Dự phòng phải thu khó đòi` <dbl> -22332866679, -14901…
## $ `Tài sản thiếu chờ xử lý` <chr> NA, NA, NA, NA, NA, …
## $ `Hàng tồn kho` <dbl> 5.686840e+12, 6.1280…
## $ `Hàng tồn kho2` <dbl> 5.723932e+12, 6.1659…
## $ `Dự phòng giảm giá hàng tồn kho` <dbl> -37092148693, -37853…
## $ `Tài sản ngắn hạn khác` <dbl> 147018887251, 228821…
## $ `Chi phí trả trước ngắn hạn` <dbl> 89544473336, 8286044…
## $ `Thuế giá trị gia tăng được khấu trừ` <dbl> 33580977723, 9942895…
## $ `Thuế phải thu Ngân sách Nhà nước` <dbl> 23893436192, 4653207…
## $ `B - TÀI SẢN DÀI HẠN` <dbl> 1.749541e+13, 1.6737…
## $ `Các khoản phải thu dài hạn` <dbl> 17592137763, 1613199…
## $ `Phải thu khách hàng3` <chr> "398152069", NA, NA,…
## $ `Phải thu từ cho vay dài hạn` <dbl> NA, NA, NA, NA, NA, …
## $ `Phải thu dài hạn khác` <dbl> 17193985694, 1613199…
## $ `Tài sản cố định` <dbl> 1.255056e+13, 1.2689…
## $ `Tài sản cố định hữu hình` <dbl> 1.152020e+13, 1.1688…
## $ `Nguyên giá` <dbl> 3.271305e+13, 3.1109…
## $ `Giá trị hao mòn lũy kế` <dbl> -2.119285e+13, -1.94…
## $ `Tài sản cố định vô hình` <dbl> 1.030364e+12, 1.0011…
## $ `Nguyên giá4` <dbl> 1.466192e+12, 1.3664…
## $ `Giá trị hao mòn lũy kế5` <dbl> -435828219794, -3652…
## $ `Bất động sản đầu tư` <dbl> 53617793172, 5559415…
## $ `Nguyên giá6` <dbl> 98822678885, 9882267…
## $ `Giá trị hao mòn lũy kế7` <dbl> -45204885713, -43228…
## $ `Tài sản dở dang dài hạn` <dbl> 1.539776e+12, 9.3692…
## $ `Chi phí sản xuất, kinh doanh dở dang dài hạn` <dbl> 404666242750, 381979…
## $ `Xây dựng cơ bản dở dang` <dbl> 1.135110e+12, 5.5494…
## $ `Các khoản đầu tư tài chính dài hạn` <dbl> 1.373190e+12, 8.3122…
## $ `Đầu tư vào các công ty liên doanh, liên kết` <dbl> 622223692780, 602591…
## $ `Đầu tư góp vốn vào các đơn vị khác` <dbl> 94548675081, 1019750…
## $ `Dự phòng giảm giá đầu tư tài chính dài hạn` <dbl> -23582690668, -23582…
## $ `Đầu tư nắm giữ đến ngày đáo hạn8` <chr> "680000000000", "150…
## $ `Tài sản dài hạn khác` <dbl> 1.960671e+12, 2.2079…
## $ `Chi phí trả trước dài hạn` <dbl> 792476015491, 871585…
## $ `Tài sản thuế thu nhập hoãn lại` <dbl> 92172946105, 1444850…
## $ `Lợi thế thương mại` <dbl> 1.076022e+12, 1.3219…
## $ `TỔNG CỘNG TÀI SẢN` <dbl> 5.504906e+13, 5.2673…
## $ `NỢ PHẢI TRẢ` <dbl> 1.887466e+13, 1.7647…
## $ `Nợ ngắn hạn` <dbl> 1.845955e+13, 1.7138…
## $ `Phải trả người bán` <dbl> 3.874064e+12, 3.8058…
## $ `Người mua trả tiền trước` <dbl> 191336029327, 164712…
## $ `Thuế phải nộp Ngân sách Nhà nước` <dbl> 1.014478e+12, 9.6787…
## $ `Phải trả người lao động` <dbl> 307904216360, 289224…
## $ `Chi phí phải trả` <dbl> 2.115775e+12, 1.9102…
## $ `Doanh thu chưa thực hiện ngắn hạn` <dbl> 263912732, 263912729…
## $ `Phải trả ngắn hạn khác` <dbl> 1.148532e+12, 1.1939…
## $ `Vay ngắn hạn` <dbl> 9.115435e+12, 8.2177…
## $ `Dự phòng phải trả ngắn hạn` <dbl> 11775786301, 1677051…
## $ `Quỹ khen thưởng và phúc lợi` <dbl> 679981823727, 572091…
## $ `Nợ dài hạn` <dbl> 415111869758, 508937…
## $ `Phải trả người bán dài hạn` <chr> NA, NA, NA, NA, "-",…
## $ `Chi phí phải trả dài hạn` <chr> NA, NA, NA, NA, NA, …
## $ `Doanh thu chưa thực hiện dài hạn` <chr> NA, NA, NA, NA, NA, …
## $ `Phải trả dài hạn khác` <dbl> 722927552, 106337825…
## $ `Vay dài hạn` <dbl> 157903902450, 238476…
## $ `Thuế thu nhập hoãn lại phải trả` <dbl> 256485039756, 269397…
## $ `D - VỐN CHỦ SỞ HỮU (400 = 410)` <dbl> 3.617440e+13, 3.5025…
## $ `Vốn chủ sở hữu` <dbl> 3.617440e+13, 3.5025…
## $ `Vốn cổ phần` <dbl> 2.089955e+13, 2.0899…
## $ `Thặng dư vốn cổ phần` <chr> "34110709700", "3411…
## $ `Vốn khác của chủ sở hữu` <dbl> 499080803215, 499080…
## $ `Cổ phiếu quỹ` <chr> NA, NA, NA, "-", "-1…
## $ `Chênh lệch quy đổi tiền tệ` <dbl> 295734210956, 174100…
## $ `Quỹ đầu tư phát triển` <dbl> 7.079115e+12, 6.1637…
## $ `Lợi nhuận sau thuế chưa phân phối` <dbl> 3.471225e+12, 3.9262…
## $ `- LNST chưa phân phối lũy kế đến cuối năm trước` <dbl> 3.493001e+11, 1.0684…
## $ `- LNST chưa phân phối năm nay` <dbl> 3.121925e+12, 2.8577…
## $ `Lợi ích cổ đông không kiểm soát` <dbl> 3.895583e+12, 3.3289…
## $ `TỔNG NGUỒN VỐN` <dbl> 5.504906e+13, 5.2673…
## Rows: 10
## Columns: 23
## $ Năm <dbl> 2024,…
## $ `Doanh thu bán hàng và cung cấp dịch vụ` <dbl> 6.182…
## $ `Các khoản giảm trừ doanh thu` <dbl> 41280…
## $ `Doanh thu thuần về bán hàng và cung cấp dịch vụ (10 = 01 - 02)` <dbl> 6.178…
## $ `Giá vốn hàng bán và dịch vụ cung cấp` <dbl> 3.619…
## $ `Lợi nhuận gộp về bán hàng và cung cấp dịch vụ (20 = 10 - 11)` <dbl> 2.559…
## $ `Doanh thu hoạt động tài chính` <dbl> 1.585…
## $ `Chi phí tài chính` <dbl> 42823…
## $ `Trong đó: Chi phí lãi vay` <dbl> 27942…
## $ `Lãi/(lỗ) chia từ công ty liên kết, liên doanh` <dbl> 82002…
## $ `Chi phí bán hàng` <dbl> 1.335…
## $ `Chi phí quản lý doanh nghiệp` <dbl> 1.827…
## $ `Lợi nhuận thuần từ hoạt động kinh doanh` <dbl> 1.159…
## $ `Thu nhập khác` <dbl> 23063…
## $ `Chi phí khác` <dbl> 22495…
## $ `Kết quả từ hoạt động khác` <dbl> 56761…
## $ `Lợi nhuận kế toán trước thuế` <dbl> 1.159…
## $ `Chi phí thuế TNDN hiện hành` <dbl> 2.240…
## $ `(Lợi ích)/chi phí thuế TNDN hoãn lại` <dbl> -9409…
## $ `Lợi nhuận sau thuế TNDN` <dbl> 9.452…
## $ `Chủ sở hữu của Công ty` <dbl> 9.392…
## $ `Lợi ích cổ đông không kiểm soát` <dbl> 60582…
## $ `Lãi cơ bản trên cổ phiếu` <dbl> 4022.…
## Rows: 10
## Columns: 50
## $ Năm <dbl> …
## $ `Lợi nhuận kế toán trước thuế` <dbl> …
## $ `Khấu hao và phân bổ` <dbl> …
## $ `Phân bổ lợi thế thương mại` <dbl> …
## $ `Các khoản dự phòng` <dbl> …
## $ `(Lãi)/lỗ chênh lệch tỷ giá do đánh giá lại các khoản mục tiền tệ có gốc ngoại tệ` <dbl> …
## $ `Lãi do đánh giá lại khoản đầu tư vào công ty liên kết khi trở thành công ty con` <chr> …
## $ `Lỗ từ thanh lý/xóa sổ tài sản cố định và xây dựng cơ bản dở dang` <dbl> …
## $ `Thu nhập từ cổ tức, lãi tiền gửi và lãi/lỗ từ hoạt động đầu tư khác` <dbl> …
## $ `(Lãi)/lỗ chia từ công ty liên kết, liên doanh` <chr> …
## $ `Chi phí lãi vay` <dbl> …
## $ `Thu nhập từ khoản vay được miễn giảm` <chr> …
## $ `Lợi nhuận từ hoạt động kinh doanh trước những thay đổi vốn lưu động` <dbl> …
## $ `Biến động các khoản phải thu` <dbl> …
## $ `Biến động hàng tồn kho` <dbl> …
## $ `Biến động các khoản phải trả và nợ phải trả khác` <dbl> …
## $ `Biến động chi phí trả trước` <dbl> …
## $ `Tiền chi mua TSCĐ và tài sản dài hạn khác` <chr> …
## $ `Tiền lãi vay đã trả` <dbl> …
## $ `Thuế thu nhập doanh nghiệp đã nộp` <dbl> …
## $ `Tiền chi khác cho hoạt động kinh doanh` <dbl> …
## $ `Lưu chuyển tiền thuần từ hoạt động kinh doanh` <dbl> …
## $ `Tiền chi mua tài sản cố định và tài sản dài hạn khác` <dbl> …
## $ `Tiền thu từ thanh lý tài sản cố định và xây dựng cơ bản dở dang` <dbl> …
## $ `Tiền chi tiền gửi có kì hạn` <chr> …
## $ `Tiền thu gửi có kỳ hạn` <chr> …
## $ `Tiền chi cho vay` <chr> …
## $ `Tiền thu hồi cho vay` <chr> …
## $ `Tiền thu hồi từ bán công cụ nợ của đơn vị khác` <chr> …
## $ `Tiền chi đầu tư góp vốn vào các đơn vị khác` <chr> …
## $ `Tiền thu hồi đầu tư vào các đơn vị khác` <chr> …
## $ `Tiền thu lãi tiền gửi và cổ tức` <dbl> …
## $ `Khoản tiền thuần chi cho hợp nhất kinh doanh` <chr> …
## $ `Lưu chuyển tiền thuần từ hoạt động đầu tư` <chr> …
## $ `III. LƯU CHUYỂN TIỀN TỪ HOẠT ĐỘNG TÀI CHÍNH` <dbl> …
## $ `Tiền thu từ bán cổ phiếu quỹ` <chr> …
## $ `Tiền thu từ phát hành cổ phiếu bởi công ty con cho cổ đông không kiểm soát` <chr> …
## $ `Tiền thu từ nhận góp vốn của cổ đông không kiểm soát` <chr> …
## $ `Tiền hoàn trả vốn góp cho cổ đông không kiểm soát của công ty con đã giải thể` <chr> …
## $ `Tiền thu góp vốn của cổ đông không kiểm soát` <chr> …
## $ `Tiền thu từ đi vay` <dbl> …
## $ `Tiền chi trả nợ gốc vay` <dbl> …
## $ `Tiền chi trả cổ tức` <dbl> …
## $ `Tiền chi trả cổ tức của các công ty con chia cho cổ đông không kiểm soát` <dbl> …
## $ `Lưu chuyển tiền thuần từ hoạt động tài chính` <dbl> …
## $ `Lưu chuyển tiền thuần trong năm` <dbl> …
## $ `Tiền và các khoản tương đương tiền đầu năm` <dbl> …
## $ `Ảnh hưởng của thay đổi tỷ giá hối đoái đối với tiền và các khoản tương đương tiền` <dbl> …
## $ `Chênh lệch quy đổi tiền tệ` <dbl> …
## $ `Tiền và các khoản tương đương tiền cuối năm` <dbl> …
Giải thích kỹ thuật:
glimpse() là hàm từ package dplyr, hiển thị cấu trúc dữ liệu theo dạng ngang (transposed), cho phép xem nhanh tên biến, kiểu dữ liệu và một vài giá trị mẫu đầu tiên của mỗi cột.
Hàm này đặc biệt hữu ích khi làm việc với bảng dữ liệu có nhiều cột, giúp quan sát tổng quan mà không bị tràn màn hình.
## [1] "Năm"
## [2] "Tài sản ngắn hạn"
## [3] "Tiền và các khoản tương đương tiền"
## [4] "Tiền"
## [5] "Các khoản tương đương tiền"
## [6] "Các khoản đầu tư tài chính ngắn hạn"
## [7] "Chứng khoán kinh doanh"
## [8] "Dự phòng giảm giá chứng khoán kinh doanh"
## [9] "Đầu tư nắm giữ đến ngày đáo hạn"
## [10] "Các khoản phải thu ngắn hạn"
## [11] "Phải thu khách hàng"
## [12] "Trả trước cho người bán"
## [13] "Phải thu từ cho vay ngắn hạn"
## [14] "Phải thu ngắn hạn khác"
## [15] "Dự phòng phải thu khó đòi"
## [16] "Tài sản thiếu chờ xử lý"
## [17] "Hàng tồn kho"
## [18] "Hàng tồn kho2"
## [19] "Dự phòng giảm giá hàng tồn kho"
## [20] "Tài sản ngắn hạn khác"
## [21] "Chi phí trả trước ngắn hạn"
## [22] "Thuế giá trị gia tăng được khấu trừ"
## [23] "Thuế phải thu Ngân sách Nhà nước"
## [24] "B - TÀI SẢN DÀI HẠN"
## [25] "Các khoản phải thu dài hạn"
## [26] "Phải thu khách hàng3"
## [27] "Phải thu từ cho vay dài hạn"
## [28] "Phải thu dài hạn khác"
## [29] "Tài sản cố định"
## [30] "Tài sản cố định hữu hình"
## [31] "Nguyên giá"
## [32] "Giá trị hao mòn lũy kế"
## [33] "Tài sản cố định vô hình"
## [34] "Nguyên giá4"
## [35] "Giá trị hao mòn lũy kế5"
## [36] "Bất động sản đầu tư"
## [37] "Nguyên giá6"
## [38] "Giá trị hao mòn lũy kế7"
## [39] "Tài sản dở dang dài hạn"
## [40] "Chi phí sản xuất, kinh doanh dở dang dài hạn"
## [41] "Xây dựng cơ bản dở dang"
## [42] "Các khoản đầu tư tài chính dài hạn"
## [43] "Đầu tư vào các công ty liên doanh, liên kết"
## [44] "Đầu tư góp vốn vào các đơn vị khác"
## [45] "Dự phòng giảm giá đầu tư tài chính dài hạn"
## [46] "Đầu tư nắm giữ đến ngày đáo hạn8"
## [47] "Tài sản dài hạn khác"
## [48] "Chi phí trả trước dài hạn"
## [49] "Tài sản thuế thu nhập hoãn lại"
## [50] "Lợi thế thương mại"
## [51] "TỔNG CỘNG TÀI SẢN"
## [52] "NỢ PHẢI TRẢ"
## [53] "Nợ ngắn hạn"
## [54] "Phải trả người bán"
## [55] "Người mua trả tiền trước"
## [56] "Thuế phải nộp Ngân sách Nhà nước"
## [57] "Phải trả người lao động"
## [58] "Chi phí phải trả"
## [59] "Doanh thu chưa thực hiện ngắn hạn"
## [60] "Phải trả ngắn hạn khác"
## [61] "Vay ngắn hạn"
## [62] "Dự phòng phải trả ngắn hạn"
## [63] "Quỹ khen thưởng và phúc lợi"
## [64] "Nợ dài hạn"
## [65] "Phải trả người bán dài hạn"
## [66] "Chi phí phải trả dài hạn"
## [67] "Doanh thu chưa thực hiện dài hạn"
## [68] "Phải trả dài hạn khác"
## [69] "Vay dài hạn"
## [70] "Thuế thu nhập hoãn lại phải trả"
## [71] "D - VỐN CHỦ SỞ HỮU (400 = 410)"
## [72] "Vốn chủ sở hữu"
## [73] "Vốn cổ phần"
## [74] "Thặng dư vốn cổ phần"
## [75] "Vốn khác của chủ sở hữu"
## [76] "Cổ phiếu quỹ"
## [77] "Chênh lệch quy đổi tiền tệ"
## [78] "Quỹ đầu tư phát triển"
## [79] "Lợi nhuận sau thuế chưa phân phối"
## [80] "- LNST chưa phân phối lũy kế đến cuối năm trước"
## [81] "- LNST chưa phân phối năm nay"
## [82] "Lợi ích cổ đông không kiểm soát"
## [83] "TỔNG NGUỒN VỐN"
## [1] "Năm"
## [2] "Doanh thu bán hàng và cung cấp dịch vụ"
## [3] "Các khoản giảm trừ doanh thu"
## [4] "Doanh thu thuần về bán hàng và cung cấp dịch vụ (10 = 01 - 02)"
## [5] "Giá vốn hàng bán và dịch vụ cung cấp"
## [6] "Lợi nhuận gộp về bán hàng và cung cấp dịch vụ (20 = 10 - 11)"
## [7] "Doanh thu hoạt động tài chính"
## [8] "Chi phí tài chính"
## [9] "Trong đó: Chi phí lãi vay"
## [10] "Lãi/(lỗ) chia từ công ty liên kết, liên doanh"
## [11] "Chi phí bán hàng"
## [12] "Chi phí quản lý doanh nghiệp"
## [13] "Lợi nhuận thuần từ hoạt động kinh doanh"
## [14] "Thu nhập khác"
## [15] "Chi phí khác"
## [16] "Kết quả từ hoạt động khác"
## [17] "Lợi nhuận kế toán trước thuế"
## [18] "Chi phí thuế TNDN hiện hành"
## [19] "(Lợi ích)/chi phí thuế TNDN hoãn lại"
## [20] "Lợi nhuận sau thuế TNDN"
## [21] "Chủ sở hữu của Công ty"
## [22] "Lợi ích cổ đông không kiểm soát"
## [23] "Lãi cơ bản trên cổ phiếu"
## [1] "Năm"
## [2] "Lợi nhuận kế toán trước thuế"
## [3] "Khấu hao và phân bổ"
## [4] "Phân bổ lợi thế thương mại"
## [5] "Các khoản dự phòng"
## [6] "(Lãi)/lỗ chênh lệch tỷ giá do đánh giá lại các khoản mục tiền tệ có gốc ngoại tệ"
## [7] "Lãi do đánh giá lại khoản đầu tư vào công ty liên kết khi trở thành công ty con"
## [8] "Lỗ từ thanh lý/xóa sổ tài sản cố định và xây dựng cơ bản dở dang"
## [9] "Thu nhập từ cổ tức, lãi tiền gửi và lãi/lỗ từ hoạt động đầu tư khác"
## [10] "(Lãi)/lỗ chia từ công ty liên kết, liên doanh"
## [11] "Chi phí lãi vay"
## [12] "Thu nhập từ khoản vay được miễn giảm"
## [13] "Lợi nhuận từ hoạt động kinh doanh trước những thay đổi vốn lưu động"
## [14] "Biến động các khoản phải thu"
## [15] "Biến động hàng tồn kho"
## [16] "Biến động các khoản phải trả và nợ phải trả khác"
## [17] "Biến động chi phí trả trước"
## [18] "Tiền chi mua TSCĐ và tài sản dài hạn khác"
## [19] "Tiền lãi vay đã trả"
## [20] "Thuế thu nhập doanh nghiệp đã nộp"
## [21] "Tiền chi khác cho hoạt động kinh doanh"
## [22] "Lưu chuyển tiền thuần từ hoạt động kinh doanh"
## [23] "Tiền chi mua tài sản cố định và tài sản dài hạn khác"
## [24] "Tiền thu từ thanh lý tài sản cố định và xây dựng cơ bản dở dang"
## [25] "Tiền chi tiền gửi có kì hạn"
## [26] "Tiền thu gửi có kỳ hạn"
## [27] "Tiền chi cho vay"
## [28] "Tiền thu hồi cho vay"
## [29] "Tiền thu hồi từ bán công cụ nợ của đơn vị khác"
## [30] "Tiền chi đầu tư góp vốn vào các đơn vị khác"
## [31] "Tiền thu hồi đầu tư vào các đơn vị khác"
## [32] "Tiền thu lãi tiền gửi và cổ tức"
## [33] "Khoản tiền thuần chi cho hợp nhất kinh doanh"
## [34] "Lưu chuyển tiền thuần từ hoạt động đầu tư"
## [35] "III. LƯU CHUYỂN TIỀN TỪ HOẠT ĐỘNG TÀI CHÍNH"
## [36] "Tiền thu từ bán cổ phiếu quỹ"
## [37] "Tiền thu từ phát hành cổ phiếu bởi công ty con cho cổ đông không kiểm soát"
## [38] "Tiền thu từ nhận góp vốn của cổ đông không kiểm soát"
## [39] "Tiền hoàn trả vốn góp cho cổ đông không kiểm soát của công ty con đã giải thể"
## [40] "Tiền thu góp vốn của cổ đông không kiểm soát"
## [41] "Tiền thu từ đi vay"
## [42] "Tiền chi trả nợ gốc vay"
## [43] "Tiền chi trả cổ tức"
## [44] "Tiền chi trả cổ tức của các công ty con chia cho cổ đông không kiểm soát"
## [45] "Lưu chuyển tiền thuần từ hoạt động tài chính"
## [46] "Lưu chuyển tiền thuần trong năm"
## [47] "Tiền và các khoản tương đương tiền đầu năm"
## [48] "Ảnh hưởng của thay đổi tỷ giá hối đoái đối với tiền và các khoản tương đương tiền"
## [49] "Chênh lệch quy đổi tiền tệ"
## [50] "Tiền và các khoản tương đương tiền cuối năm"
Giải thích kỹ thuật:
Hàm names() trả về một vector chứa tên của tất cả các cột trong data frame.
Điều này cho phép người phân tích nắm được toàn bộ các chỉ tiêu tài chính có sẵn trong mỗi báo cáo.
# Bảng CÂN ĐỐI KẾ TOÁN
CDKT_chon <- CDKT %>%
select(
Năm,
`TỔNG CỘNG TÀI SẢN`,
`NỢ PHẢI TRẢ`,
`Nợ ngắn hạn`,
`Vốn chủ sở hữu`,
`Tiền và các khoản tương đương tiền`,
`Phải thu khách hàng`,
`Hàng tồn kho`
)
# Bảng KẾT QUẢ HOẠT ĐỘNG KINH DOANH
HDKD_chon <- HDKD %>%
select(
Năm,
`Doanh thu thuần về bán hàng và cung cấp dịch vụ (10 = 01 - 02)`,
`Lợi nhuận gộp về bán hàng và cung cấp dịch vụ (20 = 10 - 11)`,
`Lợi nhuận thuần từ hoạt động kinh doanh`,
`Lợi nhuận sau thuế TNDN`,
`Trong đó: Chi phí lãi vay`
)
# Bảng LƯU CHUYỂN TIỀN TỆ
LCTT_chon <- LCTT %>%
select(
Năm,
`Lưu chuyển tiền thuần từ hoạt động kinh doanh`,
`Lưu chuyển tiền thuần từ hoạt động đầu tư`,
`Lưu chuyển tiền thuần từ hoạt động tài chính`,
`Tiền chi trả cổ tức`
)Giải thích kỹ thuật:
Hàm select() từ package dplyr cho phép chọn các cột cụ thể từ data frame dựa trên tên biến.
Dấu ` (backtick) được sử dụng để bao quanh tên biến có chứa khoảng trắng, ký tự đặc biệt hoặc ký tự tiếng Việt có dấu.
Toán tử %>% (pipe operator) giúp nối các thao tác xử lý dữ liệu một cách tuần tự và dễ đọc.
vnm <- CDKT_chon %>%
full_join(HDKD_chon, by = "Năm") %>%
full_join(LCTT_chon, by = "Năm") %>%
arrange(Năm)Giải thích kỹ thuật:
full_join() là hàm từ package dplyr, thực hiện phép nối (join) hai data frame dựa trên một hoặc nhiều cột khóa chung.
Tham số by = "Năm" chỉ định biến "Năm" là khóa để ghép các bảng.
full_join() giữ lại tất cả các hàng từ cả hai bảng, kể cả khi không có giá trị khớp (khác với inner_join() chỉ giữ hàng khớp).
arrange(Năm) sắp xếp dữ liệu theo thứ tự tăng dần của năm.
## [1] 0
Giải thích kỹ thuật:
duplicated() trả về một vector logic, với giá trị TRUE cho các hàng bị trùng lặp và FALSE cho hàng duy nhất.
sum() đếm số lượng giá trị TRUE, tức là số hàng trùng lặp.
## Năm
## 0
## TỔNG CỘNG TÀI SẢN
## 0
## NỢ PHẢI TRẢ
## 0
## Nợ ngắn hạn
## 0
## Vốn chủ sở hữu
## 0
## Tiền và các khoản tương đương tiền
## 0
## Phải thu khách hàng
## 0
## Hàng tồn kho
## 0
## Doanh thu thuần về bán hàng và cung cấp dịch vụ (10 = 01 - 02)
## 0
## Lợi nhuận gộp về bán hàng và cung cấp dịch vụ (20 = 10 - 11)
## 0
## Lợi nhuận thuần từ hoạt động kinh doanh
## 0
## Lợi nhuận sau thuế TNDN
## 0
## Trong đó: Chi phí lãi vay
## 0
## Lưu chuyển tiền thuần từ hoạt động kinh doanh
## 0
## Lưu chuyển tiền thuần từ hoạt động đầu tư
## 0
## Lưu chuyển tiền thuần từ hoạt động tài chính
## 0
## Tiền chi trả cổ tức
## 0
Giải thích kỹ thuật:
is.na() kiểm tra từng ô dữ liệu, trả về TRUE nếu giá trị là NA (missing) và FALSE nếu không.
colSums() tính tổng theo cột, cho biết mỗi biến có bao nhiêu giá trị bị thiếu.
## Warning: package 'stringi' was built under R version 4.5.2
names(vnm) <- names(vnm) %>%
stri_trans_general("Latin-ASCII") %>%
str_to_lower() %>%
str_replace_all("[^a-z0-9]+", "_") %>%
str_replace_all("_+", "_") %>%
str_remove("^_|_$")
names(vnm)## [1] "nam"
## [2] "tong_cong_tai_san"
## [3] "no_phai_tra"
## [4] "no_ngan_han"
## [5] "von_chu_so_huu"
## [6] "tien_va_cac_khoan_tuong_duong_tien"
## [7] "phai_thu_khach_hang"
## [8] "hang_ton_kho"
## [9] "doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02"
## [10] "loi_nhuan_gop_ve_ban_hang_va_cung_cap_dich_vu_20_10_11"
## [11] "loi_nhuan_thuan_tu_hoat_dong_kinh_doanh"
## [12] "loi_nhuan_sau_thue_tndn"
## [13] "trong_do_chi_phi_lai_vay"
## [14] "luu_chuyen_tien_thuan_tu_hoat_dong_kinh_doanh"
## [15] "luu_chuyen_tien_thuan_tu_hoat_dong_dau_tu"
## [16] "luu_chuyen_tien_thuan_tu_hoat_dong_tai_chinh"
## [17] "tien_chi_tra_co_tuc"
Giải thích kỹ thuật:
stri_trans_general("Latin-ASCII") từ package stringi chuyển đổi ký tự Unicode có dấu sang ký tự ASCII không dấu (ví dụ: "ả" → "a").
str_to_lower() chuyển tất cả ký tự sang chữ thường.
str_replace_all("[^a-z0-9]+", "_") thay thế mọi ký tự không phải chữ cái hoặc số bằng dấu gạch dưới.
str_replace_all("_+", "_") gộp nhiều dấu gạch dưới liên tiếp thành một.
str_remove("^_|_$") loại bỏ dấu gạch dưới ở đầu hoặc cuối tên biến.
vnm <- vnm %>%
arrange(nam) %>%
mutate(tai_san_bq = (tong_cong_tai_san + lag(tong_cong_tai_san)) / 2)Giải thích kỹ thuật:
arrange(nam) sắp xếp dữ liệu theo thứ tự tăng dần của năm, đảm bảo hàm lag() hoạt động đúng.
lag() lấy giá trị của biến ở hàng trước đó (năm t-1).
mutate() tạo biến mới tai_san_bq là trung bình cộng của tài sản năm hiện tại và năm trước.
vnm <- vnm %>%
mutate(ros = loi_nhuan_sau_thue_tndn / doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02)Giải thích kỹ thuật:
mutate() tạo biến mới ros bằng cách chia Lợi nhuận sau thuế cho Doanh thu thuần.
Công thức: ROS = Lợi nhuận sau thuế / Doanh thu thuần × 100%.
Giải thích kỹ thuật:
mutate() tạo biến mới
ROA được tính bằng Lợi nhuận sau thuế chia cho Tổng tài sản bình quân.
Sử dụng tai_san_bq (đã tính ở bước 2) thay vì tài sản cuối kỳ.
vnm <- vnm %>%
mutate(von_chu_bq = (von_chu_so_huu + lag(von_chu_so_huu)) / 2,
roe = loi_nhuan_sau_thue_tndn / von_chu_bq)Giải thích kỹ thuật:
mutate() tạo biến mới
Tương tự ROA, ROE cũng sử dụng giá trị bình quân của Vốn chủ sở hữu.
von_chu_bq là trung bình cộng của vốn chủ năm hiện tại và năm trước.
ROE = Lợi nhuận sau thuế / Vốn chủ sở hữu bình quân.
vnm <- vnm %>%
mutate(tang_truong_doanh_thu = (doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02 -
lag(doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02)) /
lag(doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02))Giải thích kỹ thuật:
mutate() tạo biến mới
Công thức tính tốc độ tăng trưởng: (Giá trị hiện tại - Giá trị kỳ trước) / Giá trị kỳ trước.
lag() lấy doanh thu năm trước làm gốc so sánh.
Kết quả là tỷ lệ thay đổi tương đối, thường biểu diễn dưới dạng phần trăm.
Giải thích kỹ thuật:
mutate() tạo biến mới
Công thức đơn giản: Vốn chủ sở hữu / Tổng tài sản.
Kết quả là tỷ lệ trong khoảng [0, 1], cho biết tỷ trọng vốn chủ sở hữu trong tổng nguồn vốn.
Giải thích kỹ thuật:
mutate() tạo biến mới
log(): Hàm logarit tự nhiên (cơ số e) trong R.
Biến đổi logarit giúp chuẩn hóa phân phối và giảm độ lệch do sự chênh lệch lớn về quy mô.
Giải thích kỹ thuật:
mutate() tạo biến mới
Công thức: Tổng nợ phải trả / Tổng tài sản.
Kết quả trong khoảng [0, 1], cho biết tỷ lệ tài sản được tài trợ bằng nợ.
vnm <- vnm %>%
mutate(ts_ngan_han = tien_va_cac_khoan_tuong_duong_tien + phai_thu_khach_hang + hang_ton_kho,
he_so_thanh_toan_ngan_han = ts_ngan_han / no_ngan_han)Giải thích kỹ thuật:
Tạo biến ts_ngan_han bằng tổng ba thành phần thanh khoản chính: tiền, khoản phải thu và hàng tồn kho.
he_so_thanh_toan_ngan_han = Tài sản ngắn hạn / Nợ ngắn hạn.
vnm <- vnm %>%
mutate(nhom_tang_truong = case_when(
tang_truong_doanh_thu < 0 ~ "Suy giảm",
tang_truong_doanh_thu < 0.1 ~ "Ổn định",
TRUE ~ "Tăng trưởng cao"
))Giải thích kỹ thuật:
case_when(): Hàm trong dplyr cho phép tạo nhiều điều kiện phân loại theo thứ tự ưu tiên.
Các điều kiện được đánh giá từ trên xuống dưới, điều kiện đầu tiên thỏa mãn sẽ được áp dụng.
TRUE ~ đóng vai trò như điều kiện "else", bắt tất cả các trường hợp còn lại.
vnm <- vnm %>%
mutate(
nhom_hieu_qua = case_when(
roe >= quantile(roe, 0.67, na.rm = TRUE) ~ "Hiệu quả cao",
roe >= quantile(roe, 0.33, na.rm = TRUE) ~ "Hiệu quả trung bình",
TRUE ~ "Hiệu quả thấp"
)
)
vnm %>% count(nhom_hieu_qua)Giải thích kỹ thuật:
quantile(roe, 0.67, na.rm = TRUE): Tính phân vị thứ 67% (tercile thứ hai) của ROE, bỏ qua giá trị NA.
quantile(roe, 0.33, na.rm = TRUE): Tính phân vị thứ 33% (tercile thứ nhất).
Phân chia dữ liệu thành ba nhóm đều nhau dựa trên phân vị, đảm bảo mỗi nhóm chiếm khoảng 1/3 số quan sát.
vnm <- vnm %>%
mutate(
hieu_qua_ROE = case_when(
roe >= quantile(roe, 0.67, na.rm = TRUE) ~ "Tốt",
roe >= quantile(roe, 0.33, na.rm = TRUE) ~ "Trung bình",
TRUE ~ "Thấp"
),
hieu_qua_ROA = case_when(
roa >= quantile(roa, 0.67, na.rm = TRUE) ~ "Tốt",
roa >= quantile(roa, 0.33, na.rm = TRUE) ~ "Trung bình",
TRUE ~ "Thấp"
)
)Giải thích kỹ thuật:
Áp dụng cùng phương pháp phân vị như mục 12, nhưng tạo riêng hai biến phân loại cho ROE và ROA.
Nhãn được đơn giản hóa thành "Tốt", "Trung bình", "Thấp" để dễ diễn giải.
Hai biến này độc lập nhau, cho phép phân tích ma trận hiệu quả 3×3.
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 4.008e+13 5.142e+13 5.798e+13 5.495e+13 6.027e+13 6.178e+13
Giải thích kỹ thuật:
Hàm summary() là hàm cơ bản trong R dùng để tính toán các chỉ số thống kê mô tả cho biến số liên tục, bao gồm:
Min.: Giá trị nhỏ nhất trong tập dữ liệu
1st Qu.: Phân vị thứ nhất (25%) - giá trị mà 25% quan sát nhỏ hơn nó
Median: Trung vị (50%) - giá trị ở giữa khi sắp xếp tăng dần
Mean: Giá trị trung bình cộng
3rd Qu.: Phân vị thứ ba (75%) - giá trị mà 75% quan sát nhỏ hơn nó
Max.: Giá trị lớn nhất
Ý nghĩa thống kê:
Kết quả cho thấy doanh thu thuần của VNM giai đoạn 2015-2024 dao động từ 40.080 nghìn tỷ đồng (năm 2015) đến 61.780 nghìn tỷ đồng (năm 2024), với giá trị trung bình 54.950 nghìn tỷ đồng và trung vị 57.980 nghìn tỷ đồng.
Sự chênh lệch giữa trung bình và trung vị tương đối nhỏ (54.950 so với 57.980), cho thấy phân phối doanh thu nghiêng trái nhẹ (left-skewed), phản ánh xu hướng tăng trưởng doanh thu ổn định qua các năm. Khoảng tứ phân vị (IQR = Q3 - Q1 = 60.270 - 51.420 ≈ 8.850 nghìn tỷ) cho thấy 50% giá trị trung tâm phân bố trong biên độ khá hẹp, chứng tỏ doanh thu tương đối ổn định và ít biến động mạnh.
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 7.770e+12 9.105e+12 9.829e+12 9.709e+12 1.049e+13 1.124e+13
Giải thích kỹ thuật:
Tương tự biến doanh thu, hàm summary() được áp dụng cho biến lợi nhuận sau thuế thu nhập doanh nghiệp (LNST), trả về bộ 6 chỉ số thống kê mô tả cơ bản giúp đánh giá xu thế trung tâm, độ phân tán và hình dạng phân phối của biến.
Ý nghĩa thống kê:
Lợi nhuận sau thuế của VNM biến động từ 7.770 nghìn tỷ đồng đến 11.240 nghìn tỷ đồng, với trung bình 9.709 nghìn tỷ đồng và trung vị 9.829 nghìn tỷ đồng.
Giá trị trung bình gần với trung vị cho thấy phân phối lợi nhuận tương đối đối xứng, phản ánh sự ổn định trong khả năng sinh lời của doanh nghiệp. Tuy nhiên, biên độ dao động (Max - Min ≈ 3.470 nghìn tỷ) tương đối lớn, tương đương 44,7% so với giá trị nhỏ nhất, cho thấy lợi nhuận chịu ảnh hưởng đáng kể từ các yếu tố kinh doanh và thị trường qua các năm. Điều này đặt ra yêu cầu phân tích sâu hơn về các yếu tố tác động đến biến động lợi nhuận.
vnm %>%
summarise(
mean = mean(tong_cong_tai_san, na.rm = TRUE),
sd = sd(tong_cong_tai_san, na.rm = TRUE),
min = min(tong_cong_tai_san, na.rm = TRUE),
max = max(tong_cong_tai_san, na.rm = TRUE),
median = median(tong_cong_tai_san, na.rm = TRUE)
)Giải thích kỹ thuật:
summarise() (từ package dplyr): tạo bảng tóm tắt với các chỉ số được tính toán
mean(): tính giá trị trung bình cộng
sd(): tính độ lệch chuẩn (standard deviation) - đo lường độ phân tán xung quanh giá trị trung bình
min(), max(): giá trị nhỏ nhất và lớn nhất
median(): trung vị
Tham số na.rm = TRUE: loại bỏ giá trị thiếu (NA) khỏi tính toán
Ý nghĩa thống kê:
Tổng tài sản bình quân của VNM đạt 43.200 nghìn tỷ đồng với độ lệch chuẩn 10.200 nghìn tỷ đồng (hệ số biến thiên CV = 10.200/43.200 ≈ 23,6%), cho thấy quy mô tài sản có biến động đáng kể qua thời gian nghiên cứu.
Tài sản tăng từ 27.500 nghìn tỷ đồng (2015) lên 55.000 nghìn tỷ đồng (2024), tương đương mức tăng trưởng 100% trong 9 năm (CAGR ≈ 8,0% mỗi năm). Trung vị (46.600 nghìn tỷ) cao hơn trung bình (43.200 nghìn tỷ), cho thấy phân phối nghiêng phải (right-skewed), phản ánh xu hướng gia tăng quy mô tài sản mạnh mẽ trong những năm gần đây, đặc biệt từ 2019 trở đi khi công ty thực hiện chiến lược mở rộng và M&A
Giải thích kỹ thuật:
filter(): hàm lọc dữ liệu theo điều kiện logic
Điều kiện < 0: giữ lại các quan sát có dòng tiền thuần từ hoạt động kinh doanh (CFO - Cash Flow from Operations) âm
Kết quả là một tập con (subset) chỉ chứa các năm không đạt dòng tiền dương từ hoạt động cốt lõi
Ý nghĩa thống kê:
Kết quả trả về 0 quan sát, chứng tỏ VNM duy trì dòng tiền hoạt động dương liên tục trong toàn bộ giai đoạn 2015-2024. Đây là dấu hiệu tích cực về chất lượng lợi nhuận và sức khỏe tài chính.
Dòng tiền hoạt động dương thường xuyên cho thấy:
Lợi nhuận kế toán có nền tảng tiền mặt thực (không chỉ là lợi nhuận “trên giấy”)
Doanh nghiệp có khả năng thu hồi công nợ tốt
Chu kỳ chuyển đổi tiền mặt (cash conversion cycle) được quản lý hiệu quả
Công ty có nguồn lực nội sinh để tái đầu tư và chi trả cổ tức
Điều này đặc biệt quan trọng trong ngành sữa - ngành có đặc thủy chu kỳ sản xuất dài, hàng tồn kho lớn và yêu cầu vốn lưu động cao.
vnm %>%
group_by(nhom_tang_truong) %>%
summarise(across(c(roa, roe, ros, debt_ratio), mean, na.rm = TRUE))## Warning: There was 1 warning in `summarise()`.
## ℹ In argument: `across(c(roa, roe, ros, debt_ratio), mean, na.rm = TRUE)`.
## ℹ In group 1: `nhom_tang_truong = "Suy giảm"`.
## Caused by warning:
## ! The `...` argument of `across()` is deprecated as of dplyr 1.1.0.
## Supply arguments directly to `.fns` through an anonymous function instead.
##
## # Previously
## across(a:b, mean, na.rm = TRUE)
##
## # Now
## across(a:b, \(x) mean(x, na.rm = TRUE))
Giải thích kỹ thuật:
group_by(nhom_tang_truong): gom nhóm dữ liệu theo biến phân loại “nhóm tăng trưởng”
across(): áp dụng cùng một hàm cho nhiều cột cùng lúc
c(roa, roe, ros, debt_ratio): danh sách các biến cần tính toán
mean: hàm tính trung bình được áp dụng cho từng biến trong từng nhóm
na.rm = TRUE: bỏ qua giá trị thiếu
Ý nghĩa thống kê:
Kết quả cho thấy mối quan hệ rõ rệt giữa tốc độ tăng trưởng doanh thu và hiệu quả tài chính:
Nhóm “Tăng trưởng cao” (tăng trưởng doanh thu ≥ 10%):ROA = 32,9%, ROE = 43,2%, ROS = 19,7%. Tỷ lệ nợ thấp nhất (23,8%). Phản ánh giai đoạn hoạt động hiệu quả nhất, công ty tận dụng tối ưu tài sản và vốn chủ để tạo ra lợi nhuận cao Nhóm “Ổn định” (0% < tăng trưởng < 10%): ROA = 23,8%, ROE = 34,6%, ROS = 17,8%. Tỷ lệ nợ cao hơn (32,2%). Các chỉ số sinh lời ở mức trung bình, cho thấy doanh nghiệp đang trong giai đoạn duy trì và củng cố Nhóm “Suy giảm” (tăng trưởng âm): ROA = 16,8%, ROE = 25,0%, ROS = 14,3%. Tỷ lệ nợ 32,3%. Các chỉ số thấp nhất, phản ánh năm 2022 khi doanh thu giảm do ảnh hưởng hậu COVID-19
Phân tích này cho thấy tăng trưởng doanh thu là động lực chính thúc đẩy hiệu quả tài chính. Đồng thời, các năm tăng trưởng cao thường đi kèm với cơ cấu vốn lành mạnh hơn (nợ thấp), chứng tỏ công ty ưu tiên tăng trưởng bền vững.
vnm <- vnm %>%
arrange(nam) %>%
mutate(
delta_doanh_thu = doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02 - lag(doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02),
delta_loi_nhuan = loi_nhuan_sau_thue_tndn - lag(loi_nhuan_sau_thue_tndn),
delta_roa = roa - lag(roa),
delta_roe = roe - lag(roe)
)
vnm %>%
select(nam, delta_doanh_thu, delta_loi_nhuan, delta_roa, delta_roe)Giải thích kỹ thuật:
arrange(nam): sắp xếp dữ liệu theo thứ tự thời gian tăng dần
mutate(): tạo biến mới
lag(): hàm lấy giá trị của quan sát trước đó (năm t-1)
Phép trừ giá trị hiện tại - lag(giá trị): tính biến động tuyệt đối (delta) giữa hai năm liên tiếp
Các biến delta được tạo ra giúp phân tích tốc độ thay đổi năm-qua-năm (year-over-year change) của các chỉ tiêu.
Ý nghĩa thống kê:
Giai đoạn 2016–2017 – Tăng trưởng mạnh: Doanh thu và lợi nhuận tăng nhanh (doanh thu +6.714 và +4.247 tỷ; lợi nhuận +1.590 và +914 tỷ), ROE cải thiện +1,2 điểm %. Vinamilk hưởng lợi từ mở rộng thị trường, nhu cầu tiêu dùng và xuất khẩu tăng.
Giai đoạn 2018–2019 – Hiệu quả suy giảm: Lợi nhuận giảm nhẹ (-72,5 tỷ), ROA và ROE giảm mạnh (-3,7 điểm %) do giá nguyên liệu tăng và chi phí marketing lớn. Biên lợi nhuận thu hẹp phản ánh cạnh tranh gay gắt trong ngành.
Giai đoạn 2020–2021 – Phục hồi rồi chững lại: Năm 2020 lợi nhuận tăng (+681 tỷ) nhờ tiêu dùng phục hồi, nhưng năm 2021 giảm mạnh (-603 tỷ), ROE giảm -4,86 điểm % do ảnh hưởng kéo dài của COVID-19 và chi phí logistics tăng cao.
Năm 2022 – Suy giảm mạnh nhất: Doanh thu giảm lần đầu (-962,9 tỷ), lợi nhuận giảm sâu (-2.050 tỷ), ROE giảm -5,62 điểm % do lạm phát, chi phí nguyên liệu cao và sức mua yếu.
Giai đoạn 2023–2024 – Phục hồi ổn định: Doanh thu và lợi nhuận tăng trở lại, ROE cải thiện +1,61 điểm %, cho thấy VNM đã vượt qua giai đoạn khó khăn, hoạt động tài chính phục hồi bền vững.
cv <- function(x) sd(x, na.rm = TRUE) / mean(x, na.rm = TRUE)
vnm %>%
summarise(across(c(roa, roe, ros, debt_ratio, tang_truong_doanh_thu), cv))Giải thích kỹ thuật:
Hàm cv(): tính hệ số biến thiên (Coefficient of Variation)
across(): áp dụng hàm cv() cho nhiều biến cùng lúc
Ý nghĩa thống kê:
Kết quả cho thấy mức độ ổn định khác nhau của các chỉ tiêu:
ROS (12,4%): Biến động thấp nhất, cho thấy biên lợi nhuận tương đối ổn định qua các năm. Điều này phản ánh khả năng kiểm soát chi phí và định giá hiệu quả của VNM.
Debt Ratio (12,5%): Tỷ lệ nợ cũng ổn định, chứng tỏ công ty duy trì cơ cấu vốn nhất quán, không có biến động lớn về chính sách tài trợ.
ROE (21,9%): Biến động trung bình, phản ánh hiệu quả sử dụng vốn chủ chịu ảnh hưởng từ cả lợi nhuận và đòn bẩy tài chính.
ROA (25,8%): Biến động cao hơn ROE, cho thấy hiệu quả sử dụng tổng tài sản bị tác động nhiều hơn bởi các yếu tố hoạt động.
Tăng trưởng doanh thu (109%): Biến động cực cao, phản ánh sự chênh lệch lớn giữa các năm tăng trưởng mạnh và năm suy giảm (2022). Đây là biến số kém ổn định nhất, chịu tác động mạnh từ chu kỳ kinh tế và yếu tố bên ngoài.
Phân tích CV cho thấy VNM duy trì được ổn định về mặt lợi nhuận và cơ cấu vốn (ROS, debt ratio), nhưng doanh thu và hiệu suất tài sản biến động nhiều hơn do ảnh hưởng của môi trường kinh doanh.
vnm %>%
filter(roa > mean(roa, na.rm = TRUE) & roe > mean(roe, na.rm = TRUE)) %>%
select(nam, roa, roe, ros, debt_ratio)Giải thích kỹ thuật:
filter(): lọc các quan sát thỏa mãn đồng thời hai điều kiện
Điều kiện 1: roa > mean(roa, na.rm = TRUE) - ROA cao hơn trung bình
Điều kiện 2: roe > mean(roe, na.rm = TRUE) - ROE cao hơn trung bình
Toán tử &: phép AND logic, yêu cầu cả hai điều kiện đều đúng
select(): chọn các cột cần hiển thị
Ý nghĩa thống kê:
Giai đoạn 2016–2020: Hoàng kim
Trong 5 năm này, ROA và ROE đều vượt mức trung bình, phản ánh hiệu quả vận hành cao. Năm 2016–2017 là đỉnh cao: ROE đạt 43,2% và 44,4%, ROA đạt 32,9% và 32,1%, ROS ổn định quanh 20%, tỷ lệ nợ thấp (23,7%–31,1%). Đây là kết quả từ các thương vụ M&A Driftwood Dairy và Angkor Dairy, tối ưu hóa lợi nhuận và vốn chủ sở hữu.
2018–2020: Hiệu quả giảm dần. ROE giảm xuống 40,7%–35,5%, ROA giảm tương ứng, tỷ lệ nợ tăng nhẹ (29,7%–33,5%). Hiệu quả vẫn cao nhưng áp lực cạnh tranh và chi phí đầu vào bắt đầu ảnh hưởng đến kết quả tài chính.
Giai đoạn 2021–2024: Dưới trung bình. ROE dao động 25,0%–30,6%, ROA dao động 16,8%–22,3%. COVID-19, lạm phát và cạnh tranh gia tăng khiến lợi nhuận và hiệu quả sử dụng tài sản giảm.
Tổng thể, VNM trải qua chu kỳ tăng trưởng mạnh, sau đó bước vào giai đoạn điều chỉnh và phục hồi cần quản trị rủi ro.
vars <- vnm %>%
select(
roa, roe,
debt_ratio,
tang_truong_doanh_thu,
size,
von_chu_so_huu,
tong_cong_tai_san
)
round(cor(vars, use = "pairwise.complete.obs"), 3)## roa roe debt_ratio tang_truong_doanh_thu size
## roa 1.000 0.991 -0.735 0.854 -0.924
## roe 0.991 1.000 -0.661 0.806 -0.879
## debt_ratio -0.735 -0.661 1.000 -0.786 0.901
## tang_truong_doanh_thu 0.854 0.806 -0.786 1.000 -0.812
## size -0.924 -0.879 0.901 -0.812 1.000
## von_chu_so_huu -0.925 -0.894 0.828 -0.763 0.988
## tong_cong_tai_san -0.929 -0.892 0.877 -0.786 0.996
## von_chu_so_huu tong_cong_tai_san
## roa -0.925 -0.929
## roe -0.894 -0.892
## debt_ratio 0.828 0.877
## tang_truong_doanh_thu -0.763 -0.786
## size 0.988 0.996
## von_chu_so_huu 1.000 0.995
## tong_cong_tai_san 0.995 1.000
Giải thích kỹ thuật:
select(): chọn tập con các biến số cần phân tích tương quan
cor(): tính ma trận tương quan Pearson giữa các cặp biến
Tham số use = "pairwise.complete.obs": với mỗi cặp biến, chỉ sử dụng các quan sát có đầy đủ cả hai giá trị (loại bỏ NA theo cặp)
round(..., 3): làm tròn kết quả đến 3 chữ số thập phân
Hệ số tương quan Pearson (r) dao động từ -1 đến +1:
r > 0: tương quan dương (cùng chiều)
r < 0: tương quan âm (ngược chiều)
|r| càng gần 1: mối quan hệ tuyến tính càng mạnh
Ý nghĩa thống kê:
Ma trận tương quan cho thấy các mối quan hệ đáng chú ý:
Nhóm tương quan dương mạnh:
ROE và ROA có tương quan rất cao (0.991), điều này hợp lý vì cả hai đều đo lường hiệu suất sinh lời, chỉ khác mẫu số (vốn chủ vs tài sản). Mối quan hệ gần như tuyệt đối này cho thấy cấu trúc vốn của VNM tương đối ổn định.
Tăng trưởng doanh thu tương quan dương mạnh với ROA (0.854) và ROE (0.806), chứng tỏ các năm tăng trưởng doanh thu cao thường đi kèm với hiệu quả sinh lời tốt—phản ánh khả năng quản lý chi phí và tận dụng quy mô kinh tế.
Size, vốn chủ sở hữu và tổng tài sản có tương quan cực cao với nhau (> 0.99), điều này đương nhiên vì size = log(tài sản) và vốn chủ là thành phần chính của tài sản.
Nhóm tương quan âm mạnh:
ROA và ROE tương quan âm mạnh với size (-0.924 và -0.879), von_chu_so_huu (-0.925 và -0.894), tong_cong_tai_san (-0.929 và -0.892). Đây là phát hiện quan trọng: khi VNM mở rộng quy mô (tăng tài sản, vốn), hiệu suất sinh lời có xu hướng giảm. Điều này phản ánh hiện tượng “giảm lợi nhuận biên” (diminishing returns) khi doanh nghiệp trưởng thành—các khoản đầu tư mới khó đạt được hiệu quả cao như giai đoạn đầu.
Tỷ lệ nợ (debt_ratio) tương quan âm với ROA (-0.735) và ROE (-0.661), cho thấy các năm VNM tăng đòn bẩy tài chính thường có hiệu suất sinh lời thấp hơn. Điều này trái với lý thuyết đòn bẩy tích cực, gợi ý rằng VNM có thể sử dụng nợ vào các khoản đầu tư chưa sinh lời ngay hoặc chi phí lãi vay cao làm xói mòn lợi nhuận.
Debt_ratio tương quan dương với size (0.901), nghĩa là khi quy mô tăng, VNM có xu hướng tăng sử dụng nợ vay—chiến lược tài trợ phổ biến trong giai đoạn mở rộng.
Tăng trưởng doanh thu tương quan âm với debt_ratio (-0.786), cho thấy các năm tăng trưởng cao thường là những năm VNM giảm tỷ lệ nợ hoặc tăng cường vốn chủ sở hữu.
Hàm ý quản trị: Ma trận này cung cấp bằng chứng định lượng về trade-off giữa tăng trưởng quy mô và hiệu quả hoạt động. VNM cần cân bằng giữa việc mở rộng (để duy trì vị thế thị trường) và duy trì lợi nhuận biên (để thỏa mãn cổ đông). Đồng thời, việc sử dụng nợ cần được tối ưu hóa để đảm bảo các khoản vay thực sự tạo ra giá trị gia tăng
vnm %>%
arrange(nam) %>%
mutate(delta_ts = tong_cong_tai_san - lag(tong_cong_tai_san),
delta_vc = von_chu_so_huu - lag(von_chu_so_huu)) %>%
select(nam, tong_cong_tai_san, delta_ts, von_chu_so_huu, delta_vc)vnm %>%
filter(debt_ratio > mean(debt_ratio, na.rm = TRUE),
roe > mean(roe, na.rm = TRUE)) %>%
select(nam, roe, roa, debt_ratio)vnm %>%
mutate(ty_le_co_tuc_roe = tien_chi_tra_co_tuc / (roe * von_chu_so_huu)) %>%
select(nam, tien_chi_tra_co_tuc, roe, ty_le_co_tuc_roe)vnm %>%
mutate(ty_le_cce = luu_chuyen_tien_thuan_tu_hoat_dong_kinh_doanh / loi_nhuan_sau_thue_tndn) %>%
select(nam, luu_chuyen_tien_thuan_tu_hoat_dong_kinh_doanh, loi_nhuan_sau_thue_tndn, ty_le_cce)vnm %>%
mutate(ty_le_giu_lai = 1 - (tien_chi_tra_co_tuc / loi_nhuan_sau_thue_tndn)) %>%
select(nam, loi_nhuan_sau_thue_tndn, tien_chi_tra_co_tuc, ty_le_giu_lai)vnm %>%
group_by(nhom_tang_truong) %>%
summarise(across(c(luu_chuyen_tien_thuan_tu_hoat_dong_dau_tu,
luu_chuyen_tien_thuan_tu_hoat_dong_tai_chinh), mean, na.rm = TRUE))## Warning: There were 3 warnings in `summarise()`.
## The first warning was:
## ℹ In argument: `across(...)`.
## ℹ In group 1: `nhom_tang_truong = "Suy giảm"`.
## Caused by warning in `mean.default()`:
## ! argument is not numeric or logical: returning NA
## ℹ Run `dplyr::last_dplyr_warnings()` to see the 2 remaining warnings.
vnm %>%
arrange(nam) %>%
mutate(
pct_ts = (tong_cong_tai_san / lag(tong_cong_tai_san) - 1),
pct_dt = (doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02 / lag(doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02) - 1),
pct_ln = (loi_nhuan_sau_thue_tndn / lag(loi_nhuan_sau_thue_tndn) - 1)
) %>%
select(nam, pct_ts, pct_dt, pct_ln)data1p <- subset(
vnm,
roe > 0.15 & hieu_qua_ROE == "Tốt"
)
data1p %>%
select(nam, tong_cong_tai_san, von_chu_so_huu, no_phai_tra, roe, hieu_qua_ROE)data4p <- subset(
vnm,
luu_chuyen_tien_thuan_tu_hoat_dong_kinh_doanh > 0 &
roe > 0.13
)
data4p %>%
select(nam, roe, luu_chuyen_tien_thuan_tu_hoat_dong_kinh_doanh)data10p <- subset(
vnm,
luu_chuyen_tien_thuan_tu_hoat_dong_kinh_doanh > 0 &
luu_chuyen_tien_thuan_tu_hoat_dong_tai_chinh < 0 &
roe > mean(roe, na.rm = TRUE)
)
data10p %>%
select(nam, roe, luu_chuyen_tien_thuan_tu_hoat_dong_kinh_doanh, luu_chuyen_tien_thuan_tu_hoat_dong_tai_chinh)library(ggplot2)
ggplot(vnm, aes(x = nam, y = debt_ratio)) +
geom_line(linewidth = 1.2, color = "#C3F550") +
geom_point(size = 2) +
geom_smooth(method = "loess", se = FALSE, color = "#1b4332") +
labs(title = "Tỷ lệ nợ qua các năm", y = "Debt ratio", x = "Năm") +
theme_minimal()## `geom_smooth()` using formula = 'y ~ x'
## Warning: package 'reshape2' was built under R version 4.5.2
vars <- vnm |> dplyr::select(roe, roa, ros, debt_ratio, tang_truong_doanh_thu,
size,von_chu_so_huu, tong_cong_tai_san)
mat <- round(cor(vars, use = "pairwise.complete.obs"), 2)
dfm <- reshape2::melt(mat, varnames = c("x","y"), value.name = "corr")
ggplot(dfm, aes(x, y, fill = corr)) +
geom_tile(color = "white") +
geom_text(aes(label = corr), size = 3) +
scale_fill_gradient2(low="#b2182b", mid="white", high="#2166ac", midpoint=0) +
coord_equal() +
labs(title = "Ma trận tương quan (heatmap)", x = "", y = "") +
theme(axis.text.x = element_text(angle=45, hjust=1))vnm_long2 <- vnm %>%
tidyr::pivot_longer(cols = c(doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02,
loi_nhuan_sau_thue_tndn),
names_to = "chiso", values_to = "giatri")
ggplot(vnm_long2, aes(x = as.factor(nam), y = giatri/1e12, fill = chiso)) +
geom_col(position = "dodge") +
scale_fill_manual(values = c("#4daf4a", "#e41a1c"),
labels = c("Doanh thu thuần", "Lợi nhuận sau thuế")) +
labs(
title = "So sánh doanh thu và lợi nhuận theo năm",
x = "Năm", y = "Giá trị (nghìn tỷ)", fill = "Chỉ tiêu"
) +
theme_minimal()vnm_sub <- vnm %>%
select(nam, roe, roa, ros, debt_ratio) %>%
tidyr::pivot_longer(cols = -nam, names_to = "chiso", values_to = "giatri")
ggplot(vnm_sub, aes(x = nam, y = giatri, color = chiso)) +
geom_line(linewidth = 1) +
geom_point(size = 2) +
facet_wrap(~ chiso, scales = "free_y", ncol = 2) +
labs(
title = "Diễn biến các chỉ tiêu tài chính chính qua các năm",
x = "Năm", y = "Giá trị"
) +
theme_minimal()## Warning: Removed 2 rows containing missing values or values outside the scale range
## (`geom_line()`).
## Warning: Removed 2 rows containing missing values or values outside the scale range
## (`geom_point()`).
library(ggplot2); library(scales)
ggplot(vnm, aes(x = nam,
y = doanh_thu_thuan_ve_ban_hang_va_cung_cap_dich_vu_10_01_02/1e12)) +
geom_line(color = "grey60") +
geom_point(aes(size = loi_nhuan_sau_thue_tndn/1e12, color = ros), alpha=.85) +
scale_color_gradient(low = "#fee0d2", high = "#cb181d") +
scale_size_continuous(range = c(3,10), name = "LNST (nghìn tỷ)") +
scale_x_continuous(breaks = seq(min(vnm$nam), max(vnm$nam), 1)) +
labs(title = "Doanh thu – LNST – ROS",
x = "Năm", y = "Doanh thu (nghìn tỷ)", color = "ROS") +
theme_minimal()roll_sd <- function(x, k = 3) {
sapply(seq_along(x), function(i) {
j <- max(1, i - k + 1):i
sd(x[j], na.rm = TRUE)
})
}
rv <- vnm %>%
arrange(nam) %>%
mutate(roe_sd3 = roll_sd(roe, 3))
ggplot(rv, aes(nam)) +
geom_col(aes(y = roe_sd3), fill = "#a8ddb5", alpha = 0.8) +
geom_line(aes(y = roe), color = "#2e8b57", linewidth = 1.2) +
geom_point(aes(y = roe), size = 3, color = "#006d2c") +
geom_hline(yintercept = mean(rv$roe_sd3, na.rm = TRUE),
linetype = 2, color = "#66bb6a") +
labs(
title = "Độ biến động ROE (Trung bình trượt 3 năm)",
x = "Năm",
y = "Giá trị"
) +
theme_minimal(base_size = 13) ## Warning: Removed 2 rows containing missing values or values outside the scale range
## (`geom_col()`).
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_line()`).
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_point()`).
library(dplyr)
pareto <- vnm %>%
arrange(desc(loi_nhuan_sau_thue_tndn)) %>%
mutate(ty_le = loi_nhuan_sau_thue_tndn / sum(loi_nhuan_sau_thue_tndn),
ty_le_tich_luy = cumsum(ty_le))
ggplot(pareto, aes(x = reorder(as.factor(nam), -loi_nhuan_sau_thue_tndn))) +
geom_col(aes(y = ty_le*100), fill = "#66bb6a") +
geom_line(aes(y = ty_le_tich_luy*100, group = 1), color = "#2e7d32", linewidth = 1) +
geom_point(aes(y = ty_le_tich_luy*100), color = "#004d40", size = 3) +
geom_text(aes(y = ty_le*100, label = paste0(round(ty_le*100,1), "%")),
vjust = -0.3, size = 3) +
labs(title = "Tỷ trọng lợi nhuận theo năm",
x = "Năm", y = "Tỷ trọng (%)") + theme_minimal(base_size = 13)##
## Attaching package: 'tidyr'
## The following object is masked from 'package:reshape2':
##
## smiths
library(ggplot2)
vnm_cf <- vnm %>%
select(nam,
luu_chuyen_tien_thuan_tu_hoat_dong_kinh_doanh,
luu_chuyen_tien_thuan_tu_hoat_dong_dau_tu,
luu_chuyen_tien_thuan_tu_hoat_dong_tai_chinh) %>%
mutate(across(-nam, ~as.numeric(.))) %>%
pivot_longer(-nam, names_to = "hoat_dong", values_to = "dong_tien")## Warning: There was 1 warning in `mutate()`.
## ℹ In argument: `across(-nam, ~as.numeric(.))`.
## Caused by warning:
## ! NAs introduced by coercion
ggplot(vnm_cf, aes(x = factor(nam), y = dong_tien/1e12, fill = hoat_dong)) +
geom_col() +
scale_fill_manual(values = c("#2e7d32", "#81c784", "#a5d6a7"),
labels = c("Kinh doanh", "Đầu tư", "Tài chính")) +
geom_hline(yintercept = 0, color = "#004d40", linetype = "dashed") +
labs(title = "Dòng tiền theo hoạt động", x = "Năm", y = "Nghìn tỷ") +
theme_minimal(base_size = 13) +
theme(legend.position = "top")## Warning: Removed 2 rows containing missing values or values outside the scale range
## (`geom_col()`).
ggplot(vnm, aes(x = nam)) +
geom_col(aes(y = tong_cong_tai_san/1e12, fill = "Tổng tài sản"), alpha = 0.6) +
geom_line(aes(y = von_chu_so_huu/1e12, color = "Vốn chủ sở hữu"), linewidth = 1.2) +
geom_point(aes(y = von_chu_so_huu/1e12, color = "Vốn chủ sở hữu"), size = 3) +
geom_line(aes(y = no_phai_tra/1e12, linetype = "Nợ phải trả"), linewidth = 1.2, color = "#e41a1c") +
geom_text(aes(y = tong_cong_tai_san/1e12, label = round(tong_cong_tai_san/1e12,1)), vjust=-0.5, size=3) +
labs(title="Cấu trúc Tài sản – Vốn – Nợ theo năm", x="Năm", y="Tỷ nghìn tỷ", fill="", color="", linetype="") +
theme_minimal()