Giảng viên hướng dẫn: ThS. Trần Mạnh Tường
Sinh viên
thực hiện: Nhóm 24: Lê Ngọc Tường Vy và Trần Hoàng Minh Nhật
08/11/2025
Nhóm xin gửi lời cảm ơn chân thành đến Thầy ThS. Trần Mạnh Tường đã tận tình hướng dẫn, hỗ trợ và định hướng trong suốt quá trình thực hiện tiểu luận. Nhờ sự chỉ dẫn và góp ý tận tâm của Thầy, nhóm đã hiểu sâu hơn về nội dung học phần, rèn luyện được tư duy phân tích dữ liệu và trong quá trình nghiên cứu và xử lý dữ liệu. Bài tiểu luận này là kết quả của sự nỗ lực và học hỏi không ngừng của nhóm dưới sự hướng dẫn của Thầy.
Xin chân thành cảm ơn Thầy!
Nhóm xin cam đoan rằng toàn bộ nội dung trong bài tiểu luận này là kết quả nghiên cứu, phân tích và trình bày của riêng nhóm, không sao chép hay vi phạm bản quyền. Các số liệu, bảng biểu và kết quả phân tích được thu thập, xử lý trung thực và có trích dẫn rõ ràng. Nhóm hoàn toàn chịu trách nhiệm về tính chính xác và trung thực của nội dung bài làm.
1. library(readxl) # Nạp thư viện 'readxl' để đọc dữ liệu từ các tệp Excel (.xlsx, .xls)
2. library(skimr) # Nạp thư viện 'skimr' để tạo bản tóm tắt thống kê nhanh chóng, đẹp mắt (giống như 'summary' nhưng chi tiết hơn)
3. library(tidyverse) # Nạp gói thư viện 'tidyverse' tổng hợp (bao gồm dplyr, ggplot2, tidyr, v.v.), mặc dù nhiều gói đã được tải riêng lẻ trước đó
4. library(ggplot2) # Nạp thư viện 'ggplot2' để tạo các đồ thị và biểu đồ trực quan hóa dữ liệu
5. library(dplyr) # Nạp thư viện 'dplyr' (một phần của tidyverse) để thao tác và xử lý dữ liệu hiệu quả
6. library(tidyr) # Nạp thư viện 'tidyr' (một phần của tidyverse) để làm sạch và định hình lại dữ liệu
7. library(DT) # Nạp thư viện 'DT' để tạo các bảng dữ liệu tương tác, có thể tìm kiếm, sắp xếp
8. library(kableExtra) # Nạp thư viện 'kableExtra' để tùy chỉnh và làm đẹp các bảng HTML/LaTeX
9. library(lubridate) # Nạp thư viện 'lubridate' để thao tác và xử lý dữ liệu thời gian và ngày tháng
10. library(moments) # Nạp thư viện 'moments' để tính các đặc trưng phân phối như moment, skewness, kurtosis
Thị trường bất động sản Hoa Kỳ là một trong những thị trường lớn và có ảnh hưởng mạnh mẽ, phản ánh các xu hướng kinh tế và đầu tư toàn cầu. Việc phân tích dữ liệu giao dịch bất động sản giúp nhà đầu tư và cơ quan quản lý hiểu rõ hơn về giá cả, hành vi mua bán, và yếu tố chi phối cung cầu theo khu vực và thời gian.
Đồng thời, Ngân hàng TMCP Đầu tư và Phát triển Việt Nam (BIDV) là một trong bốn ngân hàng lớn nhất Việt Nam, đóng vai trò quan trọng trong cung cấp vốn cho nền kinh tế. Phân tích dữ liệu tài chính của BIDV sẽ giúp đánh giá sức khỏe tài chính và hiệu quả hoạt động của ngân hàng trong bối cảnh kinh tế biến động.
Phân tích thị trường bất động sản Hoa Kỳ và các yếu tố ảnh hưởng đến giá bán, diện tích đất và mức độ hấp dẫn của từng khu vực.
Đánh giá hiệu quả tài chính của BIDV giai đoạn 2010–2024, thông qua các chỉ số như NIM, NPM, tỷ lệ tiền mặt trên tổng tài sản, lợi nhuận sau thuế và thu nhập hoạt động.
Ứng dụng R trong việc phân tích, trực quan hóa dữ liệu và đưa ra các nhận định về hiệu quả hoạt động của BIDV.
Đối tượng nghiên cứu: Giao dịch bất động sản tại Hoa Kỳ và các chỉ tiêu tài chính của BIDV.
Phạm vi dữ liệu: Dữ liệu từ bộ “USA Real Estate Dataset” (2015–2024) và bộ dữ liệu tài chính của BIDV (2010–2024).
Cung cấp cái nhìn tổng quan về thị trường bất động sản Hoa Kỳ và tình hình tài chính của BIDV.
Hỗ trợ ra quyết định cho nhà đầu tư và cơ quan quản lý trong việc phát triển chiến lược đầu tư và quản lý tài chính.
Minh họa khả năng ứng dụng các công cụ phân tích dữ liệu hiện đại để xử lý và trực quan hóa dữ liệu tài chính và bất động sản.
Bộ dữ liệu “USA Real Estate Dataset” được thu thập tại trang web Kaggle . Đây là một bộ dữ liệu công khai được xây dựng nhằm phục vụ mục đích học tập và thực hành phân tích dữ liệu trong lĩnh vực bất động sản. Bộ dữ liệu mô tả thông tin chi tiết của hơn 2,2 triệu bất động sản trên khắp các bang, thành phố và mã vùng của Hoa Kỳ. Mỗi dòng dữ liệu tương ứng với một bất động sản cụ thể, bao gồm các thông tin như giá bán, diện tích đất, diện tích nhà, số phòng ngủ, số phòng tắm, vị trí địa lý, mã vùng bưu điện, trạng thái giao dịch và ngày bán gần nhất. Dữ liệu được tổ chức dưới dạng dữ liệu định lượng và định tính, phản ánh đặc điểm và xu hướng chung của thị trường nhà ở Hoa Kỳ.
Ta tiến hành đọc tệp CSV và gán dữ liệu vào một đối tượng có tên là tieuluan để phục vụ cho quá trình phân tích.
1. tieuluan <- read.csv("D:/TMT_R/realtor-data.zip.csv")
2. tieuluan$prev_sold_date <- as.Date(tieuluan$prev_sold_date, format = "%Y-%m-%d")
Giải thích kỹ thuật
Dòng 1 dùng để nạp dữ liệu đầu vào cho bài
Dòng 2 dùng để chuyển dữ liệu trong cột prev_sold_date của bảng tieuluan sang kiểu ngày (Date) theo định dạng năm-tháng-ngày (%Y-%m-%d)
1. head(tieuluan)
Giải thích kỹ thuật
Dòng 1 dùng để xem 6 hàng đầu tiên của dữ liệu
1. tail(tieuluan)
Giải thích kỹ thuật
Dòng 1 dùng để xem 6 hàng cuối của dữ liệu
Ta sử dụng sử dụng một số lệnh bên dưới để xem thông tin chung của tieuluan.
1. dim(tieuluan)
## [1] 2226382 12
Giải thích kỹ thuật
Dòng 1 dùng để kiểm tra kích thước dữ liệu
Nhận xét: Sử dụng lệnh dim() kết quả trả về cho thấy bộ dữ liệu tieuluan có 2.226.382 hàng (quan sát) và 12 cột (biến), phản ánh quy mô và số lượng biến của tập dữ liệu.
1. names(tieuluan)
## [1] "brokered_by" "status" "price" "bed"
## [5] "bath" "acre_lot" "street" "city"
## [9] "state" "zip_code" "house_size" "prev_sold_date"
Giải thích kỹ thuật
Dòng 1 dùng để xem tên các biến trong bộ dữ liệu.
Nhận xét: Sử dụng lệnh names() kết quả trả về tên các biến trong bộ dữ liệu. Trong bộ dữ liệu tieuluan,có 12 biến bao gồm: “brokered_by”, “status”, “price”, “bed”, “bath”, “acre_lot”, “street”, “city”, “state”, “zip_code”, “house_size”, “prev_sold_date”.
Nhằm đảm bảo tính chính xác và phù hợp với mục tiêu nghiên cứu, tác giả đã chọn lọc 6 biến chính: status, price, bath, city, acre_lot và prev_sold_date. Thông tin chi tiết về các biến này được thể hiện trong bảng dưới đây.
1. tieuluan <- tieuluan[, c("status", "price", "bath", "city", "acre_lot", "prev_sold_date")]
Giải thích kỹ thuật
Dòng 1 dùng để giữ lại 6 biến phân tích.
| STT | Tên biến | Mô tả |
|---|---|---|
| 1 | status | Trạng thái bất động sản (đang bán hoặc sẵn sàng xây dựng) |
| 2 | price | Giá của bất động sản (hiện tại hoặc gần nhất) |
| 3 | bath | Số lượng phòng tắm của bất động sản |
| 4 | acre_lot | Diện tích đất (tính bằng mẫu Anh - acre) |
| 5 | city | Tên thành phố nơi bất động sản tọa lạc |
| 6 | prev_sold_date | Ngày bán gần nhất trước đó (nếu có) |
Giải thích kỹ thuật
Dòng 1 Dùng để tạo một bảng dữ liệu mới tên des bằng hàm data.frame().
Dòng 2 Dùng để tạo cột STT gồm các số thứ tự từ 1 đến 6.
Dòng 3-4 Dùng để tạo cột Tên_biến, chứa danh sách tên các biến trong bộ dữ liệu bất động sản.
Dòng 5-11 Dùng để mô tả các biến
Dòng 12 Dùng để gọi bảng dữ liệu des và truyền qua các hàm tiếp theo bằng toán tử %>%.
Dòng 13 Dùng hàm kable() để chuyển bảng des thành bảng HTML, với align = “c” để căn giữa tất cả các cột.
Dòng 14 Dùng col.names để đặt tiêu đề cột là STT, Tên biến, Mô tả (được in đậm).
Dòng 15 Dùng caption để thêm tiêu đề cho bảng, căn giữa và in đậm dòng chữ “Bảng 1. Danh sách các biến tác giả chọn để phân tích”.
Dòng 16 Dùng hàm kable_styling() để chỉnh giao diện bảng HTML.
Dòng 17 Các tùy chọn striped, hover, condensed, responsive giúp bảng xen kẽ màu, đổi màu khi rê chuột, gọn hơn và tự co giãn; full_width = F để bảng không chiếm toàn bộ chiều ngang, position = “center” để căn giữa, font_size = 14 để chỉnh cỡ chữ.
Dòng 18 Dùng để định dạng hàng tiêu đề in đậm và có nền đỏ đậm.
Dòng 19 Dùng để thêm viền phải cho cả ba cột trong bảng.
1. str(tieuluan)
## 'data.frame': 2226382 obs. of 6 variables:
## $ status : chr "for_sale" "for_sale" "for_sale" "for_sale" ...
## $ price : num 105000 80000 67000 145000 65000 179000 50000 71600 100000 300000 ...
## $ bath : int 2 2 1 2 2 3 1 2 1 3 ...
## $ city : chr "Adjuntas" "Adjuntas" "Juana Diaz" "Ponce" ...
## $ acre_lot : num 0.12 0.08 0.15 0.1 0.05 0.46 0.2 0.08 0.09 7.46 ...
## $ prev_sold_date: Date, format: NA NA ...
Giải thích kỹ thuật
Dòng 1 dùng để xem cấu trúc tổng quát của dữ liệu
Nhận xét: Sử dụng lệnh str() kết quả trả về cấu trúc tổng quát của bộ dữ liệu, bao gồm số quan sát, số biến, tên biến và kiểu dữ liệu của từng biến. Trong bộ dữ liệu hiện tại có 982.413 quan sát và 6 biến với các kiểu dữ liệu như num (số thực), int (số nguyên) và chr (chuỗi ký tự). Các biến số như price, bath, acre_lot và là các biến định lượng, còn các biến status, city và prev_sold_date là chuỗi ký tự.
1. sapply(tieuluan, class)
## status price bath city acre_lot
## "character" "numeric" "integer" "character" "numeric"
## prev_sold_date
## "Date"
Giải thích kỹ thuật
Dòng 1 dùng để xem kiểu dữ liệu theo từng cột
Nhận xét: Sử dụng lệnh sapply() với class kết quả trả về kiểu dữ liệu của từng biến trong bộ dữ liệu. Trong tieuluan, các biến có kiểu factor như status; kiểu numeric như price, bath, acre_lot; kiểu character như city; và kiểu Date như prev_sold_date. Các thông tin này giúp xác định loại biến để phân tích và trực quan hóa dữ liệu phù hợp.
1. #Thống kê mô tả biến price
2. summary_price <- tieuluan$price
3. data.frame(
4. Min = min(summary_price, na.rm = TRUE),
5. Q1 = quantile(summary_price, 0.25, na.rm = TRUE),
6. Median = median(summary_price, na.rm = TRUE),
7. Mean = mean(summary_price, na.rm = TRUE),
8. Q3 = quantile(summary_price, 0.75, na.rm = TRUE),
9. Max = max(summary_price, na.rm = TRUE),
10. SD = sd(summary_price, na.rm = TRUE),
11. Variance = var(summary_price, na.rm = TRUE),
12. Skewness = skewness(summary_price, na.rm = TRUE),
13. Kurtosis = kurtosis(summary_price, na.rm = TRUE))
Giải thích kỹ thuật
Dòng 1: Gán cột price từ bảng tieuluan vào biến summary_price để dễ thao tác.
Dòng 2: Bắt đầu tạo một bảng dữ liệu mới (data frame) chứa các chỉ số thống kê của summary_price.
Dòng 3-10: Tính các giá trị thống kê cơ bản gồm: giá trị nhỏ nhất (Min), tứ phân vị thứ nhất (Q1), trung vị (Median), trung bình (Mean), tứ phân vị thứ ba (Q3), giá trị lớn nhất (Max), độ lệch chuẩn (SD) và phương sai (Variance), tất cả đều bỏ qua giá trị thiếu (na.rm = TRUE).
Dòng 11: Tính độ lệch (Skewness) – đo độ nghiêng của phân phối: > 0 nghiêng phải, < 0 nghiêng trái.
Dòng 12: Tính độ nhọn (Kurtosis) – đo độ “nhọn” của phân phối: > 3 nhọn hơn chuẩn, < 3 dẹt hơn chuẩn.
Nhận xét: Biến price có giá trị dao động từ 0 đến 2.147.483.600, cho thấy sự chênh lệch rất lớn giữa các căn nhà, với sự xuất hiện của nhiều giá trị cực đoan. Giá trung vị (325.000) thấp hơn trung bình (524.195,5), cho thấy phân bố lệch phải mạnh. Độ lệch chuẩn (2.138.893) và phương sai (4,57E+12) cực kỳ cao, phản ánh mức độ phân tán lớn trong dữ liệu. Skewness = 546,30 và kurtosis = 492.425,1 cho thấy dữ liệu có đuôi phải rất dài và chứa nhiều giá trị ngoại lai, cần được xem xét hoặc loại bỏ khi thực hiện các phân tích thống kê tiếp theo để tránh sai lệch kết quả.
1. #Thống kê mô tả biến bath
2. summary_bath <- tieuluan$bath
3. data.frame(
4. Min = min(summary_bath, na.rm = TRUE),
5. Q1 = quantile(summary_bath, 0.25, na.rm = TRUE),
6. Median = median(summary_bath, na.rm = TRUE),
7. Mean = mean(summary_bath, na.rm = TRUE),
8. Q3 = quantile(summary_bath, 0.75, na.rm = TRUE),
9. Max = max(summary_bath, na.rm = TRUE),
10. SD = sd(summary_bath, na.rm = TRUE),
11. Variance = var(summary_bath, na.rm = TRUE),
12. Skewness = skewness(summary_bath, na.rm = TRUE),
13. Kurtosis = kurtosis(summary_bath, na.rm = TRUE)
14. )
Giải thích kỹ thuật: tương tự như thống kê mô tả của biến price
Nhận xét: Biến bath dao động từ 1 đến 830, với trung vị (Median = 2) thấp hơn trung bình (Mean = 2,50), cho thấy phần lớn các căn nhà có số phòng tắm thấp, nhưng tồn tại một số giá trị cực lớn (outliers). Độ lệch chuẩn (SD = 1,65) và phương sai (2,73) khá cao so với quy mô dữ liệu thông thường, phản ánh sự phân tán mạnh do ảnh hưởng của các giá trị bất thường. Skewness = 152,41 và kurtosis = 65.876,96 cho thấy dữ liệu có phân bố lệch phải rất mạnh và đuôi dài, cần kiểm tra và xử lý ngoại lai trước khi thực hiện các phân tích sâu hơn để đảm bảo độ tin cậy của kết quả.
1. #Thống kê mô tả biến acre_lot
2. summary_acre <- tieuluan$acre_lot
3. data.frame(
4. Min = min(summary_acre, na.rm = TRUE),
5. Q1 = quantile(summary_acre, 0.25, na.rm = TRUE),
6. Median = median(summary_acre, na.rm = TRUE),
7. Mean = mean(summary_acre, na.rm = TRUE),
8. Q3 = quantile(summary_acre, 0.75, na.rm = TRUE),
9. Max = max(summary_acre, na.rm = TRUE),
10. SD = sd(summary_acre, na.rm = TRUE),
11. Variance = var(summary_acre, na.rm = TRUE),
12. Skewness = skewness(summary_acre, na.rm = TRUE),
13. Kurtosis = kurtosis(summary_acre, na.rm = TRUE)
14. )
Giải thích kỹ thuật: tương tự như thống kê mô tả của biến price
Nhận xét: Biến acre_lot dao động từ 0 đến 100.000, với trung vị (Median = 0,26) thấp hơn trung bình (Mean = 15,22), cho thấy phần lớn các bất động sản có diện tích nhỏ nhưng tồn tại một số giá trị cực lớn (outliers). Độ lệch chuẩn (SD = 762,82) và phương sai (581.900,2) rất cao, phản ánh mức độ biến động mạnh trong dữ liệu. Skewness = 106,28 và kurtosis = 12.545,29 cho thấy dữ liệu có phân bố lệch phải rất mạnh và đuôi dài, nghĩa là có nhiều bất động sản có diện tích vượt trội so với đa số còn lại, cần được kiểm tra và xử lý ngoại lai khi phân tích chi tiết hơn.
1. status_tab <- table(tieuluan$status)
2. status_freq <- as.data.frame(status_tab)
3. names(status_freq) <- c("Trạng thái", "Tần số")
4. status_freq[["Tần suất (%)"]] <- round(100 * status_freq[["Tần số"]] / sum(status_freq[["Tần số"]]), 2)
5. status_freq
Giải thích kỹ thuật
Dòng 1: Dùng để đếm số lượng xuất hiện của từng loại trạng thái trong cột status, lưu kết quả vào biến status_tab.
Dòng 2: Dùng để chuyển bảng tần số status_tab sang dạng data frame, giúp dễ xử lý và hiển thị.
Dòng 3: Dùng để đặt lại tên hai cột của bảng thành “Trạng thái” và “Tần số”
Dòng 4: Thêm một cột mới “Tần suất (%)” bằng cách tính tỷ lệ phần trăm của từng trạng thái: lấy tần số chia tổng tần số rồi nhân 100, sau đó làm tròn 2 chữ số thập phân bằng round().
Dòng 5: Dùng để hiển thị bảng kết quả status_freq
Nhận xét: Biến status gồm ba nhóm chính là for_sale (62,40%), ready_to_build (1,13%) và sold (36,47%). Kết quả cho thấy phần lớn các bất động sản trong bộ dữ liệu đang ở trạng thái rao bán, trong khi số lượng đã bán chiếm tỷ lệ thấp hơn và ready_to_build chỉ chiếm một phần rất nhỏ. Điều này phản ánh nguồn cung trên thị trường đang lớn hơn nhu cầu giao dịch thực tế, thể hiện thị trường có mức độ thanh khoản chưa cao trong giai đoạn khảo sát.
1. city_freq <- tieuluan %>%
2. count(city) %>%
3. mutate(`Tần suất (%)` = round(100 * n / sum(n), 2)) %>%
4. arrange(desc(n))
5. topn <- 10
6. top_city <- city_freq[1:topn, ]
7. other_city <- city_freq[(topn + 1):nrow(city_freq), ]
8. other_summary <- data.frame(
9. city = "Khác",
10. n = sum(other_city$n),
11. `Tần suất (%)` = round(100 * sum(other_city$n) / sum(city_freq$n), 2),
12. stringsAsFactors = FALSE )
13. names(other_summary) <- names(top_city)
14. city_desc <- rbind(top_city, other_summary)
15. names(city_desc) <- c("Thành phố", "Tần số", "Tần suất (%)")
16. city_desc
Giải thích kỹ thuật
Dòng 1: Gọi bảng dữ liệu tieuluan và bắt đầu chuỗi thao tác với toán tử %>%.
Dòng 2: Dùng count(city) để đếm số lượng từng thành phố trong cột city.
Dòng 3: Dùng mutate() để thêm cột “Tần suất (%)”, tính bằng công thức 100 * n / sum(n) và làm tròn 2 chữ số.
Dòng 4: Dùng arrange(desc(n)) để sắp xếp bảng giảm dần theo tần số.
Dòng 5: Gán topn <- 10 để xác định số lượng thành phố muốn lấy ở top đầu.
Dòng 6: Lấy top 10 thành phố phổ biến nhất và lưu vào top_city.
Dòng 7: Lấy các thành phố còn lại ngoài top 10 và lưu vào other_city.
Dòng 8–13: Tạo bảng other_summary gộp các thành phố còn lại thành nhóm “Khác”, gồm: tên nhóm “Khác”, tổng số lượng, tổng tần suất (%) và giữ chuỗi “Khác” ở dạng ký tự (không factor).
Dòng 14: Dùng để đồng nhất tên cột giữa hai bảng trước khi ghép.
Dòng 15: Dùng để ghép bảng top 10 và nhóm “Khác” thành bảng cuối city_desc.
Dòng 16: Đổi tên các cột trong bảng city_desc sang tiếng Việt có dấu: “Thành phố”, “Tần số”, “Tần suất (%)”.
Dòng 18: Hiển thị bảng city_desc – kết quả thống kê
Nhận xét: Biến city cho thấy phần lớn bất động sản thuộc nhóm “Khác” (94,54%), phản ánh phạm vi phân bố rất rộng, bao gồm nhiều khu vực nhỏ lẻ khác nhau. Trong nhóm các thành phố lớn, Houston (1,07%; 23.862 căn), Chicago (0,82%; 18.238 căn) và New York City (0,57%; 12.634 căn) là ba khu vực có số lượng bất động sản cao nhất. Các thành phố còn lại gồm Jacksonville (0,53%; 11.743 căn), Philadelphia (0,47%; 10.449 căn), Miami (0,44%; 9.737 căn), Los Angeles (0,40%; 8.984 căn), Tucson (0,40%; 8.943 căn), Dallas (0,38%; 8.569 căn) và Richmond (0,38%; 8.360 căn) có tỷ lệ thấp hơn. Điều này cho thấy dữ liệu có tính đa vùng rõ rệt, phản ánh thị trường bất động sản phân tán trên phạm vi toàn quốc, không tập trung vào một vài khu vực cụ thể.
1. # Kiểm tra xem dữ liệu có giá trị NA nào không
2. any(is.na(tieuluan))
## [1] TRUE
Giải thích kỹ thuật: dùng để kiểm tra xem dữ liệu có giá trị NA nào không
Nhận xét: Sử dụng lệnh any(is.na()) kết quả trả về kiểm tra xem có bất kỳ giá trị thiếu nào trong toàn bộ bộ dữ liệu hay không. Trong tieuluan, kết quả là TRUE, cho thấy toàn bộ dữ liệu có giá trị NA.
1. sum(is.na(tieuluan))
## [1] 1573198
Giải thích kỹ thuật: dùng để đếm tổng số giá trị bị thiếu trong toàn bộ dataset
Nhận xét: Sử dụng lệnh sum(is.na()) kết quả trả về tổng số giá trị bị thiếu trong toàn bộ bộ dữ liệu. Trong tieuluan, kết quả là 1.573.198, nghĩa là có giá trị 1.573.198 NA trong dataset.
1. colSums(is.na(tieuluan))
## status price bath city acre_lot
## 0 1541 511771 0 325589
## prev_sold_date
## 734297
Giải thích kỹ thuật: dùng để đếm số lượng giá trị NA trong từng cột
Nhận xét: Sử dụng lệnh colSums(is.na()) trả về số lượng giá trị NA trong từng cột của bộ dữ liệu. Trong tieuluan, các biến có giá trị thiếu đáng chú ý là bath (511.771 NA), acre_lot (325.589 NA) và prev_sold_date (734.297 NA). Ngoài ra, biến price (1.541 NA) cũng có một lượng nhỏ giá trị bị thiếu, trong khi các biến phân loại như status và city không có giá trị NA. Kết quả này giúp xác định rõ các cột cần được xử lý dữ liệu thiếu trước khi tiến hành các bước phân tích thống kê và mô hình hóa tiếp theo.
1. names(tieuluan)[colSums(is.na(tieuluan)) > 0]
## [1] "price" "bath" "acre_lot" "prev_sold_date"
Giải thích kỹ thuật: dùng để liệt kê tên các cột có giá trị bị thiếu
Nhận xét: Sử dụng lệnh names(tieuluan)[colSums(is.na(tieuluan)) > 0] trả về tên các cột có giá trị bị thiếu trong bộ dữ liệu. Kết quả cho thấy các cột bị thiếu dữ liệu là: price, bath, acre_lot và prev_sold_date. Thông tin này giúp xác định những biến cần được xử lý giá trị thiếu (NA) trước khi tiến hành phân tích, thống kê mô tả hoặc trực quan hóa dữ liệu, nhằm đảm bảo tính chính xác và toàn vẹn của kết quả.
1. tieuluan <- na.omit(tieuluan)
2. sum(is.na(tieuluan))
## [1] 0
Giải thích kỹ thuật
Dòng 1: dùng để loại bỏ tất cả giá trị NA trong dữ liệu tieuluan
Dòng 2 : dùng để kiểm tra tổng số giá trị NA còn lại (sau khi loại bỏ)
Nhận xét: Sử dụng lệnh na.omit() loại bỏ tất cả các giá trị NA trong bộ dữ liệu tieuluan. Sau khi thực hiện, lệnh sum(is.na(tieuluan)) trả về 0, cho thấy không còn giá trị thiếu trong dataset. Điều này đảm bảo dữ liệu đã sẵn sàng cho các bước phân tích và trực quan hóa tiếp theo.
1. head(duplicated(tieuluan))
## [1] FALSE FALSE FALSE FALSE FALSE FALSE
Giải thích kỹ thuật:dùng để xem 6 giá trị đầu tiên của kết quả duplicated()
Nhận xét: Sử dụng lệnh duplicated() kết quả trả về kiểm tra các quan sát trùng lặp trong bộ dữ liệu. Trong tieuluan, 6 giá trị đầu tiên đều là FALSE, nghĩa là các quan sát này không bị trùng lặp.
1. sum(duplicated(tieuluan))
## [1] 2546
Giải thích kỹ thuật: dùng để đếm tổng số dòng bị trùng
Nhận xét: Sử dụng lệnh sum(duplicated()) cho kết quả 2546, nghĩa là trong tieuluan có 2.546 quan sát bị trùng lặp. Điều này cho thấy dữ liệu có sự lặp lại thông tin giữa các dòng, cần được kiểm tra và loại bỏ hoặc gộp lại trước khi thực hiện các bước phân tích tiếp theo để đảm bảo tính duy nhất và độ tin cậy của dữ liệu.
1. tieuluan <- tieuluan[!duplicated(tieuluan),]
Giải thích kỹ thuật: dùng để xóa các dòng trùng lặp trong dữ liệu; hàm duplicated() xác định dòng trùng, dấu ! giữ lại dòng không trùng để tạo bảng dữ liệu duy nhất.
1. remove_extreme_outliers_multi <- function(df, vars) {
2. for (var in vars) {
3. q1 <- quantile(df[[var]], 0.25, na.rm = TRUE)
4. q3 <- quantile(df[[var]], 0.75, na.rm = TRUE)
5. iqr <- q3 - q1
6. lower <- q1 - 3 * iqr
7. upper <- q3 + 3 * iqr
8. df <- df %>% filter(.data[[var]] >= lower, .data[[var]] <= upper) }
9. return(df)}
10. vars_extreme <- c("price", "bath", "acre_lot")
11. tieuluan <- remove_extreme_outliers_multi(tieuluan, vars_extreme)
12. tieuluan <- tieuluan %>%
13. filter(price >= 10000,
14. bath >= 1,
15. acre_lot > 0)
Giải thích kỹ thuật
Dòng 1: Tạo hàm để loại bỏ các outlier cực đoan cho nhiều biến cùng lúc.
Dòng 2: Sử dụng vòng for để lặp qua từng biến trong danh sách vars.
Dòng 3-4: Tính tứ phân vị thứ nhất và thứ ba (Q1,Q3) của biến, loại bỏ giá trị thiếu (na.rm = TRUE).
Dòng 5: Tính khoảng tứ phân vị (IQR = Q3 - Q1).
Dòng 6: Xác định ngưỡng dưới để loại bỏ outlier cực đoan (Q1 - 3×IQR). Hệ số 3 giúp chỉ loại các điểm rất bất thường.
Dòng 7: Xác định ngưỡng trên để loại bỏ outlier cực đoan (Q3 + 3×IQR).
Dòng 8: Giữ lại các hàng có giá trị nằm trong khoảng [lower, upper] bằng hàm filter().
Dòng 9: Trả về dữ liệu đã được loại bỏ outlier.
Dòng 10: Tạo danh sách các biến liên tục vars_extreme gồm “price”, “bath”, “acre_lot”.
Dòng 11: Gọi hàm để loại bỏ các giá trị cực đoan khỏi các biến đã chọn trong tieuluan.
Dòng 12–15: Tiếp tục lọc dữ liệu giữ lại các quan sát hợp lệ: price
>= 10000, bath >= 1, acre_lot > 0 để đảm bảo dữ liệu thực tế,
hợp lý.
## . Sửa lỗi dữ liệu
1. subset(tieuluan, price <= 0)
Giải thích kỹ thuật: dùng để tìm các giao dịch có giá âm hoặc bằng 0.
Nhận xét: Sử dụng lệnh subset(tieuluan, price <= 0) tìm các giao dịch có giá âm hoặc bằng 0. Kết quả trả về 0 quan sát, cho thấy trong bộ dữ liệu tieuluan không có giao dịch nào có giá ≤ 0, đảm bảo dữ liệu giá nhà hợp lệ để phân tích.
1. subset(tieuluan, acre_lot <= 0)
Giải thích kỹ thuật: dùng để tìm các giao dịch có acre_lot <= 0
Nhận xét: Sử dụng lệnh subset(tieuluan, acre_lot <= 0) tìm các giao dịch có diện tích đất bằng hoặc nhỏ hơn 0. Kết quả trả về 0 quan sát, cho thấy trong bộ dữ liệu tieuluan không có giao dịch nào có diện tích đất ≤ 0, đảm bảo dữ liệu về diện tích đất hợp lệ để phân tích.
1. subset(tieuluan, bath <= 0)
Giải thích kỹ thuật : dùng để tìm các giao dịch có bath <= 0.
Nhận xét: Sử dụng lệnh subset(tieuluan, bath <= 0) tìm các giao dịch có số phòng tắm bằng hoặc nhỏ hơn 0. Kết quả trả về 0 quan sát, cho thấy trong bộ dữ liệu tieuluan không có giao dịch nào có số phòng tắm ≤ 0, đảm bảo dữ liệu về số phòng tắm hợp lệ để phân tích.
1. unique(tieuluan$status)
## [1] "for_sale" "sold"
Giải thích kỹ thuật : dùng để kiểm tra giá trị status chứa tất cả các trạng thái khác nhau, không lặp lại.
Nhận xét: Sử dụng lệnh unique() trả về các giá trị duy nhất của một biến trong bộ dữ liệu. Trong ví dụ này, unique(tieuluan$status) cho thấy biến status chỉ có hai giá trị “for_sale” và “sold”, không có lỗi chính tả hay giá trị bất thường, đảm bảo dữ liệu hợp lệ để phân nhóm và phân tích.
1. # Chuyển biến status từ character sang factor
2. tieuluan$status <- as.factor(tieuluan$status)
Giải thích kỹ thuật: dùng để chuyển biến status từ character sang factor
1. sapply(tieuluan, class)
## status price bath city acre_lot
## "factor" "numeric" "integer" "character" "numeric"
## prev_sold_date
## "Date"
Giải thích kỹ thuật : dùng để kiểm tra lại kiểu dữ liệu của toàn bộ biến
Nhận xét: Sử dụng lệnh sapply(tieuluan, class) trả về kiểu dữ liệu của từng biến trong bộ dữ liệu. Kết quả cho thấy các biến price và acre_lot có kiểu numeric; biến bath có kiểu integer; biến status có kiểu factor; biến city có kiểu character và biến prev_sold_date có kiểu Date. Thông tin này giúp xác định rõ loại dữ liệu của từng biến, từ đó lựa chọn phương pháp phân tích và trực quan hóa phù hợp trong các bước tiếp theo.
1. str(tieuluan)
## 'data.frame': 980077 obs. of 6 variables:
## $ status : Factor w/ 2 levels "for_sale","sold": 1 1 1 1 1 1 1 1 1 1 ...
## $ price : num 110000 950000 525000 289900 384900 ...
## $ bath : int 3 4 3 2 2 3 4 2 2 2 ...
## $ city : chr "Dorado" "Saint Thomas" "Agawam" "Agawam" ...
## $ acre_lot : num 0.09 0.99 0.45 0.36 0.46 0.56 0.77 0.16 0.49 0.5 ...
## $ prev_sold_date: Date, format: "2019-06-28" "2013-10-11" ...
## - attr(*, "na.action")= 'omit' Named int [1:1078777] 1 2 3 4 5 6 7 8 9 10 ...
## ..- attr(*, "names")= chr [1:1078777] "1" "2" "3" "4" ...
Giải thích kỹ thuật: Hàm str(tieuluan) hiển thị cấu trúc dữ liệu của tieuluan, gồm số dòng, cột, tên biến và kiểu dữ liệu, giúp xem nhanh tổng quan dữ liệu.
1. summary(tieuluan)
## status price bath city
## for_sale:426036 Min. : 10000 Min. :1.000 Length:980077
## sold :554041 1st Qu.: 233000 1st Qu.:2.000 Class :character
## Median : 360000 Median :2.000 Mode :character
## Mean : 435034 Mean :2.397
## 3rd Qu.: 550000 3rd Qu.:3.000
## Max. :1680000 Max. :6.000
## acre_lot prev_sold_date
## Min. :0.0100 Min. :1901-01-01
## 1st Qu.:0.1300 1st Qu.:2017-06-21
## Median :0.1900 Median :2021-12-07
## Mean :0.2576 Mean :2017-12-19
## 3rd Qu.:0.3000 3rd Qu.:2022-03-07
## Max. :1.1800 Max. :2026-04-08
Giải thích kỹ thuật: Hàm summary(tieuluan) hiển thị thống kê mô tả nhanh cho các biến: với số là Min, Q1, Median, Mean, Q3, Max; với chuỗi là tần suất từng nhóm. Giúp nhìn tổng quan dữ liệu
Tác giả thực hiện các lệnh lọc dữ liệu cơ bản theo điều kiện:
1. head(tieuluan[tieuluan$price >= quantile(tieuluan$price, 0.95, na.rm = TRUE), ], 5)
Giải thích kỹ thuật: dùng để lấy các nhà giá trong top 5% cao nhất và hiện 5 dòng đầu
1. head(tieuluan[tieuluan$acre_lot == max(tieuluan$acre_lot, na.rm = TRUE), ], )
Giải thích kỹ thuật: dùng để Lấy các nhà có diện tích đất lớn nhất (acre_lot) và hiện 6 dòng đầu
1. head(tieuluan[tieuluan$status == "sold", ], 7)
Giải thích kỹ thuật: dùng để lấy 7 dòng nhà đã sold
1. head(tieuluan[tieuluan$price >= 1670000 & tieuluan$price <= 1680000, ], 10)
Giải thích kỹ thuật: dùng để lấy các nhà giá từ 1670000 đến 1680000 và hiện 10 dòng đầu
1. head(tieuluan[tieuluan$bath >= 3 & tieuluan$acre_lot > 0.8, ], 10)
Giải thích kỹ thuật: dùng để lấy nhà có ít nhất 3 phòng tắm, diện tích đất > 0,8 mẫu Anh và hiện 10 dòng đầu
1. top_city <- tieuluan %>%
2. count(city, sort = TRUE) %>%
3. slice(1) %>%
4. pull(city)
5. head(tieuluan[tieuluan$city == top_city, ], 10)
Giải thích kỹ thuật
Dòng 1–2: Sử dụng count(city, sort = TRUE) để đếm số lượng nhà theo từng thành phố và sắp xếp giảm dần theo tần suất xuất hiện.
Dòng 3–4: Dùng slice(1) để lấy thành phố có số lượng nhà nhiều nhất, sau đó pull(city) để trích tên thành phố đó lưu vào biến top_city.
1. head(tieuluan[tieuluan$acre_lot <= quantile(tieuluan$acre_lot, 0.05, na.rm = TRUE), ], 7)
Giải thích kỹ thuật: dùng để lấy các nhà diện tích thuộc top 5% nhỏ nhất và hiện 7 dòng đầu
1. head(tieuluan[tieuluan$bath >= 4 & tieuluan$price > 1600000, ], 5)
Giải thích kỹ thuật: dùng để lấy các nhà có từ 4 phòng tắm trở lên và giá > 1600000 và hiện 5 dòng đầu
1. head(tieuluan[tieuluan$price == 1680000, ], 14)
Giải thích kỹ thuật: dùng để Lấy các nhà giá = 1680000 và hiện 14 dòng đầu
1. head(tieuluan[tieuluan$acre_lot == max(tieuluan$acre_lot, na.rm = TRUE), ], 5)
Giải thích kỹ thuật: dùng để lấy các bất động sản có diện tích đất lớn nhất và hiện 5 dòng đầu
Tác giả thực hiện một số lệnh sau đây để truy cập một giá trị cụ thể:
1. tieuluan[25555, 3]
## [1] 3
Giải thích kỹ thuật: dùng để lấy giá trị bath ở dòng thứ 25555, cột thứ 3
1. tieuluan$city[which.max(tieuluan$price)]
## [1] "Brooklyn"
Giải thích kỹ thuật: dùng để lấy giá trị city của dòng có price lớn nhất
1. tieuluan$city[1234]
## [1] "West Hartford"
Giải thích kỹ thuật: dùng để lấy giá trị city ở dòng thứ 12343
1. tieuluan$acre_lot[which.min(tieuluan$acre_lot)]
## [1] 0.01
Giải thích kỹ thuật: dùng để lấy giá trị acre_lot nhỏ nhất trong bộ dữ liệu
1. tieuluan[15000, 2]
## [1] 349900
Giải thích kỹ thuật: dùng để lấy giá trị price ở dòng thứ 15000, cột thứ 2
1. tieuluan$bath[10001]
## [1] 4
Giải thích kỹ thuật: dùng để lấy giá trị bath ở dòng thứ 10001
1. tieuluan$price[which.max(tieuluan$price)]
## [1] 1680000
Giải thích kỹ thuật: dùng để lấy giá trị price lớn nhất trong bộ dữ liệu
1. tieuluan$acre_lot[2025]
## [1] 0.31
Giải thích kỹ thuật: dùng để lấy giá trị acre_lot (diện tích đất) ở dòng thứ 2025
1. tieuluan[19000, "city"]
## [1] "Oakhurst"
Giải thích kỹ thuật: dùng để lấy giá trị city ở dòng 19000 truy cập theo tên cột
1. tieuluan$bath[which.max(tieuluan$bath)]
## [1] 6
Giải thích kỹ thuật: dùng để lấy giá trị bath lớn nhất trong bộ dữ liệu
Tác giả thực hiện các lệnh thêm và sửa dữ liệu dưới đây:
1. tieuluan$status[1005] <- "sold"
Giải thích kỹ thuật: dùng để chỉnh lại trạng thái ở dòng 1005 thành sold
1. tieuluan$city[5555] <- "Adams"
Giải thích kỹ thuật: dùng để cập nhật lại tên thành phố cho dòng thứ 5555
1. tieuluan$TransactionNo <- 1:nrow(tieuluan)
Giải thích kỹ thuật: dùng để thêm cột đánh số thứ tự giao dịch
1. tieuluan <- tieuluan[-3, ]
Giải thích kỹ thuật: dùng để xóa dòng thứ 3 khỏi dữ liệu
1. tieuluan$bath[10] <- 3
Giải thích kỹ thuật: dùng để gán lại số phòng tắm dòng thứ 10 thành 3
1. tieuluan$price[2] <- tieuluan$price[2] * 1.05
Giải thích kỹ thuật: dùng để sửa giá dòng thứ 2 của biến price tăng 5%ệ
1. tieuluan$price[nrow(tieuluan)] <- tieuluan$price[nrow(tieuluan)] * 1.05
Giải thích kỹ thuật: dùng để cập nhật price dòng cuối cùng tăng 5%
1. tieuluan$price[4] <- tieuluan$price[4] * 0.93
Giải thích kỹ thuật: dùng để sửa giá dòng thứ 4 giảm 7%
1. tieuluan$status[6789] <- "for_sale"
Giải thích kỹ thuật: dùng để sửa trạng thái dòng thứ 6789 thành for_sale
1. tieuluan$bath[1999] <- 3
Giải thích kỹ thuật: dùng để sửa số phòng tắm của dòng thứ 999 thành 3
1. tieuluan$price[nrow(tieuluan)] <- tieuluan$price[nrow(tieuluan)] * 1.05
Giải thích kỹ thuật: dùng để tăng giá dòng cuối cùng lên 5%
1. tieuluan$city[2004] <- "Vernon"
Giải thích kỹ thuật: dùng để chỉnh lại thành phố của dòng thứ 2004 thành “Vernon”
1. tieuluan$acre_lot[118] <- tieuluan$acre_lot[118] * 1.5
Giải thích kỹ thuật: dùng để tăng diện tích đất (acre_lot) của dòng 118 lên gấp rưỡi
1. tieuluan$bath[order(tieuluan$price, decreasing = TRUE)[1:3]] <- 5
Giải thích kỹ thuật: dùng để đặt lại số phòng tắm cho top 3 dòng giá cao nhất thành 5
1. tieuluan$acre_lot_m2 <- tieuluan$acre_lot * 4046.86
Giải thích kỹ thuật: dùng để tạo 1 biến mới tên acre_lot_m2 từ acre_lot sang mét vuông
1. tieuluan <- tieuluan %>%
2. mutate(
3. prev_sold_date = as.Date(prev_sold_date),
4. prev_month_year = format(prev_sold_date, "%m-%Y"),
5. prev_year = year(prev_sold_date))
Giải thích kỹ thuật
Dòng 1: Gán lại dữ liệu cho tieuluan sau khi biến đổi.
Dòng 2: Dùng hàm mutate() để tạo hoặc chỉnh sửa cột trong bảng dữ liệu.
Dòng 3: Chuyển prev_sold_date về kiểu ngày chuẩn bằng as.Date().
Dòng 4: Tạo biến prev_month_year thể hiện tháng-năm theo định dạng “mm-YYYY”.
Dòng 5: Tạo biến prev_year lưu năm riêng biệt từ cột ngày gốc.
1. tieuluan <- tieuluan %>%
2. mutate(
3. mucgianha = case_when(
4. price < 100000 ~ "Rất rẻ",
5. price >= 100000 & price < 300000 ~ "Rẻ",
6. price >= 300000 & price < 600000 ~ "Trung bình",
7. price >= 600000 & price < 1000000 ~ "Mắc",
8. price >= 1000000 ~ "Rất mắc"))
Giải thích kỹ thuật
Dòng 1: Sử dụng toán tử pipe %>% để liên kết các bước xử lý dữ liệu.
Dòng 2: Dùng hàm mutate() để tạo thêm biến mới trong bảng tieuluan.
Dòng 3: Hàm case_when() dùng để gán nhãn phân loại cho biến dựa trên điều kiện.
Dòng 4–8: Phân khúc price thành 5 mức: “Rất rẻ” (<100.000 USD), “Rẻ” (100.000–<300.000), “Trung bình” (300.000–<600.000), “Mắc” (600.000–<1.000.000), “Rất mắc” (≥1.000.000).
1. # Phân tổ biến acre_lot thành diện tích đất
2. tieuluan <- tieuluan %>%
3. mutate(
4. dientichdat = cut(
5. acre_lot,
6. breaks = c(0, 0.1, 0.2, 0.5, 1, Inf),
7. labels = c("Rất nhỏ", "Nhỏ", "Vừa", "Lớn", "Rất lớn"),
8. include.lowest = TRUE,
9. right = FALSE))
10. table(tieuluan$dientichdat)
##
## Rất nhỏ Nhỏ Vừa Lớn Rất lớn
## 149461 366590 348537 86273 29215
Giải thích kỹ thuật
Dòng 1: Dùng toán tử pipe %>% để liên kết các bước xử lý dữ liệu.
Dòng 2: Hàm mutate() được dùng để tạo biến mới dientichdat từ biến acre_lot.
Dòng 3–8: Sử dụng hàm cut() để chia acre_lot thành 5 nhóm hợp lý theo khoảng: breaks = c(0, 0.1, 0.2, 0.5, 1, Inf) tương ứng với “Rất nhỏ”, “Nhỏ”, “Vừa”, “Lớn”, “Rất lớn”; include.lowest = TRUE giúp bao gồm giá trị nhỏ nhất, còn right = FALSE quy định khoảng [min, max).
Dòng 10: Dùng table(tieuluan$dientichdat) để đếm số lượng quan sát trong từng nhóm diện tích đất.
1. data1 <- subset(
2. tieuluan,
3. mucgianha %in% c("Rẻ", "Rất rẻ") &
4. status == "sold" )
5. head(data1)
Giải thích kỹ thuật
Dòng 1: Hàm subset() được dùng để lọc dữ liệu theo điều kiện cụ thể.
Dòng 2: Chỉ định bảng dữ liệu gốc là tieuluan.
Dòng 3–4: Điều kiện lọc: mucgianha nằm trong các nhóm “Rẻ” hoặc “Rất rẻ” và status bằng “sold”.
Dòng 5: Hàm head(data1) hiển thị 6 dòng đầu tiên của bảng dữ liệu data1.
1. data2 <- subset(
2. tieuluan,
3. bath >= 3 &
4. dientichdat %in% c("Lớn", "Rất lớn"))
5. head(data2)
Giải thích kỹ thuật
Dòng 1-2: tương tự phân tổ Nhà có giá thuộc nhóm “Rẻ” hoặc “Rất rẻ” và đã bán
Dòng 3–4: Điều kiện lọc: bath >= 3 (nhà có từ 3 phòng tắm trở lên) và dientichdat diện tích đất “Lớn” hoặc “Rất lớn”.
Nhận xét : Nhóm bất động sản này gồm các nhà có từ 3 phòng tắm trở lên và diện tích đất thuộc nhóm “Lớn” hoặc “Rất lớn”, với 54.324 quan sát, chiếm 5,54% trên tổng số quan sát. Nhóm này đại diện cho phân khúc nhà ở trung – cao cấp, có không gian sống rộng rãi, tiện nghi hiện đại, hướng đến khách hàng có thu nhập khá và cao, đặc biệt là các hộ gia đình mong muốn nâng cấp chất lượng cuộc sống hoặc đầu tư lâu dài. Nhóm này phản ánh xu hướng mở rộng nhu cầu nhà ở diện tích lớn và đầy đủ tiện ích, đồng thời thể hiện sự quan tâm gia tăng của nhà đầu tư vào phân khúc bất động sản giá trị cao với tiềm năng sinh lời ổn định.
1. data3 <- subset(
2. tieuluan,
3. mucgianha %in% c("Cao", "Rất cao") &
4. status == "sold")
5. head(data3)
Giải thích kỹ thuật
Dòng 1-2: tương tự phân tổ Nhà có giá thuộc nhóm “Rẻ” hoặc “Rất rẻ” và đã bán
Dòng 3–4: Điều kiện lọc: mucgianha giá nhà thuộc nhóm “Cao” hoặc “Rất cao” và status là đã bán.
Nhận xét: Nhóm bất động sản này gồm các nhà có giá thuộc mức “Mắc” hoặc “Rất mắc” và đã được bán (sold), nhưng không có quan sát nào trong bộ dữ liệu hiện tại. Điều này cho thấy phân khúc nhà cao cấp tuy tồn tại trên thị trường nhưng phần lớn vẫn đang trong trạng thái rao bán, chưa phát sinh nhiều giao dịch thực tế. Nguyên nhân có thể do giá trị tài sản lớn, tính thanh khoản thấp hoặc nhu cầu mua thực tế hạn chế so với các phân khúc giá thấp hơn. Kết quả này phản ánh xu hướng thị trường tập trung vào phân khúc trung bình – thấp.
1. data4 <- subset(
2. tieuluan,
3. prev_sold_date >= 2020 &
4. bath >= 2 &
5. status == "sold")
6. head(data4)
Giải thích kỹ thuật
Dòng 1-2: tương tự phân tổ Nhà có giá thuộc nhóm “Rẻ” hoặc “Rất rẻ” và đã bán.
Dòng 3–5: Điều kiện lọc: năm bán trước từ 2020 trở đi, bath >= 2 có ít nhất 2 phòng tắm và status là đã bán.
Nhận xét : Nhóm bất động sản này gồm các nhà đã bán từ năm 2020 trở đi và có từ 2 phòng tắm trở lên, với 473.096 quan sát, chiếm 48,27% tổng dữ liệu. Nhóm này phản ánh phân khúc phổ thông–trung cấp, giá chủ yếu “Rẻ” đến “Trung bình”, diện tích nhỏ–vừa, phù hợp gia đình trẻ và người mua an cư sau đại dịch. Một phần nhỏ thuộc nhóm cao cấp ven biển, thể hiện xu hướng đầu tư dài hạn của khách hàng khá giả.
1. data5 <- subset(
2. tieuluan,
3. mucgianha == "Rẻ" &
4. dientichdat %in% c("Lớn", "Rất lớn"))
5. head(data5)
Giải thích kỹ thuật
Dòng 1-2: tương tự phân tổ Nhà có giá thuộc nhóm “Rẻ” hoặc “Rất rẻ” và đã bán..
Dòng 3–4: Điều kiện lọc: mucgianha là “Rẻ” và dientichdat là “Lớn” hoặc “Rất lớn”.
Nhận xét: Nhóm này gồm các nhà có giá “Rẻ” nhưng diện tích đất “Lớn” hoặc “Rất lớn”, với 39.450 quan sát, chiếm 4,03% tổng dữ liệu. Phần lớn đang rao bán (for_sale), có 1–3 phòng tắm và diện tích trung bình khoảng (2.000–5.000 m²). Nhóm này phản ánh phân khúc nhà giá thấp nhưng ưu tiên không gian rộng, phù hợp người mua ngân sách hạn chế muốn sở hữu nhiều đất hoặc nhà đầu tư tìm cơ hội tích lũy bất động sản dài hạn.
1. data6 <- subset(
2. tieuluan,
3. prev_sold_date < 2016 &
4. mucgianha %in% c("Rẻ", "Rất rẻ"))
5. head(data6)
Giải thích kỹ thuật
Dòng 1–2: Tương tự phân tổ “Nhà có giá thuộc nhóm ‘Rẻ’ hoặc ‘Rất rẻ’ và đã bán” (lọc dữ liệu từ tieuluan).
Dòng 3–4: Điều kiện lọc: nhà được giao dịch trước năm 2016 và mucgianha giá thuộc nhóm “Rẻ” hoặc “Rất rẻ”
Nhận xét : Nhóm này gồm các căn giao dịch (trước 2016) và giá “Rẻ/Rất rẻ”, có 517 quan sát với 12 biến, chiếm 0,05% tổng dữ liệu. Phần lớn đang rao bán (for_sale), 1–2 phòng tắm, đất nhỏ–vừa (ước khoảng (200–1.500 m²)). Nhóm này phản ánh nhu cầu của người mua ngân sách hạn chế và nhà đầu tư cải tạo/cho thuê, tập trung vào bất động sản cũ cần nâng cấp với giá vào thấp.
1. data7 <- subset(
2. tieuluan,
3. city == "Akron" &
4. mucgianha == "Rẻ" &
5. status == "sold" )
6. head(data7)
Giải thích kỹ thuật
Dòng 1–2: Tương tự phân tổ “Nhà có giá thuộc nhóm ‘Rẻ’ hoặc ‘Rất rẻ’ và đã bán” .
Dòng 3–4: Điều kiện lọc: chỉ lấy các căn nhà ở thành phố Akro), mucgianha thuộc nhóm “Rẻ” và status là đã bán.
Nhận xét : Phân nhóm “giá Rẻ, đã bán” tại một địa bàn cụ thể có 681 quan sát, chiếm 0,07% tổng dữ liệu. Giao dịch tập trung giai đoạn 2021–2022; số phòng tắm phổ biến 1–3; diện tích đất chủ yếu mức Vừa–Lớn, vẫn hiện diện một số “Rất lớn”. Cấu hình này cho thấy nhu cầu mạnh của nhóm khách hàng nhạy giá, ưu tiên nhà ở tầm trung với quỹ đất đủ dùng, phù hợp mục tiêu an cư hoặc đầu tư ngắn hạn.
1. data8 <- subset(
2. tieuluan,
3. city == "Atlanta" &
4. dientichdat %in% c("Lớn", "Rất lớn") &
5. status == "sold")
6. head(data8)
Giải thích kỹ thuật
Dòng 1–2: Tương tự phân tổ “Nhà có giá thuộc nhóm ‘Rẻ’ hoặc ‘Rất rẻ’ và đã bán”
Dòng 3–4: Điều kiện lọc: các căn ở thành phố Atlanta, dientichdat diện tích đất thuộc nhóm “Lớn” hoặc “Rất lớn” và status là đã bán.
Nhận xét : Phân nhóm nhà đã bán tại Atlanta có diện tích đất “Lớn/Rất lớn” gồm 222 quan sát, chiếm 0,02% tổng dữ liệu. Giao dịch tập trung giai đoạn 2021–2022, giá trải từ “Rẻ” đến “Rất mắc”, chủ yếu Trung bình–Mắc, với 2–4 phòng tắm phổ biến. Phân khúc này phản ánh nhu cầu cao về nhà có quỹ đất rộng, phục vụ khách hàng thu nhập khá–cao hướng đến không gian sống thoáng và đầu tư dài hạn.
1. thongke1 <- tieuluan %>%
2. summarise(
3. Sogiaodich = n(),
4. Giatritb = mean(price, na.rm = TRUE),
5. max = max(price, na.rm = TRUE),
6. min = min(price, na.rm = TRUE),
7. Trungvi = median(price, na.rm = TRUE),
8. Dolechchuan = sd(price, na.rm = TRUE),
9. Q1 = quantile(price, 0.25, na.rm = TRUE),
10. Q3 = quantile(price, 0.75, na.rm = TRUE))
11. head(thongke1)
Giải thích kỹ thuật
Dòng 1–2: Sử dụng toán tử %>% để chuyển dữ liệu tieuluan vào hàm summarise() nhằm tính các chỉ số thống kê cho biến price.
Dòng 3–10: Tính các giá trị thống kê mô tả gồm số giao dịch,giá trung bình, giá cao nhất, giá thấp nhất, trung vị, độ lệch chuẩn và tính tứ phân vị thứ nhất Q1 và thứ ba Q3.
Dòng 11: head(thongke1) hiển thị kết quả thống kê mô tả vừa tính được.
Dựa vào bảng thông kê trên
Tổng giá trị giao dịch là 980.076 giao dịch
Giá trị trung bình của giá trị giao dịch là 435.034,3 USD.
Trung vị: 360.000 USD.
Giá trị tối thiểu và tối đa: 10.000 USD đến 1.680.000 USD → khoảng cách rất lớn, nhấn mạnh biến động giao dịch đa dạng.
Độ lệch chuẩn: 293.287,6 USD, cho thấy mức độ biến động cao giữa các giao dịch
Q1 và Q3: 233.000 USD và 550.000 USD, cho thấy phần lớn giao dịch tập trung ở mức giá trung bình – khá trong thị trường.
1. ### . Thống kê mô tả cho biến acre_lot_m2
2. thongke2 <- tieuluan %>% #Dùng %>% để chuyển bảng dữ liệu tieuluan vào hàm summarise()
3. summarise( #Hàm summarise() để tính toán các thống kê mô tả
4. Sogiaodich = n(), #Số lượng quan sát (tổng số căn nhà trong dữ liệu)
5. Dientichtb = mean(acre_lot_m2, na.rm = TRUE), #Giá trị trung bình của diện tích (bỏ qua NA)
6. Max = max(acre_lot_m2, na.rm = TRUE), #Giá trị diện tích lớn nhất
7. Min = min(acre_lot_m2, na.rm = TRUE), #Giá trị diện tích nhỏ nhất
8. Trungvi = median(acre_lot_m2, na.rm = TRUE), #Trung vị (median) – diện tích đại diện
9. Dolechchuan = sd(acre_lot_m2, na.rm = TRUE), #Độ lệch chuẩn – mức độ phân tán của diện tích
10. Q1 = quantile(acre_lot_m2, 0.25, na.rm = TRUE), #Tứ phân vị thứ nhất (25% dữ liệu nhỏ hơn giá trị này)
11. Q3 = quantile(acre_lot_m2, 0.75, na.rm = TRUE) #Tứ phân vị thứ ba (75% dữ liệu nhỏ hơn giá trị này)
12. )
13. head(thongke2) #Hiển thị kết quả thống kê ra màn hình
Giải thích kỹ thuật : tương tự như thông kê mô tả của biến price
Dựa trên bảng thống kê:
Tổng số giao dịch là 980.076 giao dịch.
Diện tích trung bình là 1.042,61m².
Trung vị: 768,9034 m².
Giá trị tối thiểu và tối đa: từ 40,4686 m² đến 7.775,295 m² → khoảng cách rất lớn, phản ánh sự đa dạng rõ rệt về quy mô đất.
Độ lệch chuẩn: 905,742 m², cho thấy mức biến động cao giữa các bất động sản.
Q1 và Q3: lần lượt là 526,0918 m² và 1.214,058 m², cho thấy phần lớn bất động sản tập trung ở nhóm diện tích trung bình – khá trong thị trường.
1. thongke3 <- tieuluan %>%
2. group_by(mucgianha, dientichdat) %>%
3. summarise(
4. Sogiaodich = n(),
5. Giatritb = mean(price, na.rm = TRUE),
6. Trungvi = median(price, na.rm = TRUE),
7. Max = max(price, na.rm = TRUE),
8. Min = min(price, na.rm = TRUE),
9. Dolechchuan = sd(price, na.rm = TRUE),
10. Q1 = quantile(price, 0.25, na.rm = TRUE),
11. Q3 = quantile(price, 0.75, na.rm = TRUE)) %>%
12. arrange(mucgianha, dientichdat)
13. head(thongke3)
Giải thích kỹ thuật
Dòng 1–2: Sử dụng %>% để đưa bảng dữ liệu tieuluan vào hàm group_by(), nhóm theo hai biến phân loại là mucgianha và dientichdat.
Dòng 3–11: Dùng summarise() để tính các thống kê mô tả trong từng nhóm, gồm: số giao dịch , giá trung bình , trung vị , giá cao nhất , giá thấp nhất, độ lệch chuẩn, và hai tứ phân vị.
Dòng 12: arrange() sắp xếp kết quả theo thứ tự mucgianha và dientichdat.
Dòng 13: head(thongke3) hiển thị 6 dòng đầu tiên của bảng thống kê kết quả.
Dựa vào bảng thống kê trên:
Số lượng giao dịch giữa các nhóm giá và diện tích không đồng đều, trong đó các nhóm “Rẻ – Nhỏ/Vừa” và “Trung bình – Nhỏ/Vừa” chiếm tỷ trọng cao nhất, phản ánh phân khúc nhà ở tầm trung và giá thấp là phổ biến nhất trên thị trường.
Giá trị trung bình tăng dần theo phân khúc giá, thể hiện sự phân tầng rõ rệt giữa các mức giá:
Rất rẻ: khoảng 68.949 – 72.805 USD
Rẻ: khoảng 209.332 – 215.681 USD
Trung bình: khoảng 426.656 – 435.705 USD
Mắc: khoảng 760.660 – 771.369 USD
Rất mắc: khoảng 1.286.162 – 1.302.464 USD → Cho thấy mức giá được phân tầng hợp lý, phản ánh cấu trúc thị trường rõ ràng từ phổ thông đến cao cấp.
Độ lệch chuẩn (SD) tăng mạnh ở các phân khúc cao cấp, cho thấy mức biến động giá lớn do khác biệt về vị trí và tiện ích:
Rất rẻ: khoảng 20.156 – 22.636 USD
Rẻ: khoảng 54.485 – 56.311 USD
Trung bình: khoảng 83.515 – 85.174 USD
Mắc: khoảng 111.693 – 115.360 USD
Rất mắc: khoảng 172.444 – 177.751 USD
Khoảng giá Q1–Q3 cho thấy phần lớn giao dịch tập trung trong các mức:
Rất rẻ: 53.000 – 89.900 USD
Rẻ: 164.900 – 260.000 USD
Trung bình: 351.000 – 499.900 USD
Mắc: 665.000 – 859.000 USD
Rất mắc: 1.149.888 – 1.450.000 USD → Phản ánh mức giá phổ biến của từng phân khúc và ranh giới rõ ràng giữa các tầng thị trường.
Giá tối thiểu – tối đa trải rộng từ 10.000 USD đến 1.680.000 USD, cho thấy biên độ chênh lệch rất lớn, phản ánh thị trường đa dạng, bao gồm cả phân khúc nhà ở đại chúng và bất động sản cao cấp.
1. thongke4 <- tieuluan %>%
2. group_by(status, dientichdat) %>%
3. summarise(
4. Sogiaodich = n(),
5. Giatritb = mean(price, na.rm = TRUE),
6. Trungvi = median(price, na.rm = TRUE),
7. Max = max(price, na.rm = TRUE),
8. Min = min(price, na.rm = TRUE),
9. Dolechchuan = sd(price, na.rm = TRUE),
10. Q1 = quantile(price, 0.25, na.rm = TRUE),
11. Q3 = quantile(price, 0.75, na.rm = TRUE)) %>%
12. arrange(status, dientichdat)
13. head(thongke4)
Giải thích kỹ thuật
Dòng 1–2:tương tự như thống kê theo mucgianha và dientichdat nhưng nhóm dữ liệu theo hai biến: status và dientichdat.
Dòng 3–11: tương tự như thống kê theo mucgianha và dientichdat
Dòng 12: arrange() sắp xếp kết quả theo thứ tự status và dientichdat.
Dựa vào bảng thống kê trên:
Số lượng giao dịch giữa hai trạng thái “for_sale” và “sold” có sự chênh lệch rõ rệt, trong đó các nhóm “Nhỏ” và “Vừa” chiếm tỷ trọng lớn nhất ở cả hai trạng thái. Điều này phản ánh phân khúc nhà có diện tích trung bình được quan tâm và giao dịch nhiều nhất trên thị trường.
Giá trị trung bình tăng dần theo quy mô diện tích, thể hiện mối quan hệ hợp lý giữa diện tích và giá trị bất động sản:
For_sale: từ 424.604 USD (Rất nhỏ) đến 482.998 USD (Rất lớn)
Sold: từ 419.450 USD (Vừa) đến 439.769 USD (Lớn) → Cho thấy giá niêm yết thường cao hơn giá bán thực tế, phù hợp với thực tế thị trường có sự thương lượng trước khi giao dịch.
Độ lệch chuẩn (SD) dao động trong khoảng 275.000 – 322.000 USD, phản ánh mức biến động giá cao, đặc biệt ở những bất động sản có diện tích lớn và rất lớn, nơi giá trị chịu ảnh hưởng mạnh bởi vị trí, tiện ích và chất lượng tài sản.
Khoảng giá Q1–Q3 tập trung chủ yếu trong khoảng:
For_sale: 210.000 – 629.000 USD
Sold: 219.900 – 569.900 USD → Điều này cho thấy phần lớn giao dịch tập trung trong phân khúc trung bình – khá, là mức phổ biến và có tính thanh khoản cao nhất.
Giá tối thiểu – tối đa trải rộng từ 10.000 – 1.680.000 USD, khẳng định thị trường bất động sản đa dạng cả về quy mô lẫn giá trị, bao gồm từ nhà ở phổ thông đến phân khúc cao cấp.
1. thongke5 <- tieuluan %>%
2. group_by(mucgianha, bath) %>%
3. summarise(
4. Sogiaodich = n(),
5. Giatritb = mean(price, na.rm = TRUE),
6. Trungvi = median(price, na.rm = TRUE),
7. Max = max(price, na.rm = TRUE),
8. Min = min(price, na.rm = TRUE),
9. Dolechchuan = sd(price, na.rm = TRUE),
10. Q1 = quantile(price, 0.25, na.rm = TRUE),
11. Q3 = quantile(price, 0.75, na.rm = TRUE)) %>%
12. arrange(mucgianha, bath)
13. head(thongke5)
Giải thích kỹ thuật
Dòng 1–2: tương tự như thống kê theo mucgianha và dientichdat nhưng nhóm theo hai biến mucgianha và bath.
Dòng 3–11: tương tự như thống kê theo mucgianha và dientichdat
Dòng 12: Sắp xếp kết quả theo thứ tự tăng dần của mucgianha và bath.
Dựa vào bảng thống kê trên:
Số lượng giao dịch giữa các nhóm giá và số phòng tắm (bath) có sự chênh lệch đáng kể, trong đó các nhóm “Rẻ – 2 phòng tắm” và “Trung bình – 2 hoặc 3 phòng tắm” chiếm tỷ trọng cao nhất, phản ánh phân khúc nhà tầm trung với 2–3 phòng tắm là lựa chọn phổ biến nhất của thị trường.
Giá trị trung bình tăng dần theo phân khúc giá, thể hiện quy luật hợp lý giữa giá trị và cấp độ nhà ở:
Rất rẻ: khoảng 58.570 – 74.954 USD
Rẻ: khoảng 183.218 – 241.996 USD
Trung bình: khoảng 413.664 – 493.703 USD
Mắc: khoảng 757.834 – 813.898 USD
Rất mắc: khoảng 1.252.930 – 1.344.547 USD → Cho thấy cấu trúc phân tầng giá rõ rệt, phản ánh sự đa dạng về thu nhập và nhu cầu của các nhóm người mua.
Độ lệch chuẩn (SD) tăng dần theo cấp độ giá, chứng tỏ phân khúc cao cấp có mức dao động giá lớn hơn do khác biệt về vị trí, thiết kế và tiện ích:
Rất rẻ: khoảng 19.153 – 31.456 USD
Rẻ: khoảng 46.652 – 57.820 USD
Trung bình: khoảng 77.652 – 85.337 USD
Mắc: khoảng 111.693 – 114.640 USD
Rất mắc: khoảng 172.434 – 181.988 USD
Khoảng giá Q1–Q3 thể hiện vùng tập trung chính của từng nhóm:
Rất rẻ: 41.526 – 91.225 USD
Rẻ: 139.000 – 280.000 USD
Trung bình: 349.000 – 557.695 USD
Mắc: 659.000 – 899.992 USD
Rất mắc: 1.099.980 – 1.499.000 USD → Cho thấy phần lớn giao dịch nằm trong khoảng trung – khá, phản ánh tính thanh khoản cao ở phân khúc tầm trung.
Giá tối thiểu – tối đa trải rộng từ 10.000 USD đến 1.680.000 USD, khẳng định thị trường có biên độ rất lớn, bao gồm từ nhà giá rẻ phổ thông đến bất động sản cao cấp, phù hợp với đặc trưng của thị trường bất động sản đa tầng và phân khúc rõ rệt.
1. thongke6 <- tieuluan %>%
2. group_by(status, mucgianha, dientichdat) %>%
3. summarise(
4. Sogiaodich = n(),
5. Giatritb = mean(price, na.rm = TRUE),
6. Trungvi = median(price, na.rm = TRUE),
7. Max = max(price, na.rm = TRUE),
8. Min = min(price, na.rm = TRUE),
9. Dolechchuan = sd(price, na.rm = TRUE),
10. Q1 = quantile(price, 0.25, na.rm = TRUE),
11. Q3 = quantile(price, 0.75, na.rm = TRUE)) %>%
12. arrange(status, mucgianha, dientichdat)
13. head(thongke6)
Giải thích kỹ thuật
Dòng 1–2: tương tự như thống kê theo mucgianha và dientichdat nhưng nhóm theo ba biến phân loại: status, mucgianha, và dientichdat.
Dòng 3–11: tương tự như thống kê theo mucgianha và dientichdat.
Dòng 12: Sắp xếp kết quả theo thứ tự tăng dần của status, mucgianha, và dientichdat để dễ dàng đọc và phân tích.
Dựa vào bảng thống kê trên:
Số lượng giao dịch giữa hai trạng thái “for_sale” và “sold” có sự khác biệt đáng kể, trong đó các nhóm “Rẻ – Nhỏ/Vừa” và “Trung bình – Nhỏ/Vừa” chiếm tỷ trọng lớn nhất. Điều này cho thấy phân khúc tầm trung và giá thấp là khu vực hoạt động sôi động nhất của thị trường, phản ánh nhu cầu mạnh từ nhóm khách hàng trung lưu.
Giá trị trung bình (Giatritb) tăng đều theo cấp độ giá và gần như ổn định giữa hai trạng thái:
Rất rẻ: khoảng 68.910 – 74.685 USD
Rẻ: khoảng 208.318 – 216.791 USD
-Trung bình: khoảng 425.387 – 437.371 USD
Mắc: khoảng 758.907 – 772.862 USD
Rất mắc: khoảng 1.282.518 – 1.309.947 USD → Điều này cho thấy sự phân tầng giá hợp lý và rõ ràng, đồng thời giá bán thực tế (sold) nhìn chung thấp hơn nhẹ so với giá niêm yết (for_sale), phù hợp với quy luật thương lượng trên thị trường.
Độ lệch chuẩn (SD) dao động từ 18.738 – 22.801 USD ở nhóm Rất rẻ, lên tới 171.170 – 178.022 USD ở nhóm Rất mắc, thể hiện mức biến động giá càng lớn ở các phân khúc cao cấp, do ảnh hưởng của vị trí, diện tích và tiện ích.
Khoảng giá Q1–Q3 phản ánh vùng tập trung của giao dịch theo nhóm:
Rất rẻ: 52.000 – 89.900 USD
Rẻ: 160.000 – 264.900 USD
Trung bình: 350.000 – 499.989 USD
Mắc: 665.000 – 859.900 USD
Rất mắc: 1.144.500 – 1.450.000 USD → Các khoảng giá này duy trì ổn định giữa hai trạng thái, cho thấy thị trường có tính thanh khoản cao ở vùng trung – khá.
Giá tối thiểu – tối đa trải rộng từ 10.000 – 1.680.000 USD, khẳng định biên độ giá rất lớn của thị trường, bao gồm từ nhà giá rẻ đại chúng đến bất động sản cao cấp, phản ánh cấu trúc thị trường đa tầng và đa nhu cầu.
1. plot(tieuluan$price, type="l", col="darkred",
2. main="Xu hướng giá", xlab="Thứ tự quan sát", ylab="Giá (USD)")
Giải thích kỹ thuật
Dòng 1: Sử dụng hàm plot() để vẽ biểu đồ đường (line plot), đặt màu sắc của đường là đỏ đậm, thiết lập tiêu đề chính, và nhãn cho trục X và trục Y.
Dòng 2: Đặt nhãn cho trục X là “Thứ tự quan sát” và trục Y là “Giá (USD)”.
1. df_year_price <- tieuluan %>%
2. group_by(prev_year) %>%
3. summarise(price_tb = mean(price, na.rm = TRUE)) %>%
4. arrange(prev_year)
5. plot(df_year_price$prev_year, df_year_price$price_tb, type="l", col="darkred", main="Biến động giá bán bất động sản theo năm",
6. xlab="Năm", ylab="Giá bán trung bình (USD)")
7. points(df_year_price$prev_year, df_year_price$price_tb,
8. pch=16, col="darkred")
Giải thích kỹ thuật
Dòng 2: group_by(prev_year) nhóm dữ liệu theo năm (prev_year).
Dòng 3: summarise(price_tb = mean(price, na.rm = TRUE)) tính giá trung bình (price_tb) mỗi năm, bỏ qua các giá trị NA.
Dòng 4: arrange(prev_year) sắp xếp kết quả theo năm tăng dần.
Dòng 5-7: Xác định loại biểu đồ tương tự biểu đồ đường (Line Plot): Giá theo thứ tự quan sát
Dòng 8: Sử dụng hàm points() để thêm các điểm tròn vào biểu đồ, với trục X là năm và trục Y là giá trung bình.
Dòng 9: pch = 16 thiết lập điểm tròn đặc.
Nhận xét : Biểu đồ cho thấy giá bán bất động sản biến động mạnh theo thời gian. Giai đoạn 1900–1940 giá giảm nhẹ, sau đó tăng vọt rõ rệt trong giai đoạn 1950–1970 và đạt mức cao nhất. Từ sau năm 1970, giá tăng dần và ổn định hơn trong khoảng 1980–2010. Đến sau năm 2020, giá có xu hướng giảm mạnh, cho thấy thị trường có dấu hiệu chững lại hoặc suy yếu do Covid.
1. status_count <- table(tieuluan$status)
2. bp <- barplot(
3. status_count,main = "Số lượng nhà theo trạng thái",
4. xlab = "Trạng thái",ylab = "Số lượng",
5. col = c("darkolivegreen", "orange"),
6. ylim = c(0, max(status_count) * 1.3))
7. text(x = bp,y = status_count + max(status_count)*0.05,
8. labels = status_count,
9. pos = 3,cex = 0.9,font = 2,col = "black")
Giải thích kỹ thuật
Dòng 1: status_count <- table(tieuluan$status) tạo bảng tần suất đếm số lượng các giá trị trong biến status của dữ liệu tieuluan.
Dòng 2: bp <- barplot(status_count, main = “Số lượng nhà theo trạng thái”, vẽ biểu đồ cột và lưu vị trí các cột vào biến bp. Thiết lập tiêu đề biểu đồ là “Số lượng nhà theo trạng thái”.
Dòng 3-4: thiết lập nhãn cho trục X là “Trạng thái”, thiết lập nhãn cho trục Y là “Số lượng
Dòng 5: thiết lập màu sắc cho các cột
Dòng 6: tăng thêm 30% giá trị lớn nhất trong bảng status_count để có khoảng trống phía trên các cột.
Dòng 7: thêm các nhãn (giá trị) lên trên các cột, với vị trí y cách giá trị của cột một khoảng nhỏ (5% của giá trị lớn nhất).
Dòng 8: in giá trị trong status_count lên trên mỗi cột.
Dòng 9: pos = 3, cex = 0.9, font = 2, col = “black” thiết lập vị trí nhãn trên cùng, kích thước chữ 90%,in độ đậm và chữ màu đen.
Nhận xét : Biểu đồ cho thấy số lượng nhà đã bán (sold) cao hơn đáng kể so với số nhà đang rao bán (for_sale). Cụ thể, số nhà bán được là 554.042, vượt khoảng 128.000 căn so với số nhà đang rao bán là 426.034. Điều này phản ánh thị trường bất động sản có tính thanh khoản khá tốt, nhu cầu mua cao hơn cung hiện có, cho thấy giao dịch diễn ra sôi động và thị trường đang phát triển tích cực.
1. status_count <- table(tieuluan$status)
2. percent <- round(100 * status_count / sum(status_count), 1)
3. labels <- paste(names(status_count), "-", percent, "%")
4. pie(
5. status_count,labels = labels,
6. main = "Tỷ lệ nhà theo trạng thái",
7. col = c("forestgreen", "goldenrod"),border = "white")
Giải thích kỹ thuật
Dòng 1: tạo bảng tần suất đếm số lượng các giá trị trong biến status.
Dòng 2: tính tỷ lệ phần trăm cho mỗi giá trị trong status_count, làm tròn đến một chữ số thập phân.
Dòng 3: tạo nhãn cho biểu đồ, kết hợp tên trạng thái với tỷ lệ phần trăm.
Dòng 4–7: Sử dụng hàm pie() để vẽ biểu đồ tròn, với các tham số:
Dòng 4: status_count là dữ liệu cần biểu diễn và gắn nhãn vào từng phần của biểu đồ.
Dòng 5: thiết lập tiêu đề cho biểu đồ.
Dòng 6: chọn màu sắc cho các phần của biểu đồ, đặt màu viền của các phần trong biểu đồ là trắn
1. boxplot(tieuluan$bath,
2. main = "Phân phối số phòng tắm",ylab = "Số lượng phòng tắm",
3. col = "#9D0",border = "#3E065F")
Giải thích kỹ thuật
Dòng 1:vẽ biểu đồ hộp(boxplot)cho biến bath, thể hiện phân phối số phòng tắm.
Dòng 2-4: xác định các chỉ số trong biểu đồ tương tự như Biểu đồ cột (Bar Plot): Số lượng nhà theo trạng thái bán.
1. boxplot(tieuluan$bath[tieuluan$bath >= 3],
2. main = "Phân phối số phòng tắm (≥ 3)",
3. ylab = "Số lượng phòng tắm",col = "yellow",border = "#3E065F")
Giải thích Kỹ thuật: các bước tương tự như Biểu đồ hộp (Box Plot): Phân phối số phòng tắm
1. bathroom_freq <- table(tieuluan$bath)
2. bp <- barplot(bathroom_freq,main = "Tần suất số phòng tắm",
3. xlab = "Số phòng tắm",ylab = "Số lượng nhà",
4. col = "lightcoral",ylim = c(0, max(bathroom_freq) * 1.2))
5. text(x = bp,y = bathroom_freq + max(bathroom_freq)*0.05,
6. labels = bathroom_freq,cex = 0.8,font = 2,col = "black")
Giải thích kỹ thuật
Dòng 1: tạo bảng tần suất để đếm số lượng các giá trị trong biến bath
Dòng 2:vẽ biểu đồ cột (barplot()) cho tần suất các giá trị trong bathroom_freq và lưu vị trí của các cột vào biến bp.
Dòng 4: thiết lập màu sắc cho các cột và điều chỉnh giới hạn trục Y để có thêm khoảng trống phía trên các cột.
Dòng 5: 0.05 là hệ số tạo khoảng cách 5% so với giá trị lớn nhất trong bathroom_freq, giúp nhãn cách đỉnh cột một khoảng.
Dòng 6: thiết lập nhãn điều chỉnh kích thước chữ (cex = 0.8), làm chữ đậm (font = 2) và màu chữ là đen.
1. top_cities <- sort(table(tieuluan$city), decreasing = TRUE)[1:10]
2. bp <- barplot(top_cities,las = 2,
3. col = "turquoise",main = "Top 10 thành phố có nhiều nhà nhất",
4. ylab = "Số lượng nhà",cex.names = 0.8,ylim = c(0, max(top_cities) * 1.25))
5. text(x = bp, y = top_cities + max(top_cities) * 0.03,
6. labels = top_cities, pos = 3, cex = 0.8,font = 2,col = "black")
Giải thích kỹ thuật
Dòng 1: tạo bảng tần suất cho biến city và sắp xếp theo thứ tự giảm dần, chỉ lấy 10 thành phố có nhiều nhà nhất.
Dòng 3: thiết lập màu sắc các cột và tiêu đề cho biểu đồ.
Dòng 4: thiết lập nhãn trục Y, giảm kích thước tên các thành phố xuống 80% (cex.names = 0.8) và trục Y để có khoảng trống phía trên các cột.
Dòng 5: thêm nhãn lên trên các cột, cách đỉnh cột một khoảng 3%.
Dòng 6: tương tự Biểu đồ cột (Bar Plot): Thể hiện tần suất số phòng tắm
1. top_cities <- sort(table(tieuluan$city), decreasing = TRUE)[1:10]
2. pct <- round(top_cities / sum(top_cities) * 100, 1)
3. labels <- paste(names(top_cities), "(", pct, "%)", sep = "")
4. pie(top_cities,labels = labels,
5. main = "Tỷ lệ % của Top 10 thành phố có nhiều nhà nhất",
6. col = rainbow(10), border = "white")
Giải thích kỹ thuật
Dòng 1: tương tự đồ thị trên
Dòng 2: tính tỷ lệ phần trăm của mỗi thành phố trong top_cities và làm tròn kết quả đến một chữ số thập phân.
Dòng 3:tạo nhãn cho biểu đồ, kết hợp tên thành phố với tỷ lệ phần trăm.
Dòng 4: vẽ biểu đồ tròn cho top_cities với nhãn đã có labels
1. bottom_cities <- sort(table(tieuluan$city), decreasing = FALSE)[1:10]
2. bp <- barplot(bottom_cities,las = 2,col = "pink",
3. main = "Top 10 thành phố có ít nhà nhất",
4. ylab = "Số lượng nhà",cex.names = 0.8,ylim = c(0, max(bottom_cities) * 1.25))
5. text(x = bp,y = bottom_cities + max(bottom_cities) * 0.03,
6. labels = bottom_cities,pos = 3,cex = 0.8,font = 2,col = "darkred")
Giải thích kỹ thuật
Dòng 1:tạo bảng tần suất cho biến city, sắp xếp theo thứ tự tăng dần và chỉ lấy 10 thành phố có ít nhà nhất.
Dòng 2:las = 2 xoay nhãn trục X thành dọc,col = “pink” chọn màu hồng cho các cột.
Dòng 4: thiết lập nhãn trục Y”, giảm kích thước tên các thành phố xuống 80% và điều chỉnh giới hạn trục Y để có thêm khoảng trống phía trên các cột.
Dòng 5:thêm nhãn (giá trị) lên trên các cột, cách đỉnh cột một khoảng 3%.
Dòng 6: thiết lập nhãn, in đậm, căn chỉnh chữ, màu chữ.
1. ggplot(tieuluan, aes(x = dientichdat, fill = status)) +
2. geom_bar(position = "dodge") +
3. geom_text(stat = "count", aes(label = ..count..),
4. position = position_dodge(width = 0.9),
5. vjust = -0.3, size = 3) +
6. scale_fill_manual(values = c("deepskyblue", "gold")) +
7. labs(title = "Trạng thái bán theo mức diện tích đất",
8. x = "Mức diện tích đất",
9. y = "Số lượng nhà") +
10. theme_minimal()
Giải thích kỹ thuật
Dòng 1: khởi tạo biểu đồ ggplot() với biến dientichdat trên trục X và màu sắc phân loại theo biến status.
Dòng 2: vẽ biểu đồ cột với các cột được đặt cạnh nhau (dodge) cho từng trạng thái trong biến status.
Dòng 3: thêm nhãn số lượng lên các cột, sử dụng ..count.. để lấy giá trị đếm cho mỗi nhóm.
Dòng 4: điều chỉnh vị trí nhãn sao cho không bị chồng lên các cột.
Dòng 5: điều chỉnh vị trí của nhãn lên trên cao hơn các cột (vjust = -0.3) và thiết lập kích thước chữ cho nhãn.
Dòng 6: thiết lập màu sắc thủ công cho các cột, với màu xanh dương và vàng cho các trạng thái.
Dòng 7: thiết lập tiêu đề, nhãn trục X và nhãn trục Y “.
Dòng 8: theme_minimal() áp dụng theme đơn giản cho biểu đồ.
1. ggplot(tieuluan %>% filter(status == "sold"),
2. aes(x = mucgianha, fill = mucgianha)) +
3. geom_bar() + geom_text(stat = "count", aes(label = ..count..),
4. hjust = -0.1, size = 2) + coord_flip() +
5. labs(title = "Số lượng nhà đã bán theo mức giá",
6. x = "Mức giá", y = "Số lượng nhà") +
7. scale_fill_manual(values = c("pink", "mediumpurple", "orange", "khaki", "tomato")) +theme_minimal(base_size = 13) +
8. theme(plot.title = element_text(hjust = 0.5, face = "bold"),
9. legend.position = "none")
Giáỉ thích kỹ thuật
Dòng 1: trục X là mucgianha và màu sắc phân loại theo mucgianha.
Dòng 2: Vẽ biểu đồ cột (geom_bar()) cho các giá trị của mucgianha trong nhóm nhà đã bán.
Dòng 3: Thêm nhãn số lượng vào biểu đồ cột, tính số lượng cho mỗi nhóm và hiển thị nhãn số lượng lên trên các cột.
Dòng 4: hjust = -0.1 điều chỉnh vị trí nhãn, đẩy chúng ra ngoài cột và size = 2 điều chỉnh kích thước chữ của nhãn.
Dòng 5: chuyển trục X thành trục Y và ngược lại để các nhãn dễ đọc hơn.
Dòng 6: Thiết lập tiêu đề của biểu đồ”, nhãn trục X”, và nhãn trục Y.
Dòng 7: dùng để chọn màu sắc cho các cột trong biểu đồ
Dòng 8: làm cho biểu đồ gọn gàng và dễ nhìn hơn.
Dòng 9: Điều chỉnh tiêu đề để căn giữa tiêu đề và làm chữ đậm, ẩn phần chú giải (legend).
1. ggplot(tieuluan %>% filter(status == "for_sale"),
2. aes(x = mucgianha, fill = mucgianha)) + geom_bar() +
3. geom_text(stat = "count", aes(label = ..count..),
4. hjust = -0.1, size = 2) + coord_flip() + labs(title = "Số lượng nhà đang rao bán theo mức giá",
5. x = "Mức giá",y = "Số lượng nhà" ) +
6. scale_fill_manual(values = c("dodgerblue", "yellowgreen", "goldenrod", "coral", "brown")) + # Màu mới hoàn toàn cho từng mức giá
7. theme_minimal(base_size = 13) +
8. theme(plot.title = element_text(hjust = 0.5, face = "bold"),
9. legend.position = "none")
Giải thích kỹ thuật: tương tự Biểu đồ cột ngang: Số lượng nhà đã bán theo từng mức giá
1. sold_data <- tieuluan %>%
2. filter(status == "sold")
3. data_pie <- sold_data %>%
4. count(dientichdat) %>%
5. mutate(tyle = round(n / sum(n) * 100, 2),
6. label = paste0(dientichdat, " - ", tyle, "%"))
7. ggplot(data_pie, aes(x = "", y = n, fill = dientichdat)) +
8. geom_bar(stat = "identity", width = 1) + coord_polar("y") + geom_text( aes(label = label),
9. position = position_stack(vjust = 0.5),size = 3 ) + scale_fill_manual(
10. values = c("orangered", "aquamarine4", "wheat", "plum", "dodgerblue4")) +
11. labs( title = "Tỷ lệ nhà đã bán theo diện tích đất" ) +
12. theme_void() +
13. theme(plot.title = element_text(hjust = 0.5, face = "bold"))
Giải thích kỹ thuật
Dòng 1: lấy các nhà có trạng thái “sold” (đã bán), lưu vào biến sold_data.
Dòng 2: Đếm số lượng nhà bán theo nhóm dientichdat
Dòng 3: mutate(tyle = round(n / sum(n) * 100, 2), label = paste0(dientichdat, ” - “, tyle,”%“)) Tạo cột mới tyle tính tỷ lệ phần trăm của từng diện tích đất (dientichdat), làm tròn kết quả đến 2 chữ số, và tạo nhãn (label) kết hợp diện tích đất và tỷ lệ phần trăm.
Dòng 4: vẽ biểu đồ tròn, trục X rỗng, trục Y là số lượng nhà và fill = dientichdat.
Dòng 5: Vẽ biểu đồ cột với các cột có chiều rộng bằng 1 (width = 1) và chuyển biểu đồ thành hình tròn bằng coord_polar(“y”).
Dòng 6: Thêm nhãn tỷ lệ phần trăm vào các phần trong biểu đồ tròn, căn chỉnh nhãn theo chiều dọc và điều chỉnh kích thước chữ là 3.
Dòng 7: Sử dụng màu sắc thủ công cho các phần của biểu đồ tròn, với màu sắc.
Dòng 9: để loại bỏ các trục, nhãn và lưới, giúp biểu đồ trở nên đơn giản.
Dòng 10: Căn giữa tiêu đề với hjust = 0.5 và làm chữ đậm.
Nhận xét: Biểu đồ cho thấy phần lớn các căn nhà đã bán tập trung ở nhóm “Nhỏ” (38,87%) và “Vừa” (34,46%), chiếm hơn 70% tổng số giao dịch. Trong khi đó, nhóm “Rất nhỏ” chiếm khoảng 15,68%, còn “Lớn” và “Rất lớn” lần lượt chỉ chiếm 8,24% và 2,74%. Điều này cho thấy nhà có diện tích trung bình và nhỏ vẫn là phân khúc được giao dịch phổ biến nhất, phù hợp với khả năng chi trả và nhu cầu thực tế của phần lớn người mua trên thị trường.
1. rent_data <- tieuluan %>%
2. filter(status == "for_sale")
3. data_pie_rent <- rent_data %>%
4. count(dientichdat) %>%
5. mutate(tyle = round(n / sum(n) * 100, 2),
6. label = paste0(dientichdat, " - ", tyle, "%"))
7. ggplot(data_pie_rent, aes(x = "", y = n, fill = dientichdat)) +
8. geom_bar(stat = "identity", width = 1) +
9. coord_polar("y") + geom_text(aes(label = label),
10. position = position_stack(vjust = 0.5), size = 3) + scale_fill_manual(values = c(
11. "seagreen", "deeppink", "goldenrod1", "cornflowerblue", "tan" )) +
12. labs(title = "Tỷ lệ nhà đang cho thuê theo diện tích đất") +
13. theme_void() +
14. theme(plot.title = element_text(hjust = 0.5, face = "bold"))
Giải thích kỹ thuật: biểu đồ vẽ tương tự biểu đồ tròn: Tỷ lệ nhà đã bán theo diện tích đất
1. forsale_2018_2020 <- tieuluan %>%
2. filter(status == "for_sale" & prev_year >= 2018 & prev_year <= 2020)
3. price_month_fs <- forsale_2018_2020 %>%
4. group_by(prev_month_year) %>%
5. summarise(price_tb = mean(price, na.rm = TRUE))
6. ggplot(price_month_fs, aes(x = prev_month_year,
7. y = price_tb,
8. group = 1)) +
9. geom_line(color = "deeppink", size = 1.2) +
10. geom_point(color = "deeppink", size = 2) +
11. labs(title = "Xu hướng giá bán trung bình nhà đang rao bán (2018–2020)",
12. x = "Tháng-Năm",
13. y = "Giá bán trung bình (USD)") +
14. theme_minimal() +
15. theme(axis.text.x = element_text(angle = 60, hjust = 0.5))
Giải thích kỹ thuật
Dòng 1:lấy các bản ghi có trạng thái là “for_sale” và năm từ 2018 đến 2020.
Dòng 2: Nhóm dữ liệu theo tháng và năm (prev_month_year) và tính giá bán trung bình (price_tb) cho mỗi tháng, bỏ qua giá trị NA.
Dòng 3: vẽ biểu đồ ggplot() sử dụng prev_month_year làm trục X (tháng-năm) và price_tb làm trục Y (giá bán trung bình), group = 1 đảm bảo tất cả các điểm được nối thành một đường duy nhất, không phân nhóm theo các giá trị khác.
Dòng 4:Vẽ đường cho giá bán trung bình có độ dày đường là 1.2.
Dòng 5: Thêm các điểm tròn vào biểu đồ đường kích thước điểm là 2.
Dòng 8: Căn chỉnh văn bản của trục X theo góc 60 độ và căn giữa các nhãn với hjust = 0.5.
1. freq_table <- tieuluan %>%
2. group_by(dientichdat, mucgianha) %>%
3. summarise(count = n()) %>%
4. ungroup()
5. ggplot(freq_table, aes(x = dientichdat, y = mucgianha, fill = count)) +
6. geom_tile(color = "white") +
7. scale_fill_gradient(low = "thistle",
8. high = "seagreen") +
9. theme_minimal() +
10. labs(x = "Diện tích đất",y = "Mức giá nhà",fill = "Số lượng")
Giải thích kỹ thuật
Dòng 1: freq_table <- tieuluan %>% group_by(dientichdat, mucgianha) %>% summarise(count = n()) %>% ungroup() Nhóm dữ liệu theo dientichdat (diện tích đất) và mucgianha (mức giá nhà), đếm số lượng bản ghi trong mỗi nhóm và lưu kết quả vào cột count, sau đó hủy nhóm (ungroup()).
Dòng 2:vẽ biểu đồ ggplot() trục X là diện tích đất, trục Y là mức giá nhà và fill = count
Dòng 3: Vẽ các ô với viền màu trắng.
Dòng 4:Thiết lập màu sắc cho các ô, với màu nhẹ cho các giá trị nhỏ và màu đậm cho các giá trị lớn.
1. ggplot(tieuluan, aes(x = log(acre_lot_m2 + 1),
2. y = log(price + 1),
3. color = mucgianha)) +
4. geom_point(alpha = 0.2) +
5. scale_color_manual(values = c(
6. "goldenrod", "slateblue", "brown3", "palegreen", "coral"
7. )) +
8. theme_minimal() +
9. labs(x = "log(Diện tích đất m²)",y = "log(Giá nhà)",color = "Mức giá")
Giải thích kỹ thuật
Dòng 1: vẽ biểu đồ ggplot() với acre_lot_m2 và price được chuyển đổi sang logarit (thêm 1 để tránh log(0)).
Dòng 2: Vẽ các điểm trên biểu đồ, với độ trong suốt (alpha = 0.2).
Dòng 3: Chỉ định màu sắc thủ công cho các điểm.
1. ggplot(tieuluan, aes(x = acre_lot_m2)) +
2. geom_histogram(binwidth = 500, fill = 'plum', color = 'forestgreen') +
3. facet_wrap(~ dientichdat) +
4. labs(title = 'Phân phối diện tích đất theo từng mức diện tích đất',
5. x = 'Diện tích đất (m²)',y = 'Số lượng') +
6. theme_minimal()
Giải thích kỹ thuật
Dòng 1: sử dụng biến acre_lot_m2 làm trục X
Dòng 2: vẽ biểu đồ histogram, chia diện tích đất thành các khoảng 500 m², tô màu cột và viền cột.
Dòng 3: chia biểu đồ thành nhiều ô nhỏ theo nhóm dientichdat
Dòng 4: thêm tiêu đề , nhãn trục X và trục Y .
Dòng 5: tạo biểu đồ gọn gàng, đơn giản
1. ggplot(tieuluan, aes(x = price)) +
2. geom_histogram(binwidth = 100000, fill = 'mediumseagreen', color = 'magenta') +
3. facet_wrap(~ mucgianha) +
4. labs(title = 'Phân phối giá bất động sản theo mức giá nhà',
5. x = 'Giá bất động sản (USD)', y = 'Số lượng') +
6. theme_minimal()
Giải thích kỹ thuật : vẽ biểu đồ tương tự Biểu đồ Histogram: Phân phối giá bất động sản theo từng mức giá nhà
1. tieuluan_2018_2024 <- tieuluan %>% filter(prev_year %in% 2018:2024)
2. ggplot(tieuluan_2018_2024, aes(x = price)) +
3. geom_histogram(binwidth = 100000, fill = "purple", color = "deepskyblue") +
4. facet_wrap(~ prev_year) +
5. labs(title = "Histogram phân phối giá theo từng năm (2018–2024)",
6. x = "Giá bất động sản (USD)",y = "Số lượng") +
7. theme_minimal(base_size = 13) +
8. theme(
9. plot.title = element_text(hjust = 0.5, face = "bold"),
10. axis.text.x = element_text(size = 10))
Giải thích kỹ thuật :
Dòng 1: chỉ lấy các bản ghi có năm (prev_year) từ 2018 đến 2024.
Dòng 2: sử dụng price làm trục X để hiển thị phân phối giá.
Dòng 3: vẽ biểu đồ histogram với mỗi cột có chiều rộng 100.000 USD, tô màu cột và viền cột
Dòng 4: chia biểu đồ thành các phần nhỏ theo từng năm (prev_year)
Dòng 5: thiết lập tiêu đề cho biểu đồ, nhãn trục X và trục Y .
Dòng 6: làm biểu đồ trở nên sạch sẽ và dễ nhìn với kích thước chữ cơ bản.
Dòng 7: căn giữa tiêu đề (0.5x) của biểu đồ và làm chữ đậm
Dòng 8: cỡ chữ cột X là 10
1. ggplot(tieuluan, aes(x = bath)) +
2. geom_density(fill = "darkmagenta") +
3. facet_wrap(~ dientichdat) +
4. labs(title = "Density plot số phòng tắm theo nhóm diện tích đất",
5. x = "Số phòng tắm", y = "Mật độ") +
6. theme_minimal(base_size = 13) +
7. theme(plot.title = element_text(hjust = 0.5, face = "bold"))
Giải thích kỹ thuật
Dòng 1:Khởi tạo biểu đồ ggplot(), sử dụng biến bath làm trục X.
Dòng 2: Vẽ đồ thị mật độ (density plot) cho bath, geom_density() tạo ra một đồ thị mật độ cho biến bath.
Dòng 3: Tạo các phần (facets) cho biểu đồ dựa trên biến dientichdat.
Dòng 4: Thiết lập tiêu đề cho biểu đồ và đặt nhãn cho trục X và trục Y.
Dòng 5: giúp biểu đồ trông gọn gàng hơn, base_size = 13 chỉ định kích thước chữ cơ bản cho các phần tử trên biểu đồ.
Dòng 6: căn giữa tiêu đề (hjust = 0.5) và làm chữ đậm.
Phân tích cho thấy thị trường bất động sản Hoa Kỳ tập trung chủ yếu ở phân khúc giá “Rẻ – Trung bình” và diện tích “Nhỏ – Vừa”. Các giao dịch đã bán chiếm ưu thế hơn đang rao bán, phản ánh thanh khoản tốt và nhu cầu ở thực cao. Phân phối giá và diện tích đều lệch phải, cho thấy sự chênh lệch lớn giữa các nhóm nhà, đặc biệt ở khu vực giá cao.
Giá nhà trung bình duy trì quanh mức dưới 500.000 USD, trong đó nhóm giá “Rẻ” và “Trung bình” chiếm đa số. Những căn có 2–3 phòng tắm, diện tích vừa phải được giao dịch nhiều nhất, phản ánh xu hướng đô thị hóa và ưu tiên nhà ở phù hợp khả năng chi trả. Mối quan hệ giữa diện tích và giá có xu hướng tăng cùng nhau nhưng không mạnh, cho thấy các yếu tố như vị trí và chất lượng vẫn đóng vai trò quan trọng hơn.
Nhìn chung, thị trường nhà ở Hoa Kỳ có tính ổn định và đa tầng, với tâm điểm là phân khúc phổ thông. Kết quả này là cơ sở để liên hệ sang phân tích BIDV, khi xu hướng giá và cầu nhà ở có thể tác động đến tín dụng bán lẻ, biên lợi nhuận (NIM) và hiệu quả sinh lời (NPM) của ngân hàng giai đoạn 2010–2024.
Bộ dữ liệu Báo cáo tài chính BIDV được nhóm tác giả thu thập từ trang web “BIDV.com.vn” bao gồm các biến tài chính quan trọng của Ngân hàng TMCP Đầu tư và Phát triển Việt Nam (BIDV) được thu thập trong giai đoạn \(\text{15}\) năm, từ năm \(\text{2010}\) đến \(\text{2024}\). Các biến được chia thành nhiều nhóm: Quy mô (như Tổng tài sản, Dư nợ cho vay), Hiệu suất (như ROA, ROE, Lợi nhuận trước/sau thuế), Cơ cấu vốn (Vốn chủ sở hữu, Tổng nợ), Dòng tiền và Các khoản mục thu chi cốt lõi (như Doanh thu lãi thuần, Chi phí hoạt động, Chi phí tín dụng). Đây là cơ sở dữ liệu toàn diện giúp phân tích xu hướng tăng trưởng, đo lường khả năng sinh lời, đánh giá hiệu quả quản lý rủi ro và nhận diện các chiến lược tài chính của BIDV trong một chu kỳ kinh tế dài.
Ta giả tiến hành đọc từng sheet của file excel Báo cáo tài chính của BIDV giai đoạn 2010-2024 và gán cho từng sheet “Cân đối kế toán”, “Hoạt động kinh doanh”, “Lưu chuyển tiền tệ” tương ứng với các object “CDKT”, “HDKD” và “LCTT”.
1. # Đọc từng sheet vào các dataframe riêng biệt và gán bào từng object mới
2. CDKT <- read_excel("D:/TMT_R/BCTC_BID_Final.xlsx", sheet = "CDKT")
3. HDKD <- read_excel("D:/TMT_R/BCTC_BID_Final.xlsx", sheet = "HDKD")
4. LCTT <- read_excel("D:/TMT_R/BCTC_BID_Final.xlsx", sheet = "LCTT")
5. head(CDKT)
1. head(HDKD)
1. head(LCTT)
Giải thích kỹ thuật
Dòng 1-3: Đọc từng sheet vào các dataframe riêng biệt
Dòng 4-6: xem 6 dòng đầu của từng dataframe
Tiếp theo tác giả lọc 14 biến phù hợp với nhu cầu phân tích và gán vào một object mới tên là “BIDV”
1. # Lọc biến tại từng bảng
2. CDKT_sel <- CDKT %>%
3. select(nam = Năm,tong_tai_san = `TỔNG TÀI SẢN`,
4. tien_mat_vangbac_daquy = `Tiền mặt, vàng bạc, đá quý`,
5. tong_no_phai_tra = `Tổng nợ phải trả`,
6. von_chu_so_huu = `Vốn chủ sở hữu`)
7. HDKD_sel <- HDKD %>%
8. select(nam = Năm,
9. thu_nhap_lai_va_cac_khoan_tuong_tu = `Thu nhập lãi và các khoản thu nhập tương tự`,
10. chi_phi_lai_va_cac_chi_phi_tuong_tu = `Chi phí lãi và các chi phí tương tự`,
11. thu_nhap_lai_thuan = `Thu nhập lãi thuần`,
12. loi_nhuan_sau_thue = `Lợi nhuận sau thuế`,
13. lai_lo_thuan_hd_ngoai_hoi_va_vang = `Lãi/(lỗ) thuần từ hoạy động kinh doanh ngoại hối và vàng`,
14. tong_thu_nhap_hoat_dong = `Tổng thu nhập hoạt động`)
15. LCTT_sel <- LCTT %>%
16. select(nam = Năm,
17. thanh_toan_nv_ncc = `Thanh toán cho nhân viên và nhà cung cấp`,
18. chi_thue_tndn = `Tiền chi nộp thuế thu nhập doanh nghiệp`,
19. tien_thu_thanh_ly_ts_co_dinh = `Tiền thu được từ thanh lý tài sản cố định`)
20. BIDV <- CDKT_sel %>%
21. left_join(HDKD_sel, by = "nam") %>%
22. left_join(LCTT_sel, by = "nam")
23. colnames(BIDV) <- gsub("\\s+", "_", tolower(
24. stringi::stri_trans_general(colnames(BIDV), "Latin-ASCII")))
25. # Xem 6 dòng đầu tiên và cuối cùng của bảng kết quả
26. head(BIDV)
1. tail(BIDV)
Giải thích kỹ thuật
Dòng 1: lọc và chọn các cộ từ bảng dữ liệu CDKT
Dòng 2-4: đổi tên các biến ứng với các biến trong CDKT
Dòng 5-18: làm tương tự dòng 1-4 cho 2 bảng HDKD và LCTT
Dòng 19: Thực hiện phép left_join giữa bảng CDKT_sel và bảng HDKD_sel dựa trên cột nam. Điều này kết hợp thông tin từ hai bảng dựa trên năm (nam), giữ tất cả các dòng từ CDKT_sel và bổ sung các giá trị tương ứng từ HDKD_sel. Nếu không có kết quả tương ứng trong HDKD_sel, các giá trị từ bảng đó sẽ là NA.
Dòng 20:thực hiện phép left_join với bảng LCTT_sel, cũng dựa trên cột nam. Điều này kết hợp thông tin từ bảng LCTT_sel với bảng kết quả của phép left_join trước đó (giữa CDKT_sel và HDKD_sel), giữ lại tất cả dữ liệu từ bảng hiện tại và bổ sung dữ liệu từ LCTT_sel theo năm (nam).
Dòng 21 :gsub(“\s+”, “_“, …) Thay thế tất cả khoảng trắng trong tên cột bằng dấu gạch dưới, tolower: chuyển thành chữ thường.
Dòng 22: Chuyển đổi tên các cột sang dạng ASCII chuẩn, loại bỏ dấu tiếng Việt và các ký tự đặc biệt.
Ta sử dụng sử dụng một số lệnh bên dưới để xem thông tin chung của BIDV.
1. dim(BIDV)
## [1] 15 14
Giải thích kỹ thuật : Kiểm tra kích thước bộ dữ liệu BIDV
-Nhận xét : Sử dụng lệnh dim() kết quả trả về cho thấy bộ dữ liệu BIDV có 15 hàng (quan sát) và 14 cột (biến), cho thấy số quan sát còn ít nhưng số lượng biến khá đầy đủ để phân tích nhiều khía cạnh tài chính và hoạt động của BIDV.
1. names(BIDV)
## [1] "nam" "tong_tai_san"
## [3] "tien_mat_vangbac_daquy" "tong_no_phai_tra"
## [5] "von_chu_so_huu" "thu_nhap_lai_va_cac_khoan_tuong_tu"
## [7] "chi_phi_lai_va_cac_chi_phi_tuong_tu" "thu_nhap_lai_thuan"
## [9] "loi_nhuan_sau_thue" "lai_lo_thuan_hd_ngoai_hoi_va_vang"
## [11] "tong_thu_nhap_hoat_dong" "thanh_toan_nv_ncc"
## [13] "chi_thue_tndn" "tien_thu_thanh_ly_ts_co_dinh"
Giải thích kỹ thuật :Xem tên các biến trong BIDV
Dữ liệu bao gồm các biến sau, được tổng hợp chi tiết trong bảng dưới đây nhằm phục vụ cho quá trình phân tích.
| STT | Tên biến | Mô tả |
|---|---|---|
| 1 | nam | Năm báo cáo tài chính |
| 2 | tong_tai_san | Tổng tài sản hợp nhất tại thời điểm báo cáo |
| 3 | tien_mat_vangbac_daquy | Tiền mặt, vàng bạc, đá quý của doanh nghiệp |
| 4 | tong_no_phai_tra | Tổng nợ phải trả vào cuối kỳ báo cáo |
| 5 | von_chu_so_huu | Vốn chủ sở hữu của BIDV tại thời điểm báo cáo |
| 6 | thu_nhap_lai_va_cac_khoan_tuong_tu | Thu nhập lãi cùng các khoản tương tự do ngân hàng tạo ra |
| 7 | chi_phi_lai_va_cac_chi_phi_tuong_tu | Chi phí lãi cùng các chi phí tương tự phải trả trong kỳ |
| 8 | thu_nhap_lai_thuan | Thu nhập lãi thuần từ hoạt động tài chính |
| 9 | loi_nhuan_sau_thue | Lợi nhuận ròng sau thuế thu nhập doanh nghiệp |
| 10 | lai_lo_thuan_hd_ngoai_hoi_va_vang | Lãi hoặc lỗ thuần từ hoạt động kinh doanh ngoại hối và vàng |
| 11 | tong_thu_nhap_hoat_dong | Tổng thu nhập hoạt động phát sinh trong kỳ |
| 12 | thanh_toan_nv_ncc | Chi phí thanh toán cho nhân viên và nhà cung cấp |
| 13 | chi_thue_tndn | Tiền chi trả thuế thu nhập doanh nghiệp |
| 14 | tien_thu_thanh_ly_ts_co_dinh | Tiền thu được từ việc thanh lý tài sản cố định |
Giải thích kỹ thuật
Dòng 1: Dùng để tạo một bảng dữ liệu mới tên des_bidv bằng hàm data.frame().
Dòng 2: Dùng để tạo cột STT, chứa các số thứ tự từ 1 đến 14.
Dòng 3-4: Dùng để tạo cột Ten_bien, chứa danh sách tên các biến trong bộ dữ liệu tài chính BIDV.
Dòng 5-11: Dùng để tạo cột Mo_ta, mô tả chi tiết cho các biến trong bộ dữ liệu tài chính.
Dòng 12: Dùng để gọi bảng dữ liệu des_bidv và truyền qua các hàm tiếp theo bằng toán tử %>%.
Dòng 13: Dùng hàm kable() để chuyển bảng des_bidv thành bảng HTML, với tham số align = “c” để căn giữa tất cả các cột.
Dòng 14: Dùng col.names để đặt tiêu đề các cột là “STT”, “Tên biến”, và “Mô tả” (các tên này được in đậm).
Dòng 15: Dùng caption để thêm tiêu đề cho bảng, căn giữa và in đậm dòng chữ “Bảng 1. Danh sách các biến trong dữ liệu tài chính BIDV”.
Dòng 16: Dùng hàm kable_styling() để chỉnh giao diện bảng HTML.
Dòng 17: Các tùy chọn striped, hover, condensed, responsive giúp bảng có hiệu ứng xen kẽ màu sắc, đổi màu khi rê chuột, gọn gàng hơn và tự động điều chỉnh kích thước; full_width = FALSE giúp bảng không chiếm toàn bộ chiều rộng, position = “center” căn giữa bảng, và font_size = 14 thay đổi cỡ chữ.
Dòng 18: Dùng row_spec(0, bold = TRUE, background = “#6495ED”) để định dạng hàng tiêu đề, làm chữ đậm và có nền màu xanh dương đậm (#6495ED).
Dòng 19: Dùng column_spec(1:3, border_right = TRUE) để thêm viền phải cho cả ba cột trong bảng.
1. str(BIDV)
## tibble [15 × 14] (S3: tbl_df/tbl/data.frame)
## $ nam : chr [1:15] "2010" "2011" "2012" "2013" ...
## $ tong_tai_san : num [1:15] 3.66e+14 4.06e+14 4.85e+14 5.48e+14 6.50e+14 ...
## $ tien_mat_vangbac_daquy : num [1:15] 3.25e+12 3.63e+12 3.30e+12 3.86e+12 5.39e+12 ...
## $ tong_no_phai_tra : num [1:15] 3.42e+14 3.81e+14 4.58e+14 5.16e+14 6.17e+14 ...
## $ von_chu_so_huu : num [1:15] 2.42e+13 2.44e+13 2.65e+13 3.20e+13 3.36e+13 ...
## $ thu_nhap_lai_va_cac_khoan_tuong_tu : num [1:15] 2.98e+13 4.46e+13 3.05e+13 4.38e+13 4.40e+13 ...
## $ chi_phi_lai_va_cac_chi_phi_tuong_tu: num [1:15] -2.06e+13 -3.19e+13 -2.13e+13 -2.90e+13 -2.71e+13 ...
## $ thu_nhap_lai_thuan : num [1:15] 9.19e+12 1.26e+13 9.21e+12 1.48e+13 1.68e+13 ...
## $ loi_nhuan_sau_thue : num [1:15] 3.76e+12 3.20e+12 2.57e+12 4.05e+12 4.99e+12 ...
## $ lai_lo_thuan_hd_ngoai_hoi_va_vang : num [1:15] 2.89e+11 3.14e+11 2.47e+11 1.62e+11 2.65e+11 ...
## $ tong_thu_nhap_hoat_dong : num [1:15] 1.15e+13 1.54e+13 1.15e+13 1.92e+13 2.19e+13 ...
## $ thanh_toan_nv_ncc : num [1:15] -5.01e+12 -6.33e+12 -4.53e+12 -6.58e+12 -7.96e+12 ...
## $ chi_thue_tndn : num [1:15] -7.14e+11 -1.20e+12 -9.69e+11 -1.09e+12 -1.51e+12 ...
## $ tien_thu_thanh_ly_ts_co_dinh : num [1:15] 5.99e+09 2.91e+09 3.32e+09 4.08e+09 1.67e+09 ...
Giải thích kỹ thuật : Xem cấu trúc tổng quát của dữ liệu BID
1. sapply(BIDV, class)
## nam tong_tai_san
## "character" "numeric"
## tien_mat_vangbac_daquy tong_no_phai_tra
## "numeric" "numeric"
## von_chu_so_huu thu_nhap_lai_va_cac_khoan_tuong_tu
## "numeric" "numeric"
## chi_phi_lai_va_cac_chi_phi_tuong_tu thu_nhap_lai_thuan
## "numeric" "numeric"
## loi_nhuan_sau_thue lai_lo_thuan_hd_ngoai_hoi_va_vang
## "numeric" "numeric"
## tong_thu_nhap_hoat_dong thanh_toan_nv_ncc
## "numeric" "numeric"
## chi_thue_tndn tien_thu_thanh_ly_ts_co_dinh
## "numeric" "numeric"
Giải thích kỹ thuật: Xem kiểu dữ liệu theo từng cột của BIDV
1. skim(BIDV)
| Name | BIDV |
| Number of rows | 15 |
| Number of columns | 14 |
| _______________________ | |
| Column type frequency: | |
| character | 1 |
| numeric | 13 |
| ________________________ | |
| Group variables | None |
Variable type: character
| skim_variable | n_missing | complete_rate | min | max | empty | n_unique | whitespace |
|---|---|---|---|---|---|---|---|
| nam | 0 | 1 | 4 | 4 | 0 | 15 | 0 |
Variable type: numeric
| skim_variable | n_missing | complete_rate | mean | sd | p0 | p25 | p50 | p75 | p100 | hist |
|---|---|---|---|---|---|---|---|---|---|---|
| tong_tai_san | 0 | 1 | 1.251883e+15 | 7.412196e+14 | 3.662678e+14 | 5.993632e+14 | 1.202284e+15 | 1.639191e+15 | 2.760792e+15 | ▇▆▅▂▃ |
| tien_mat_vangbac_daquy | 0 | 1 | 8.430533e+12 | 3.977379e+12 | 3.253384e+12 | 4.628074e+12 | 8.203016e+12 | 1.166170e+13 | 1.411672e+13 | ▇▃▂▅▆ |
| tong_no_phai_tra | 0 | 1 | 1.188759e+15 | 7.037727e+14 | 3.418986e+14 | 5.664138e+14 | 1.153450e+15 | 1.556203e+15 | 2.615881e+15 | ▇▅▆▂▃ |
| von_chu_so_huu | 0 | 1 | 6.306981e+13 | 3.801020e+13 | 2.421973e+13 | 3.282309e+13 | 4.883401e+13 | 8.298782e+13 | 1.449111e+14 | ▇▂▃▁▂ |
| thu_nhap_lai_va_cac_khoan_tuong_tu | 0 | 1 | 7.914638e+13 | 3.951223e+13 | 2.978186e+13 | 4.427068e+13 | 7.862851e+13 | 1.008776e+14 | 1.527613e+14 | ▇▂▅▁▂ |
| chi_phi_lai_va_cac_chi_phi_tuong_tu | 0 | 1 | -4.849219e+13 | 2.280513e+13 | -9.662575e+13 | -6.483006e+13 | -4.767318e+13 | -2.933516e+13 | -2.059048e+13 | ▁▁▇▂▇ |
| thu_nhap_lai_thuan | 0 | 1 | 3.065420e+13 | 1.739830e+13 | 9.191386e+12 | 1.584445e+13 | 3.095533e+13 | 4.140056e+13 | 5.800758e+13 | ▇▃▆▂▅ |
| loi_nhuan_sau_thue | 0 | 1 | 9.207143e+12 | 7.080721e+12 | 2.571943e+12 | 4.518338e+12 | 6.945586e+12 | 9.694514e+12 | 2.560404e+13 | ▇▃▁▁▂ |
| lai_lo_thuan_hd_ngoai_hoi_va_vang | 0 | 1 | 1.476188e+12 | 1.671746e+12 | 1.622780e+11 | 2.913230e+11 | 6.681280e+11 | 1.814239e+12 | 5.361499e+12 | ▇▂▁▁▂ |
| tong_thu_nhap_hoat_dong | 0 | 1 | 4.013631e+13 | 2.338242e+13 | 1.148508e+13 | 2.053524e+13 | 3.901672e+13 | 5.626547e+13 | 8.106087e+13 | ▇▂▃▁▃ |
| thanh_toan_nv_ncc | 0 | 1 | -1.363652e+13 | 6.859184e+12 | -2.580315e+13 | -1.836830e+13 | -1.379649e+13 | -7.267992e+12 | -4.525990e+12 | ▃▅▅▃▇ |
| chi_thue_tndn | 0 | 1 | -2.203221e+12 | 1.593351e+12 | -6.884931e+12 | -2.362017e+12 | -1.732575e+12 | -1.355578e+12 | -7.138120e+11 | ▁▁▁▂▇ |
| tien_thu_thanh_ly_ts_co_dinh | 0 | 1 | 9.257067e+09 | 5.983982e+09 | 1.671000e+09 | 4.689000e+09 | 8.545000e+09 | 1.144800e+10 | 2.238700e+10 | ▇▆▆▁▃ |
| Biến | Nhận_xét |
|---|---|
| nam | Biến ký tự, không thiếu giá trị, gồm 15 quan sát thể hiện các năm trong giai đoạn 2010–2024. |
| tong_tai_san | Biến số, không thiếu giá trị, trung bình ~1.25e+15, dao động từ 3.66e+14 đến 2.76e+15; tổng tài sản BIDV tăng liên tục qua các năm, thể hiện quy mô mở rộng mạnh mẽ. |
| tien_mat_vangbac_daquy | Biến số, không thiếu giá trị, trung bình ~8.43e+12, dao động từ 3.25e+12 đến 1.41e+13; lượng tiền mặt, vàng bạc, đá quý tăng dần nhưng biến động nhẹ qua các năm. |
| tong_no_phai_tra | Biến số, không thiếu giá trị, trung bình ~1.19e+15, dao động từ 3.42e+14 đến 2.62e+15; tổng nợ phải trả tăng theo quy mô hoạt động, chiếm tỷ trọng lớn trong tổng tài sản. |
| von_chu_so_huu | Biến số, không thiếu giá trị, trung bình ~6.31e+13, dao động từ 2.42e+13 đến 1.45e+14; vốn chủ sở hữu tăng ổn định, phản ánh khả năng tích lũy vốn tốt. |
| thu_nhap_lai_va_cac_khoan_tuong_tu | Biến số, không thiếu giá trị, trung bình ~7.91e+13, dao động từ 2.98e+13 đến 1.53e+14; thu nhập lãi và các khoản tương tự tăng theo thời gian, là nguồn thu chính của ngân hàng. |
| chi_phi_lai_va_cac_chi_phi_tuong_tu | Biến số, không thiếu giá trị, trung bình ~-4.85e+13, dao động từ -9.66e+13 đến -2.06e+13; chi phí lãi mang giá trị âm, phản ánh chi phí vốn của ngân hàng, biến động mạnh giữa các năm. |
| thu_nhap_lai_thuan | Biến số, không thiếu giá trị, trung bình ~3.07e+13, dao động từ 9.19e+12 đến 5.80e+13; thu nhập lãi thuần tăng qua các năm, cho thấy hiệu quả kinh doanh cốt lõi được duy trì. |
| loi_nhuan_sau_thue | Biến số, không thiếu giá trị, trung bình ~9.21e+12, dao động từ 2.57e+12 đến 2.56e+13; lợi nhuận sau thuế tăng trưởng dần, nhưng độ lệch chuẩn cao phản ánh biến động lợi nhuận lớn. |
| lai_lo_thuan_hd_ngoai_hoi_va_vang | Biến số, không thiếu giá trị, trung bình ~1.48e+12, dao động từ 1.62e+11 đến 5.36e+12; lãi/lỗ thuần từ hoạt động ngoại hối và vàng có biến động mạnh do ảnh hưởng tỷ giá và giá vàng. |
| tong_thu_nhap_hoat_dong | Biến số, không thiếu giá trị, trung bình ~4.01e+13, dao động từ 1.15e+13 đến 8.11e+13; tổng thu nhập hoạt động tăng đáng kể, phản ánh tăng trưởng ổn định của BIDV. |
| thanh_toan_nv_ncc | Biến số, không thiếu giá trị, trung bình ~-1.36e+13, dao động từ -2.58e+13 đến -4.53e+12; dòng tiền thanh toán cho nhân viên và nhà cung cấp âm, thể hiện chi ra trong hoạt động thường xuyên. |
| chi_thue_tndn | Biến số, không thiếu giá trị, trung bình ~-2.20e+12, dao động từ -6.88e+12 đến -7.14e+11; chi thuế thu nhập doanh nghiệp phản ánh nghĩa vụ thuế tăng theo lợi nhuận. |
| tien_thu_thanh_ly_ts_co_dinh | Biến số, không thiếu giá trị, trung bình ~9.26e+09, dao động từ 1.67e+09 đến 2.24e+10; tiền thu từ thanh lý tài sản cố định nhỏ, ít ảnh hưởng đến tổng lưu chuyển tiền. |
Giải thích kỹ thuật:
Dòng 1-30: Tạo hai vector var và nhan_xet chứa tên các biến và các nhận xét về các biến đó, ứng với 14 biến tài chính trong dữ liệu BIDV.
Dòng 31 : Dùng data.frame() để kết hợp hai vector var và nhan_xet thành một bảng dữ liệu có hai cột: Biến và Nhận_xét
Dòng 32: Sử dụng kable() để chuyển bảng dữ liệu thành một bảng HTML với tiêu đề là “Nhận xét thống kê các biến BIDV”.
Dòng 33: sử dụng kable_styling() để làm đẹp bảng HTML với các tùy chọn: không chiếm toàn bộ chiều rộng (full_width = F), căn giữa bảng trong trang (position = “center”), và áp dụng hiệu ứng Bootstrap như gạch sọc (striped), đổi màu khi rê chuột (hover), và làm bảng gọn hơn (condensed).
1. any(is.na(BIDV))
## [1] FALSE
Giải thích kỹ thuật: Kiểm tra xem dữ liệu BIDV có bất kỳ giá trị thiếu (NA) nào hay không
1. sum(is.na(BIDV))
## [1] 0
Giải thích kỹ thuật : Đếm tổng số giá trị thiếu (NA) trong toàn bộ bộ dữ liệu BIDV
1. colSums(is.na(BIDV))
## nam tong_tai_san
## 0 0
## tien_mat_vangbac_daquy tong_no_phai_tra
## 0 0
## von_chu_so_huu thu_nhap_lai_va_cac_khoan_tuong_tu
## 0 0
## chi_phi_lai_va_cac_chi_phi_tuong_tu thu_nhap_lai_thuan
## 0 0
## loi_nhuan_sau_thue lai_lo_thuan_hd_ngoai_hoi_va_vang
## 0 0
## tong_thu_nhap_hoat_dong thanh_toan_nv_ncc
## 0 0
## chi_thue_tndn tien_thu_thanh_ly_ts_co_dinh
## 0 0
Giải thích kỹ thuật : Đếm số lượng giá trị thiếu (NA) trong từng cột của dữ liệu BIDV
1. names(BIDV)[colSums(is.na(BIDV)) > 0]
## character(0)
Giải thích kỹ thuật: Liệt kê tên các cột trong BIDV có chứa giá trị thiếu (NA)
1. duplicated(BIDV)
## [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [13] FALSE FALSE FALSE
Giải thích kỹ thuật : Kiểm tra các dòng trùng lặp trong dữ liệu BIDV
1. sum(duplicated(BIDV))
## [1] 0
Giải thích kỹ thuật:Đếm tổng số dòng trùng lặp trong dữ liệu BIDV
1. BIDV[BIDV$tong_no_phai_tra < 0, ]
Giải thích kỹ thuật: Kiểm tra các giá trị âm bất hợp lý trong cột ‘tong_no_phai_tra’ của dữ liệu BIDV
1. BIDV[BIDV$thu_nhap_lai_va_cac_khoan_tuong_tu < 0, ]
Giải thích kỹ thuật : Kiểm tra các giá trị âm trong cột ‘thu_nhap_lai_va_cac_khoan_tuong_tu’ của dữ liệu BIDV
1. BIDV[BIDV$thu_nhap_lai_thuan < 0, c("nam", "thu_nhap_lai_thuan")]
Giải thích kỹ thuật: Kiểm tra các giá trị âm trong cột ‘thu_nhap_lai_thuan’ của dữ liệu BIDV
1. BIDV[BIDV$tong_thu_nhap_hoat_dong < 0, c("nam", "tong_thu_nhap_hoat_dong")]
Giải thích kỹ thuật : Kiểm tra các giá trị âm trong cột ‘tong_thu_nhap_hoat_dong’ của dữ liệu BIDV
1. BIDV$nam <- as.integer(BIDV$nam)
2. str(BIDV$nam)
## int [1:15] 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 ...
Giải thích kỹ thuật:
Dòng 1: chuyển nam thành dạng số
Dòng 2: xem cấu trúc biến nam
1. sapply(BIDV, class)
## nam tong_tai_san
## "integer" "numeric"
## tien_mat_vangbac_daquy tong_no_phai_tra
## "numeric" "numeric"
## von_chu_so_huu thu_nhap_lai_va_cac_khoan_tuong_tu
## "numeric" "numeric"
## chi_phi_lai_va_cac_chi_phi_tuong_tu thu_nhap_lai_thuan
## "numeric" "numeric"
## loi_nhuan_sau_thue lai_lo_thuan_hd_ngoai_hoi_va_vang
## "numeric" "numeric"
## tong_thu_nhap_hoat_dong thanh_toan_nv_ncc
## "numeric" "numeric"
## chi_thue_tndn tien_thu_thanh_ly_ts_co_dinh
## "numeric" "numeric"
Giải thích kỹ thuật: Kiểm tra kiểu dữ liệu của tất cả các cột trong dữ liệu BIDV, sapply() áp dụng hàm class() cho từng cột, trả về kiểu dữ liệu của từng biến
Nhận xét chi tiết: Sử dụng lệnh sapply(BIDV, class) cho thấy:
Biến nam hiện ở dạng integer, rất phù hợp để thực hiện các phân tích chuỗi thời gian hoặc vẽ biểu đồ theo năm.
Các biến còn lại gồm: tong_tai_san, tien_mat_vangbac_daquy, tong_no_phai_tra, von_chu_so_huu,thu_nhap_lai_va_cac_khoan_tuong_tu, chi_phi_lai_va_cac_chi_phi_tuong_tu,thu_nhap_lai_thuan, loi_nhuan_sau_thue, lai_lo_thuan_hd_ngoai_hoi_va_vang,tong_thu_nhap_hoat_dong, thanh_toan_nv_ncc, chi_thue_tndn, và tien_thu_thanh_ly_ts_co_dinh đều có kiểu numeric, đảm bảo có thể sử dụng cho các phép toán tài chính, ước lượng mô hình, và vẽ biểu đồ.
1. head(BIDV$von_chu_so_huu, 5)
## [1] 2.421973e+13 2.439045e+13 2.649445e+13 3.203998e+13 3.360620e+13
1. tail(BIDV$tong_no_phai_tra, 8)
## [1] 1.153450e+15 1.258377e+15 1.412304e+15 1.437039e+15 1.675367e+15
## [6] 2.016558e+15 2.178002e+15 2.615881e+15
1. BIDV[BIDV$tien_mat_vangbac_daquy > 4e+12, ]
1. head(BIDV[, c("nam", "tong_thu_nhap_hoat_dong")], 7)
1. tail(BIDV[, c("nam", "loi_nhuan_sau_thue")], 3)
1. BIDV[(BIDV$von_chu_so_huu / BIDV$tong_tai_san) > 0.07, ]
1. head(BIDV$tien_thu_thanh_ly_ts_co_dinh, 4)
## [1] 5.992e+09 2.910e+09 3.323e+09 4.079e+09
1. tail(BIDV$chi_thue_tndn, 2)
## [1] -4.551443e+12 -6.884931e+12
1. BIDV[BIDV$thu_nhap_lai_thuan > 0, ]
1. head(BIDV[, c("nam", "tong_tai_san", "von_chu_so_huu")], 6)
Giải thích kỹ thuật
Dòng 1:Lấy 5 giá trị đầu tiên của cột von_chu_so_huu từ bảng BIDV.
Dòng 2: Lấy 8 giá trị cuối cùng của cột tong_no_phai_tra từ bảng BIDV.
Dòng 3:Lọc ra các dòng trong bảng BIDV có giá trị của cột tien_mat_vangbac_daquy lớn hơn 4 tỷ (4e+12).
Dòng 4:Lấy 7 dòng đầu tiên của bảng BIDV chỉ với hai cột nam và tong_thu_nhap_hoat_dong.
Dòng 5:Lấy 3 dòng cuối cùng của bảng BIDV chỉ với hai cột nam và loi_nhuan_sau_thue.
Dòng 6:Lọc ra các dòng trong bảng BIDV có tỷ lệ von_chu_so_huu trên tong_tai_san lớn hơn 7%.
Dòng 7:Lấy 4 giá trị đầu tiên của cột tien_thu_thanh_ly_ts_co_dinh từ bảng BIDV.
Dòng 8:Lấy 2 giá trị cuối cùng của cột chi_thue_tndn từ bảng BIDV.
Dòng 9:Lọc ra các dòng trong bảng BIDV có giá trị của cột thu_nhap_lai_thuan lớn hơn 0.
Dòng 10:Lấy 6 dòng đầu tiên của bảng BIDV chỉ với ba cột nam, tong_tai_san, và von_chu_so_huu.
1. BIDV[nrow(BIDV), "tong_tai_san"]
1. BIDV[1, "von_chu_so_huu"]
1. BIDV[7, "loi_nhuan_sau_thue"]
1. BIDV[3, "nam"]
1. BIDV$tong_no_phai_tra[9]
## [1] 1.258377e+15
1. median_tts <- median(BIDV$tong_tai_san)
2. BIDV[which.min(abs(BIDV$tong_tai_san - median_tts)), "nam"]
1. BIDV[which.max(BIDV$tien_mat_vangbac_daquy), "nam"]
1. min(BIDV$thu_nhap_lai_thuan)
## [1] 9.191386e+12
1. mean(BIDV$loi_nhuan_sau_thue)
## [1] 9.207143e+12
1. BIDV[which.max(BIDV$chi_thue_tndn / BIDV$tong_thu_nhap_hoat_dong), "nam"]
1. BIDV$lai_lo_thuan_hd_ngoai_hoi_va_vang[BIDV$lai_lo_thuan_hd_ngoai_hoi_va_vang > 1e+12]
## [1] 1.039685e+12 1.494696e+12 1.732324e+12 1.896154e+12 3.136613e+12
## [6] 4.707371e+12 5.361499e+12
1. BIDV[which.max(BIDV$tien_thu_thanh_ly_ts_co_dinh), ]
1. BIDV[which.max(BIDV$tien_mat_vangbac_daquy / BIDV$tong_tai_san), ]
1. BIDV[which.min(BIDV$thanh_toan_nv_ncc / BIDV$tong_tai_san), ]
Giải thích kỹ thuật
Dòng 1:Lấy giá trị của cột tong_tai_san ở dòng cuối cùng của bảng BIDV, sử dụng nrow(BIDV) để xác định số dòng cuối cùng.
Dòng 2: Lấy giá trị của cột von_chu_so_huu ở dòng đầu tiên của bảng BIDV.
Dòng 3:Lấy giá trị của cột loi_nhuan_sau_thue ở dòng thứ 7 của bảng BIDV.
Dòng 4:Lấy giá trị của cột nam ở dòng thứ 3 của bảng BIDV.
Dòng 5: Lấy giá trị của cột tong_no_phai_tra ở dòng thứ 9 của bảng BIDV.
Dòng 6:Tính giá trị trung vị (median) của cột tong_tai_san trong bảng BIDV và lưu kết quả vào biến median_tts.
Dòng 7:Lấy giá trị của cột nam ở dòng có giá trị tong_tai_san gần với giá trị trung vị (median_tts), bằng cách tìm chỉ số dòng có sự chênh lệch nhỏ nhất giữa giá trị của tong_tai_san và trung vị.
Dòng 8:Lấy giá trị của cột nam ở dòng có giá trị tien_mat_vangbac_daquy lớn nhất.
Dòng 9:Lấy giá trị nhỏ nhất trong cột thu_nhap_lai_thuan của bảng BIDV.
Dòng 10:Tính giá trị trung bình của cột loi_nhuan_sau_thue trong bảng BIDV.
Dòng 11:Lấy giá trị của cột nam ở dòng có tỷ lệ chi_thue_tndn trên tong_thu_nhap_hoat_dong lớn nhất.
Dòng 12:Lọc ra các giá trị trong cột lai_lo_thuan_hd_ngoai_hoi_va_vang có giá trị lớn hơn 1 tỷ (1e+12).
Dòng 13:Lấy toàn bộ dòng có giá trị tien_thu_thanh_ly_ts_co_dinh lớn nhất.
Dòng 14:Lấy toàn bộ dòng có tỷ lệ tien_mat_vangbac_daquy trên tong_tai_san lớn nhất.
Dòng 15:Lấy toàn bộ dòng có tỷ lệ thanh_toan_nv_ncc trên tong_tai_san nhỏ nhất.
1. BIDV$tong_tai_san[nrow(BIDV)] <- BIDV$tong_tai_san[nrow(BIDV)] * 0.93
2. BIDV$von_chu_so_huu[2] <- BIDV$von_chu_so_huu[2] * 1.05
3. BIDV$tien_mat_vangbac_daquy[3] <- BIDV$tien_mat_vangbac_daquy[3] * 0.99
4. BIDV$tong_no_phai_tra[1] <- BIDV$tong_no_phai_tra[1] * 1.08
5. BIDV$thu_nhap_lai_va_cac_khoan_tuong_tu[BIDV$nam == "2021"] <- BIDV$thu_nhap_lai_va_cac_khoan_tuong_tu[BIDV$nam == "2021"] * 1.02
6. BIDV$NIM <- BIDV$thu_nhap_lai_thuan / BIDV$tong_tai_san
7. BIDV$NPM <- BIDV$loi_nhuan_sau_thue / BIDV$tong_thu_nhap_hoat_dong
8. BIDV$chi_phi_lai_va_cac_chi_phi_tuong_tu[1] <- BIDV$chi_phi_lai_va_cac_chi_phi_tuong_tu[1] * 0.98
9. BIDV$chi_thue_tndn[nrow(BIDV)] <- BIDV$chi_thue_tndn[nrow(BIDV)] * 1.05
10. BIDV$ty_le_tienmat_ts <- BIDV$tien_mat_vangbac_daquy / BIDV$tong_tai_san
11. BIDV$hieuqua_NIM <- ifelse(BIDV$NIM > 0.025, "Tốt",
12. ifelse(BIDV$NIM >= 0.015 & BIDV$NIM <= 0.025, "Trung bình", "Thấp"))
13. BIDV$hieuqua_NPM <- ifelse(BIDV$NPM > 0.20, "Rất tốt",
14. ifelse(BIDV$NPM >= 0.10 & BIDV$NPM <= 0.20, "Tốt", "Thấp"))
15. BIDV$index <- seq_along(BIDV$nam)
16. BIDV$index <- NULL
Giải thích kỹ thuật:
Dòng 1:Điều chỉnh giá trị của cột tong_tai_san ở dòng cuối cùng bằng cách giảm nó đi 7% (nhân với 0.93).
Dòng 2: Tăng giá trị của cột von_chu_so_huu ở dòng thứ 2 lên 5% (nhân với 1.05).
Dòng 3:Giảm giá trị của cột tien_mat_vangbac_daquy ở dòng thứ 3 xuống 1% (nhân với 0.99).
Dòng 4: Tăng giá trị của cột tong_no_phai_tra ở dòng đầu tiên lên 8% (nhân với 1.08).
Dòng 5: Tăng giá trị của cột thu_nhap_lai_va_cac_khoan_tuong_tu cho năm 2021 lên 2% (nhân với 1.02).
Dòng 6: BIDV\(NIM <- BIDV\)thu_nhap_lai_thuan / BIDV$tong_tai_san Tạo cột mới NIM (Biên lợi nhuận lãi ròng) bằng cách chia thu_nhap_lai_thuan cho tong_tai_san.
Dòng 7: Tạo cột mới NPM (Biên lợi nhuận sau thuế) bằng cách chia loi_nhuan_sau_thue cho tong_thu_nhap_hoat_dong.
Dòng 8:Giảm giá trị của cột chi_phi_lai_va_cac_chi_phi_tuong_tu ở dòng đầu tiên đi 2% (nhân với 0.98).
Dòng 9: Tăng giá trị của cột chi_thue_tndn ở dòng cuối cùng lên 5% (nhân với 1.05).
Dòng 10:Tạo cột mới ty_le_tienmat_ts tính tỷ lệ tiền mặt, vàng bạc, đá quý trên tổng tài sản (tien_mat_vangbac_daquy / tong_tai_san).
Dòng 11: Tạo cột hieuqua_NIM để phân loại hiệu quả NIM:“Tốt” nếu NIM > 0.025,“Trung bình” nếu NIM từ 0.015 đến 0.025,“Thấp” nếu NIM < 0.015.
Dòng 12:Tạo cột hieuqua_NPM để phân loại hiệu quả NPM:“Rất tốt” nếu NPM > 0.20,“Tốt” nếu NPM từ 0.10 đến 0.20,“Thấp” nếu NPM < 0.10.
Dòng 13:Tạo cột index, lưu trữ số thứ tự cho từng dòng trong bảng dữ liệu BIDV theo cột nam.
Dòng 14:Xóa cột index khỏi bảng BIDV sau khi không còn cần thiết nữa.
1. d1 <- subset(BIDV,
2. nam >= 2015 & nam <= 2020 &
3. NIM > 0.02)
4. head(d1)
Giải thích kỹ thuật:
Dòng 1: Hàm subset() được sử dụng để lọc dữ liệu theo điều kiện cụ thể.
Dòng 2–3: Điều kiện lọc: nam trong khoảng từ 2015 đến 2020 và NIM lớn hơn 2% (0.02).
Dòng : Hàm head(d1) hiển thị 6 dòng đầu tiên
1. d2 <- subset(BIDV,
2. NPM > 0.15 &
3. loi_nhuan_sau_thue > 0)
4. head(d2)
Giải thích kỹ thuật : thực hiện tương tự giống phân tổ Giai đoạn 2015–2020 với NIM > 2%
1. d3 <- subset(BIDV,
2. NIM > 0.03 &
3. thu_nhap_lai_va_cac_khoan_tuong_tu > 0 )
4. head(d3)
Giải thích kỹ thuật : thực hiện tương tự giống phân tổ Giai đoạn 2015–2020 với NIM > 2%
1. d4 <- subset(BIDV,
2. thanh_toan_nv_ncc < 0 &
3. loi_nhuan_sau_thue > 0 &
4. chi_thue_tndn > -1e12)
5. head(d4)
Giải thích kỹ thuật : thực hiện tương tự giống phân tổ Giai đoạn 2015–2020 với NIM > 2%
1. d5 <- subset(BIDV,
2. tong_tai_san >= 1.5e15 &
3. NIM >= 0.024)
4. head(d5)
Giải thích kỹ thuật : thực hiện tương tự giống phân tổ Giai đoạn 2015–2020 với NIM > 2%
1. d6 <- subset(
2. BIDV,
3. hieuqua_NPM == "Rất tốt" &
4. loi_nhuan_sau_thue >= 3.2e+12)
5. head(d6)
Giải thích kỹ thuật : thực hiện tương tự giống phân tổ Giai đoạn 2015–2020 với NIM > 2%
1. tk1 <- BIDV %>%
2. summarise(
3. Solieu = n(),
4. Trungbinh = mean(loi_nhuan_sau_thue, na.rm = TRUE),
5. max = max(loi_nhuan_sau_thue, na.rm = TRUE),
6. min = min(loi_nhuan_sau_thue, na.rm = TRUE),
7. Trungvi = median(loi_nhuan_sau_thue, na.rm = TRUE),
8. Dolechchuan = sd(loi_nhuan_sau_thue, na.rm = TRUE),
9. Q1 = quantile(loi_nhuan_sau_thue, 0.25, na.rm = TRUE),
10. Q3 = quantile(loi_nhuan_sau_thue, 0.75, na.rm = TRUE))
11. head(tk1)
Giải thích kỹ thuật
Dòng 1: Dùng toán tử %>% để chuyển dữ liệu từ bảng BIDV vào hàm summarise() để tính các chỉ số thống kê cho cột loi_nhuan_sau_thue.
Dòng 2–9: Tính các chỉ số thống kê mô tả cho cột loi_nhuan_sau_thue, bao gồm số lượng bản ghi (n()), giá trị trung bình (mean()), giá trị lớn nhất (max()), giá trị nhỏ nhất (min()), trung vị (median()), độ lệch chuẩn (sd()), tứ phân vị thứ nhất (quantile(…, 0.25)) và tứ phân vị thứ ba (quantile(…, 0.75)), bỏ qua các giá trị NA.
Dòng 10: head(tk1) hiển thị 6 dòng đầu tiên
Dựa vào bảng thống kê trên:
Tổng số năm quan sát: 15 năm.
Giá trị trung bình của lợi nhuận sau thuế: 9.207143 × 10¹² đồng.
Trung vị: 6.945586 × 10¹² đồng.
Giá trị nhỏ nhất và lớn nhất: từ 2.571943 × 10¹² đồng đến 2.560404 × 10¹³ đồng, cho thấy khoảng cách rất lớn, phản ánh sự chênh lệch đáng kể về lợi nhuận giữa các năm.
Độ lệch chuẩn: 7.080721 × 10¹² đồng, khá cao so với giá trị trung bình, chứng tỏ lợi nhuận sau thuế của ngân hàng biến động mạnh qua thời gian.
Q1 và Q3: lần lượt là 7.080721 × 10¹² đồng và 7.080721 × 10¹² đồng (thiếu Q3 trong dữ liệu, có thể cần bổ sung), tuy nhiên giá trị hiện có cho thấy lợi nhuận tập trung quanh mức trung bình, phản ánh hiệu quả hoạt động tương đối ổn định trong giai đoạn phân tích.
1. tk2 <- BIDV %>%
2. summarise(
3. Solieu = n(),
4. Trungbinh = mean(thu_nhap_lai_thuan, na.rm = TRUE),
5. max = max(thu_nhap_lai_thuan, na.rm = TRUE),
6. min = min(thu_nhap_lai_thuan, na.rm = TRUE),
7. Trungvi = median(thu_nhap_lai_thuan, na.rm = TRUE),
8. Dolechchuan = sd(thu_nhap_lai_thuan, na.rm = TRUE),
9. Q1 = quantile(thu_nhap_lai_thuan, 0.25, na.rm = TRUE),
10. Q3 = quantile(thu_nhap_lai_thuan, 0.75, na.rm = TRUE))
11. head(tk2)
Giải thích kỹ thuật: thực hiện tương tự giống Thống kê mô tả biến loi_nhuan_sau_thue
Dựa vào bảng thống kê trên:
Tổng số năm quan sát: 15 năm.
Giá trị trung bình của thu nhập lãi thuần: 3.065420 × 10¹³ đồng.
Trung vị: 3.095533 × 10¹³ đồng.
Giá trị nhỏ nhất và lớn nhất: từ 9.191386 × 10¹² đồng đến 5.800758 × 10¹³ đồng, cho thấy khoảng cách khá lớn, phản ánh sự khác biệt đáng kể về khả năng sinh lãi thuần giữa các năm.
Độ lệch chuẩn: 1.739830 × 10¹³ đồng, ở mức cao so với trung bình, chứng tỏ thu nhập lãi thuần của ngân hàng biến động mạnh qua các năm.
Q1 và Q3: lần lượt là 1.739830 × 10¹³ đồng và 1.584445 × 10¹³ đồng (giá trị Q3 có thể cần kiểm tra lại do dữ liệu chưa khớp), tuy nhiên nhìn chung các giá trị cho thấy phần lớn các năm có thu nhập lãi thuần ở mức trung bình – khá, phản ánh hiệu quả sinh lãi ổn định của ngân hàng qua thời gian.
1. tk3 <- BIDV %>%
2. group_by(nam, hieuqua_NPM) %>%
3. summarise(
4. Sogiaodich = n(),
5. Trungbinh = mean(tong_thu_nhap_hoat_dong, na.rm = TRUE),
6. Trungvi = median(tong_thu_nhap_hoat_dong, na.rm = TRUE),
7. Max = max(tong_thu_nhap_hoat_dong, na.rm = TRUE),
8. Min = min(tong_thu_nhap_hoat_dong, na.rm = TRUE),
9. Q1 = quantile(tong_thu_nhap_hoat_dong, 0.25, na.rm = TRUE),
10. Q3 = quantile(tong_thu_nhap_hoat_dong, 0.75, na.rm = TRUE)) %>%
11. arrange(nam, hieuqua_NPM)
12. head(tk3)
Giải thích kỹ thuật: thực hiện tương tự giống Thống kê mô tả biến loi_nhuan_sau_thue
Dựa vào bảng thống kê trên:
Tổng số năm quan sát: 15 năm, phản ánh liên tục quá trình thay đổi hiệu quả hoạt động của ngân hàng.
Nhóm “Rất tốt” gồm các năm 2010–2016, 2022–2024 (tổng 9 năm, chiếm 60% bộ dữ liệu). Trong giai đoạn này, tổng thu nhập hoạt động tăng mạnh từ 1,15 × 10¹³ lên 8,11 × 10¹³ đồng, cho thấy hiệu suất sinh lời vượt trội, khả năng kiểm soát chi phí tốt và duy trì biên lợi nhuận cao.
Nhóm “Tốt” gồm các năm 2017–2021 (6 năm, chiếm 40% bộ dữ liệu). Thu nhập hoạt động tiếp tục tăng từ 3,90 × 10¹³ đến 6,25 × 10¹³ đồng, phản ánh giai đoạn tăng trưởng ổn định, dù biên lợi nhuận có phần giảm nhẹ do chi phí và quy mô mở rộng nhanh.
Giá trị nhỏ nhất – lớn nhất: từ 1,15 × 10¹³ đến 8,11 × 10¹³ đồng, cho thấy biên độ tăng trưởng mạnh và năng lực sinh lời ngày càng cao.
→ Nhìn chung, ngân hàng duy trì hiệu quả NPM ở mức tốt trở lên trong toàn bộ giai đoạn, với xu hướng tăng trưởng bền vững và hiệu suất tài chính ngày càng được cải thiện.
1. tk4 <- BIDV %>%
2. group_by(hieuqua_NIM, hieuqua_NPM) %>%
3. summarise(
4. Sogiaodich = n(),
5. Trungbinh = mean(loi_nhuan_sau_thue, na.rm = TRUE),
6. Trungvi = median(loi_nhuan_sau_thue, na.rm = TRUE),
7. Max = max(loi_nhuan_sau_thue, na.rm = TRUE),
8. Min = min(loi_nhuan_sau_thue, na.rm = TRUE),
9. Dolechchuan= sd(loi_nhuan_sau_thue, na.rm = TRUE),
10. Q1 = quantile(loi_nhuan_sau_thue, 0.25, na.rm = TRUE),
11. Q3 = quantile(loi_nhuan_sau_thue, 0.75, na.rm = TRUE)) %>%
12. arrange(hieuqua_NIM, hieuqua_NPM)
13. head(tk4)
Giải thích kỹ thuật: thực hiện tương tự giống Thống kê mô tả biến loi_nhuan_sau_thue
Dựa vào bảng thống kê trên:
Tổng cộng 4 nhóm kết hợp giữa hiệu quả NIM và NPM, phản ánh rõ mối quan hệ giữa biên lãi và hiệu suất sinh lời ròng của ngân hàng.
Nhóm “Trung bình – Rất tốt” có 5 quan sát, lợi nhuận sau thuế trung bình đạt 1,25 × 10¹³ đồng, cao nhất trong các nhóm, cho thấy dù biên lãi ở mức trung bình nhưng khả năng kiểm soát chi phí và sinh lời ròng rất tốt.
Nhóm “Trung bình – Tốt” gồm 2 quan sát, lợi nhuận trung bình 7,89 × 10¹² đồng, phản ánh hiệu quả ổn định nhưng thấp hơn nhóm “Rất tốt” do biên lãi và quy mô lợi nhuận cùng ở mức vừa phải.
Nhóm “Tốt – Rất tốt” có 5 quan sát, lợi nhuận trung bình 6,87 × 10¹² đồng, cho thấy ngân hàng đạt hiệu suất sinh lời cao khi đồng thời duy trì biên lãi tốt và kiểm soát chi phí hiệu quả.
Nhóm “Tốt – Tốt” gồm 3 quan sát, lợi nhuận trung bình 8,42 × 10¹² đồng, thể hiện hiệu quả tài chính cân bằng và ổn định, với mức biến động thấp.
→ Nhìn chung, các nhóm có NPM “Rất tốt” đạt lợi nhuận cao hơn rõ rệt, dù NIM chỉ ở mức “Trung bình” hoặc “Tốt”, cho thấy khả năng quản lý chi phí và tối ưu lợi nhuận ròng là yếu tố then chốt giúp ngân hàng duy trì hiệu quả tài chính vượt trội.
1. plot(BIDV$tong_tai_san,
2. BIDV$loi_nhuan_sau_thue,
3. pch = 19,col = "blue",cex = 1.2,
4. xlab = "Tổng tài sản (VND)",ylab = "LN sau thuế (VND)",
5. main = "Scatter Plot: Tài sản vs LNST")
Giải thích kỹ thuật
Dòng 1-2: Sử dụng hàm plot() để vẽ biểu đồ phân tán (scatter plot), hình dạng điểm là hình tròn đặc
Dòng 3: pch = 19: Đặt kiểu điểm là hình tròn đặc, col = “blue”: Màu điểm là xanh dương, cex = 1.2: Kích thước điểm lớn hơn 20% so với mặc định.
Dòng 4: Đặt nhãn cho trục X và trục Y và nhãn biểu đồ
1. plot(BIDV$nam,BIDV$NIM,
2. type = "b",col = "red", lwd = 2,pch = 17,
3. xlab = "Năm",ylab = "NIM",main = "Line Plot: NIM theo năm")
Giải thích kỹ thuật:
Dòng 1-2: Sử dụng hàm plot() để vẽ biểu đồ đường (line plot) cho biến nam và NIM
Dòng 3: với các điểm vẽ là hình tam giác (pch = 17), màu đường là đỏ (col = “red”), độ dày đường là 2 (lwd = 2), kết hợp giữa đường và điểm (type = “b”).
Dòng 4: Đặt nhãn cho trục X là “Năm”, trục Y là “NIM” và tiêu đề biểu đồ là “Line Plot: NIM theo năm”.
1. y_max <- max(BIDV$tien_mat_vangbac_daquy) * 1.15
2. bp <- barplot(BIDV$tien_mat_vangbac_daquy,
3. names.arg = BIDV$nam, col = "orange",
4. space = 1.1,width = 0.7,
5. ylim = c(0, y_max),main = "Bar Plot: Tiền mặt, vàng bạc, đá quý",
6. xlab = "Năm",ylab = "Tổng giá trị (VND)")
7. grid()
8. text(bp, BIDV$tien_mat_vangbac_daquy,
9. labels = formatC(BIDV$tien_mat_vangbac_daquy, format = "e", digits = 2),
10. pos = 3, offset = 0.2, cex = 0.55, font = 2)
Giải thích kỹ thuật
Dòng 1:Tính giá trị lớn nhất trong cột tien_mat_vangbac_daquy của bảng BIDV và nhân với 1.15 để tạo giới hạn tối đa cho trục Y của biểu đồ.
Dòng 2-7:Vẽ biểu đồ cột với các tham số:Giá trị của cột tien_mat_vangbac_daquy cho chiều cao các cột
Dòng 3: đặt tên các cột theo giá trị của năm (nam),col = “orange”: Màu sắc của các cột là cam
Dòng 4 :space = 1.1: Khoảng cách giữa các cột, width = 0.7: Độ rộng của các cột.
Dòng 5: ylim = c(0, y_max): Giới hạn trục Y từ 0 đến giá trị tối đa y_max, main = “Bar Plot: Tiền mặt, vàng bạc, đá quý”: Tiêu đề của biểu đồ.
Dòng 6: xlab = “Năm”: Nhãn trục X là “Năm”, ylab = “Tổng giá trị (VND)”: Nhãn trục Y là “Tổng giá trị (VND)”.
Dòng 7: grid() Thêm lưới vào biểu đồ để làm cho biểu đồ dễ đọc hơn.
Dòng 8: Thêm nhãn số vào các cột của biểu đồ:
Dòng 9: Chuyển giá trị trong tien_mat_vangbac_daquy thành định dạng khoa học với 2 chữ số thập phân.
Dòng 10:pos = 3: Đặt nhãn phía trên các cột, offset = 0.2: Đẩy nhãn lên phía trên một chút để tránh trùng với các cột, cex = 0.55: Kích thước chữ là 55% so với mặc định, font = 2: Làm chữ đậm (bold).
-Nhận xét : Biểu đồ cho thấy giá trị tiền mặt, vàng bạc, đá quý của BIDV tăng mạnh và ổn định trong giai đoạn 2010–2018, đặc biệt năm 2018 đạt mức cao đột biến (~1,41×10¹³ VND). Giai đoạn 2019–2022 duy trì quanh mức cao, phản ánh chính sách dự trữ tiền mặt và tài sản có tính thanh khoản cao. Tuy nhiên, từ 2023 giá trị này giảm nhẹ, cho thấy xu hướng tối ưu hóa tài sản ngắn hạn hoặc chuyển dịch cơ cấu đầu tư sang tài sản sinh lời cao hơn.
1. boxplot(BIDV$thu_nhap_lai_thuan,
2. col = "green",border = "darkgreen",
3. horizontal = TRUE, notch = TRUE,
4. main = "Box Plot: Thu nhập lãi thuần",
5. xlab = "Thu nhập lãi thuần (VND)")
6. grid()
Giải thích kỹ thuật
Dòng 1: Sử dụng hàm boxplot() để vẽ biểu đồ hộp (box plot) cho biến thu_nhap_lai_thuan.
Dòng 2: Đặt màu cho các hộp là xanh lá cây (col = “green”), viền hộp là xanh đậm (border = “darkgreen”),
Dòng 3: vẽ hộp theo chiều ngang (horizontal = TRUE), và tạo notch (lỗ hổng) trên biểu đồ (notch = TRUE).
Dòng 4: Đặt tiêu đề biểu đồ và nhãn trục X
Dòng 5: Thêm lưới vào biểu đồ bằng hàm grid().
1. nim_counts <- table(BIDV$hieuqua_NIM)
2. percents <- round(100 * nim_counts / sum(nim_counts), 1)
3. labels_pie <- paste0(names(nim_counts), "\n(", percents, "%)")
4. pie(nim_counts,
5. labels = labels_pie,
6. col = c("forestgreen", "gold", "tomato"),
7. main = "Pie Chart: Phân loại NIM",clockwise = TRUE, cex = 1.2,init.angle = 90)
Giải thích kỹ thuật
Dòng 1-2: Sử dụng hàm table() để đếm số lượng các giá trị trong cột hieuqua_NIM của bảng BIDV, và tính tỷ lệ phần trăm của mỗi giá trị.
Dòng 3: Tạo nhãn cho biểu đồ tròn (labels_pie) bằng cách kết hợp tên các nhóm và tỷ lệ phần trăm.
Dòng 4: Sử dụng hàm pie() để vẽ biểu đồ tròn, với các nhãn được tạo từ labels_pie, màu sắc cho các phần của biểu đồ, thêm tiêu đề, xoay biểu đồ theo chiều kim đồng hồ (clockwise = TRUE) và điều chỉnh kích thước chữ cho nhãn là 1.2 (cex = 1.2), bắt đầu góc từ 90 độ (init.angle = 90).
1. hist(BIDV$lai_lo_thuan_hd_ngoai_hoi_va_vang,
2. col = "orchid",breaks = 6,
3. border = "gray30",xlab = "Lãi/lỗ thuần ngoại hối & vàng (VND)",
4. ylab = "Tần suất",
5. main = "Histogram: Phân phối lãi/lỗ hoạt động ngoại hối & vàng BIDV",
6. freq = TRUE)
7. rug(BIDV$lai_lo_thuan_hd_ngoai_hoi_va_vang, col = "navy")
Giải thích kỹ thuật
Dòng 1: Vẽ biểu đồ tần suất (histogram) cho cột lai_lo_thuan_hd_ngoai_hoi_va_vang từ bảng BIDV
Dòng 2: col = “orchid”: Màu của các cột,breaks = 6: Chia biểu đồ thành 6 nhóm.
Dòng 3: Màu viền của các cột là màu xám đậm, nhãn cột x
Dòng 4: nhãn cột y
Dòng 5: nhãn biểu đồ
Dòng 7: vẽ một dãi dưới trục x để hiển thị các giá trị
1. par(mfrow = c(1,2))
2. hist(BIDV$tien_thu_thanh_ly_ts_co_dinh,
3. col = "#40E",breaks = 5,
4. border = "black", main = "Histogram: Tiền thu thanh lý TS",
5. xlab = "Tiền thu (VND)", ylab = "Tần suất")
6. rug(BIDV$tien_thu_thanh_ly_ts_co_dinh, col = "#40E")
7. hist(BIDV$chi_thue_tndn,
8. col = "#FF10F0",breaks = 5,
9. border = "black",main = "Histogram: Chi phí thuế TNDN",
10. xlab = "Chi phí thuế (VND)", ylab = "Tần suất")
11. rug(BIDV$chi_thue_tndn, col = "#FF10F0")
r 1. par(mfrow = c(1,1))
Giải thích kỹ thuật: thực hiện tương tự giống Histogram phân phối lãi/lỗ thuần hoạt động ngoại hối & vàng
Dòng 11: chỉ hiển thị 1 biểu đồ trong một cửa sổ
1. values_stack_paytax <- rbind(
2. abs(BIDV$thanh_toan_nv_ncc),
3. abs(BIDV$chi_thue_tndn))
4. barplot(values_stack_paytax,
5. beside = FALSE,
6. names.arg = BIDV$nam,
7. col = c("#39F", "#FF1"),
8. main = "Cột chồng 2 lớp: Thanh toán NV-NCC & Chi thuế TNDN",
9. xlab = "Năm",
10. ylab = "Giá trị (VND)")
11. legend("topright", legend = c("Thanh toán NV-NCC", "Chi phí thuế TNDN"),
12. fill = c("#39F", "#FF1"), bty = "n", cex = 0.9)
Giải thích kỹ thuật
Dòng 1: Kết hợp hai cột thanh_toan_nv_ncc (chi trả cho nhân viên và nhà cung cấp) và chi_thue_tndn (chi phí thuế thu nhập doanh nghiệp) thành một bảng dữ liệu mới values_stack_paytax, chuyển cả hai cột này thành giá trị tuyệt đối
Dòng 2: Vẽ biểu đồ cột chồng (stacked bar plot) với các thông số
Dòng 11: Thêm chú giải (legend) vào góc trên bên phải của biểu đồ, với các nhãn, bty = “n”: Loại bỏ viền của chú giải, cex = 0.9: Đặt kích thước chữ cho chú giải là 0.9 lần kích thước mặc định.
1. values_triple <- rbind(BIDV$von_chu_so_huu, BIDV$tong_no_phai_tra, BIDV$tong_tai_san)
2. barplot(values_triple,
3. beside = TRUE,
4. names.arg = BIDV$nam,
5. col = c("blue", "red", "green"),
6. main = "Biểu đồ cột ba giá trị:\n Vốn chủ sở hữu, Tổng nợ phải trả, Tổng tài sản BIDV ",
7. xlab = "Năm", ylab = "Giá trị (VND)")
8. legend("topleft", legend = c("Vốn chủ sở hữu", "Tổng nợ phải trả", "Tổng tài sản"), fill = c("blue", "red", "green"))
Giải thích kỹ thuật :
Dòng 1: Dùng hàm rbind() để kết hợp ba cột
Dòng 2: Vẽ biểu đồ cột cho ba giá trị và tương tự các chỉ tiêu đã đề cập ở các biểu đồ trước đó
Dòng 8: Thêm chú giải vào góc trên bên trái
1. boxplot(BIDV$thu_nhap_lai_thuan, BIDV$loi_nhuan_sau_thue, BIDV$tong_thu_nhap_hoat_dong,
2. names = c("Thu nhập lãi thuần", "LN sau thuế", "Tổng thu nhập HĐ"),
3. col = c("orange", "skyblue", "pink"),
4. main = "Boxplot ba biến: 3 chỉ tiêu lợi nhuận BIDV",
5. ylab = "Giá trị (VND)")
Giải thích kỹ thuật:
Dòng 1: Vẽ biểu đồ hộp (box plot) cho ba biến và tương tự các chỉ tiêu đã đề cập ở các biểu đồ trước đó
1. ggplot(BIDV, aes(x = nam, y = tong_tai_san)) +
2. geom_line(color = "#39FF14", size = 1.5) +
3. geom_point(color = "#39FF14", size = 3) +
4. geom_text(aes(label = formatC(tong_tai_san, format = "e", digits = 2)),
5. vjust = -1, color = "black", size = 2.5) +
6. labs(title = "Đường đơn: Tổng tài sản theo năm", x = "Năm", y = "Tổng tài sản (VND)") +
7. theme_minimal()
Giải thích kỹ thuật
Dòng 1:Sử dụng ggplot() để tạo biểu đồ với dữ liệu
Dòng 2: Vẽ đường nối các điểm với màu sắc có độ dày 1.5
Dòng 3: Vẽ các điểm tại các giá trị dữ liệu và kích thước điểm là 3.
Dòng 4: Thêm nhãn cho các điểm,hiển thị giá trị tong_tai_san dưới dạng số khoa học (format = “e”), với 2 chữ số thập phân (digits = 2),vị trí nhãn hơi lệch lên .
Dòng 6: giao diện tối giản cho biểu đồ
###. Biểu đồ đường: Tổng nợ phải trả từng năm
1. ggplot(BIDV, aes(x = nam, y = tong_no_phai_tra)) +
2. geom_line(color = "#FF10F0", size = 1.5) +
3. geom_point(color = "#FF10F0", size = 3) +
4. geom_text(aes(label = formatC(tong_no_phai_tra, format = "e", digits = 2)),
5. vjust = -1, color = "darkred", size = 2.5) +
6. labs(title = "Đường đơn: Tổng nợ phải trả theo năm", x = "Năm", y = "Tổng nợ phải trả (VND)") +
7. theme_minimal()
Giải thích kỹ thuật : thực hiện tương tự giống với Biểu đồ đường: Tổng tài sản từng năm
1. df_triple_mean <- BIDV[, c("nam", "thu_nhap_lai_thuan", "tong_thu_nhap_hoat_dong", "loi_nhuan_sau_thue")]
2. df_triple_mean_long <- pivot_longer(df_triple_mean,
3. cols = c("thu_nhap_lai_thuan", "tong_thu_nhap_hoat_dong", "loi_nhuan_sau_thue"),
4. names_to = "variable", values_to = "value")
5. ggplot(df_triple_mean_long, aes(x = factor(nam), y = value, fill = variable)) +
6. geom_bar(stat = "identity", position = position_dodge(width = 0.7), width = 0.55) +
7. geom_text(aes(label = signif(value, 2)), color = "#00F", size = 1.6,
8. fontface = "bold", position = position_dodge(width = 0.7), vjust = -0.55) +
9. scale_fill_manual(
10. values = c("#FFD700", "#39FF14", "#FF1463"),
11. labels = c("Lợi nhuận sau thuế", "Thu nhập lãi thuần", "Tổng thu nhập hoạt động")
12. ) +labs(title = "Biểu đồ so sánh Thu nhập lãi thuần, Tổng thu nhập hoạt động, Lợi nhuận sau thuế",
13. x = "Năm", y = "Giá trị (VND)", fill = "Chỉ tiêu") +
14. theme_minimal() +
15. theme(axis.text.x = element_text(color = "#FF00EA", size = 9, angle = 20))
Giải thích kỹ thuật:
Dòng 1: tạo bảng con df_triple_mean
Dòng 2-3: Chuyển dữ liệu từ dạng rộng sang dạng dàiác cột thu_nhap_lai_thuan, tong_thu_nhap_hoat_dong, và loi_nhuan_sau_thue được chuyển thành hai cột mới: variable: Chứa tên cột gốc (các chỉ tiêu),value: Chứa giá trị của các chỉ tiêu.
Dòng 4-5: vẽ biểu đồ bar theo các chỉ tiêu tương tự các biểu đồ trên đã đề cập
Dòng 6: vẽ biểu đồ cột, cho dùng giá trị thực tế của cột value cho chiều cao các cột, đặt các cột cạnh nhau
Dòng 7: Thêm các nhãn cho biểu đồ, và cột
Dòng 9: chỉnh màu sắc cho các cột và nhãn
1. ggplot(BIDV, aes(x = tong_no_phai_tra, y = tien_thu_thanh_ly_ts_co_dinh, color = nam)) +
2. geom_point(size = 4.2, alpha = 0.85) +
3. geom_text(aes(label = formatC(tien_thu_thanh_ly_ts_co_dinh, format = "e", digits = 1)),
4. vjust = -1.06, color = "black", size = 2.7, fontface = "bold") +
5. scale_color_gradient(low = "#FFD700", high = "#FF00EA") +
6. labs(title = "BIỂU ĐỒ PHÂN TÁN:\n Tổng nợ phải trả & Tiền thu thanh lý TS cố định",
7. x = "Tổng nợ phải trả (VND)",
8. y = "Tiền thu thanh lý tài sản cố định (VND)",
9. color = "Năm") +
10. theme_minimal() +
11. theme(plot.title = element_text(hjust = 0.5, size =14 , face = "bold", color = "black"),
12. axis.text = element_text(color = "#FFD700"),
13. axis.title = element_text(size = 13, face = "bold") )
Giải thích kỹ thuật
Dòng 1 :Khởi tạo biểu đồ phân tán (ggplot)
Dòng 2: Vẽ các điểm phân tán với các thông số tương tự như các biểu đồ trước đã đề cập
Dòng 3 : Thêm nhãn cho biểu đồ với các thông số tương tự như các biểu đồ trước đã đề cập
Dòng 5: Thiết lập màu sắc cho các điểm
1. npm_counts <- as.data.frame(table(BIDV$hieuqua_NPM))
2. colnames(npm_counts) <- c("Hiệu quả NPM", "Số lượng")
3. npm_counts$y <- round(100 * npm_counts$`Số lượng` / sum(npm_counts$`Số lượng`), 1)
4. ggplot(npm_counts, aes(x = "", y = y, fill = `Hiệu quả NPM`)) +
5. geom_bar(stat = "identity", width = 1, color = "white") +
6. coord_polar("y", start = 0) +
7. scale_fill_manual(
8. values = c("#FFD700", "#39FF14", "#FF00EA"),
9. labels = c("Hiệu quả cao", "Hiệu quả trung bình", "Hiệu quả thấp") ) +
10. geom_text(
11. aes(label = paste0(y, "%")),
12. position = position_stack(vjust = 0.5), color = "#00F", size = 5, fontface = "bold" ) +
13. labs(title = "BIỂU ĐỒ TRÒN TỈ LỆ HIỆU QUẢ NPM",
14. fill = "Nhóm hiệu quả" ) +
15. theme_minimal() +
16. theme(
17. plot.title = element_text(hjust = 0.5, size = 15, face = "bold", color = "black"),
18. legend.text = element_text(size = 11))
Giải thích kỹ thuật :
Dòng 1: Tạo một bảng dữ liệu npm_counts
Dòng 2:Đặt lại tên cột cho bảng npm_counts, đổi tên các cột thành “Hiệu quả NPM” và “Số lượng” ’
Dòng 3: Tính tỷ lệ % của mỗi nhóm hiẹue quả NPM
Dòng 4-5: vẽ biểu đồ tròn với các thông số tương tự như các biểu đồ trước đã đề cập
Dòng 6: vẽ biểu đồ bar với các thông số tương tự như các biểu đồ trước đã đề cập
Dòng 7: thiết lập màu sắc cho các phần của biểu đồ tròn
Dòng 8: thêm nhãn cho biểu đồ tròn
Dòng 9: thêm tiêu đề cho biểu đồ chính
1. ggplot(BIDV, aes(x = thu_nhap_lai_va_cac_khoan_tuong_tu)) +
2. geom_histogram(fill = "#39FF14", color = "white", alpha = 0.72, bins = 12) +
3. labs(title = "PHÂN PHỐI THU NHẬP LÃI VÀ CÁC KHOẢN TƯƠNG TỰ",
4. x = "Thu nhập lãi và các khoản tương tự (VND)",
5. y = "Tần suất" ) +
6. theme_minimal() +
7. theme(
8. plot.title = element_text(hjust = 0.5, size = 15, face = "bold", color = "black"),
9. axis.text.x = element_text(color = "#FF1463", size = 11) )
Giải thích kỹ thuật
Dòng 1: vẽ biểu đồ với gglot(), trục X là cột thu_nhap_lai_va_cac_khoan_tuong_tu
Dòng 2: vẽ biểu đồ tần suất histogram với các tham số tương tự đã đề cập ở các đồ thị trước đó
Dong 3: thêm nhãn cho biểu đồ chính
Dòng 4: đơn giản hoá giao diện biểu đồ
1. df3 <- BIDV[, c("tong_thu_nhap_hoat_dong", "thanh_toan_nv_ncc", "chi_thue_tndn")]
2. df3_long <- pivot_longer(df3, cols = everything(), names_to = "Chỉ tiêu", values_to = "Giá trị")
3. ggplot(df3_long, aes(x = `Giá trị`, fill = `Chỉ tiêu`)) +
4. geom_histogram(position = "identity", alpha = 0.62, bins = 13, color = "white") +
5. scale_fill_manual(values = c("#FFD700", "#00FFF0", "#FF00EA"),
6. labels = c("Tổng thu nhập hoạt động", "Thanh toán NV-NCC", "Chi phí thuế TNDN")) +
7. labs(title = "PHÂN PHỐI 3 CHỈ TIÊU BIDV", x = "Giá trị (VND)", y = "Tần suất", fill = "Chỉ tiêu") +
8. theme_minimal() +
9. theme(plot.title = element_text(hjust = 0.5, size = 15, face = "bold", color = "black"))
Giải thích kỹ thuật: thực hiện tương tự giống Biểu đồ histogram phân phối thu nhập lãi và các khoản tương tự BIDV
1. df <- BIDV[, c("nam", "tong_tai_san", "tong_no_phai_tra", "von_chu_so_huu", "tong_thu_nhap_hoat_dong")]
2. df_long <- pivot_longer(df,
3. cols = c("tong_tai_san", "tong_no_phai_tra", "von_chu_so_huu", "tong_thu_nhap_hoat_dong"),
4. names_to = "Chỉ tiêu", values_to = "Giá trị")
5. max_value <- max(df_long$`Giá trị`, na.rm = TRUE)
6. y_breaks <- seq(0, max_value, by = 5e13)
7. label_scientific <- function(x) format(x, scientific = TRUE, digits = 2)
8. ggplot(df_long, aes(x = nam, y = `Giá trị`, color = `Chỉ tiêu`, group = `Chỉ tiêu`)) +
9. geom_line(size = 1.2) +
10. geom_point(size = 2.7) +
11. scale_color_manual(
12. values = c("#FFD700", "#39FF14", "#FF00EA", "#00FFF0"),
13. labels = c("Tổng tài sản", "Tổng nợ phải trả", "Vốn chủ sở hữu", "Tổng thu nhập hoạt động")) +
14. scale_y_continuous(
15. breaks = y_breaks,
16. labels = label_scientific) +
17. labs(title = "BIỂU ĐỒ ĐƯỜNG 4 BIẾN: Tổng tài sản, Tổng nợ phải trả, Vốn chủ sở hữu, Tổng thu nhập hoạt động",
18. x = "Năm", y = "Giá trị (VND)",color = "Chỉ tiêu") +
19. theme_minimal() +
20. theme(
21. plot.title = element_text(hjust = 0.5, size = 8, face = "bold", color = "black"),
22. axis.text.x = element_text(color = "black", size = 10),
23. axis.text.y = element_text(color = "black", size = 5))
Giải thích kỹ thuật: Giải thích kỹ thuật : thực hiện tương tự giống với Biểu đồ đường: Tổng tài sản từng năm
1. scale_fill_gradientn(
2. colors = c("#39FF14", "#0099FF", "#8000FF"),
3. name = "Tiền mặt, vàng bạc, đá quý")
## <ScaleContinuous>
## Range:
## Limits: 0 -- 1
1. df_heat1 <- BIDV[, c("nam", "tien_mat_vangbac_daquy")]
2. ggplot(df_heat1, aes(x = factor(nam), y = "Tiền mặt, vàng bạc, đá quý")) +
3. geom_tile(aes(fill = tien_mat_vangbac_daquy), color = "white", linewidth = 0.5) +
4. scale_fill_gradientn(
5. colors = c("#39FF14", "#0099FF", "#8000FF"),
6. name = "Tiền mặt, vàng bạc, đá quý" ) +
7. labs(title = "HEATMAP: Tiền mặt, vàng bạc, đá quý qua các năm", x = "Năm", y = "") +
8. theme_minimal() +
9. theme(
10. plot.title = element_text(hjust = 0.5, color = "#0099FF", size = 15, face = "bold"),
11. axis.text.x = element_text(color = "black", size = 6) )
Giải thích kỹ thuật
Dòng 1-3: Thiết lập một gradient màu cho biểu đồ:
Dòng 4: Tạo bảng con df_heat1
Dòng 5: vẽ biểu đồ với ggplot() với các tiêu chí tương tự với các biểu đồ đã đề cập ở trên
Dòng 6: vẽ biểu đồ hình vuông cho biến tien_mat_vangbac_daquy với các tiêu chí tương tự với các biểu đồ đã đề cập ở trên
Dòng 7: áp dụng gradien màu cho các hình vuông
Dòng 10: thêm nhãn cho biểu đồ chính
Dòng 11-14: giao diện tối giản và kiểu chữ màu sắc cho biểu đồ
1. ggplot(BIDV, aes(x = loi_nhuan_sau_thue)) +
2. geom_histogram(binwidth = 5e12, fill = "#2196F3", color = "#FF00EA", alpha = 0.8) +
3. facet_wrap(~hieuqua_NIM) +
4. labs(
5. x = "Lợi nhuận sau thuế (VND)",
6. y = "Số lần xuất hiện",
7. title = "Phân phối lợi nhuận sau thuế theo nhóm hiệu quả NIM") +
8. theme_minimal() +
9. theme(
10. plot.title = element_text(hjust = 0.5, color = "#2196F3", size = 15, face = "bold"),
11. axis.text.x = element_text(color = "#FF00EA", size = 11) )
Giải thích kỹ thuật : thực hiện tương tự giống với Biểu đồ histogram phân phối thu nhập lãi và các khoản tương tự BIDV
1. ggplot(BIDV, aes(x = thu_nhap_lai_va_cac_khoan_tuong_tu)) +
2. geom_density(fill = "#39FF14", color = "black", alpha = 0.8) +
3. facet_wrap(~hieuqua_NIM) +
4. labs(x = "Thu nhập lãi và các khoản tương tự (VND)",
5. y = "Mật độ (density)",
6. title = "Biểu đồ mật độ thu nhập lãi và các khoản tương tự theo hiệu quả NIM" ) +
7. theme_minimal() +
8. theme(plot.title = element_text(hjust = 0.5, color = "black", size = 12, face = "bold"),
9. axis.text.x = element_text(color = "#00AEA5", size = 11))
Giải thích kỹ thuật
Dòng 1: vẽ biểu đồ với ggplot() trục X là cột thu_nhap_lai_va_cac_khoan_tuong_tu
Dòng 2: Vẽ biểu đồ mật độ (density plot) với các tiêu chí tương tự với các biểu đồ đã đề cập ở trên
Dòng 3: chia biẻu đồ thành các nhóm con dựa trên hieuqua_nim
Dòng 4: thêm nhãn cho biểu đồ chính
Dòng 7-9: tối giản giao diện biểu đồ và điều chỉnh kiểu chữ, màu sắc của biểu đồ
-Nhận xét: Biểu đồ cho thấy phân bố thu nhập lãi và các khoản tương tự có sự khác biệt giữa hai nhóm hiệu quả NIM. Nhóm “Tốt” tập trung ở mức thu nhập trung bình–cao, thể hiện khả năng sinh lời ổn định từ hoạt động cho vay. Ngược lại, nhóm “Trung bình” có phân bố dàn trải hơn, phản ánh hiệu quả sử dụng tài sản kém ổn định, cho thấy biên lợi nhuận lãi của nhóm này chưa được tối ưu hóa.
Phân tích cho thấy quy mô hoạt động của BIDV tăng mạnh và ổn định trong giai đoạn 2010–2024. Tổng tài sản, nợ phải trả và vốn chủ sở hữu đều tăng qua các năm, trong đó nguồn vốn huy động vẫn chiếm tỷ trọng lớn. Doanh thu từ hoạt động cốt lõi và lợi nhuận sau thuế đều tăng, đặc biệt sau năm 2021, phản ánh khả năng mở rộng quy mô và hiệu quả kinh doanh ngày càng được cải thiện.
Về biên lợi nhuận, chỉ số NIM duy trì ở mức ổn định quanh 2,3–2,7% nhưng có thời điểm chịu áp lực do chi phí vốn tăng nhanh, trong khi NPM cải thiện rõ rệt nhờ kiểm soát chi phí tốt hơn. Các khoản mục thanh khoản như tiền mặt, vàng bạc, đá quý tăng theo chu kỳ, còn lợi nhuận ngoại hối – vàng biến động, cho thấy mức nhạy cảm nhất định với điều kiện thị trường tài chính.
Tổng thể, BIDV giữ được đà tăng trưởng bền vững và duy trì biên lợi nhuận dương. Tuy nhiên, ngân hàng cần tiếp tục giảm chi phí vốn, mở rộng thu nhập ngoài lãi và nâng cao hiệu quả sử dụng tài sản. Trọng tâm đề xuất là tăng tỷ lệ tiền gửi không kỳ hạn (CASA) để giảm chi phí huy động, phát triển dịch vụ và ngân hàng số nhằm đa dạng nguồn thu, đồng thời kiểm soát chặt chi phí và rủi ro để bảo vệ NIM, NPM và duy trì tăng trưởng lợi nhuận ổn định trong các năm tới.
Trần Mạnh Tường(2025). Data manipulation và Data Visualization
Nghĩa, H. P. TPP & NHỮNG TÁC ĐỘNG ĐẾN THỊ TRƯỜNG BẤT ĐỘNG SẢN VIỆT NAM.
Vương, Q. H., Nguyễn, H. S., & Trần, T. D. (2008). Hậu quả của tín dụng bất động sản ở Mỹ và nghĩ về các biện pháp phòng ngừa ở Việt Nam.
CHÍNH, T. PHÂN TÍCH HIỆU QUẢ HOẠT ĐỘNG CÙA CÁC NGÂN HÀNG THƯƠNG MẠI có PHÁN TẠI VIỆT NAM.
Ha Nam Khanh, G., & Chau, T. K. (2020). Nhân tố ảnh hưởng đến quyết định sử dụng dịch vụ smartbanking-Nghiên cứu thực nghiệm tại BIDV-Chi nhánh Bắc Sài gòn (The Factors Affect on the Decision of Using Smart Banking Service at Bank of Investment and Development of Viet Nam-North Saigon Branch). Tạp chí Khoa học & Đào tạo Ngân hàng-Số.