1 . MỞ ĐẦU

1.1 . Lý do chọn đề tài

Trong bối cảnh chuyển đổi số và sự phát triển mạnh mẽ của khoa học dữ liệu, việc thu thập, xử lý và phân tích dữ liệu đang trở thành xu hướng tất yếu trong nhiều lĩnh vực. Thị trường bất động sản là một trong những lĩnh vực có lượng dữ liệu lớn, phong phú và mang tính biến động cao, phản ánh rõ nét tình hình kinh tế – xã hội của từng khu vực. Việc phân tích dữ liệu bất động sản giúp cung cấp cái nhìn khoa học và toàn diện hơn về xu hướng giá nhà, diện tích, vị trí và các yếu tố ảnh hưởng đến thị trường.

Ngôn ngữ R và môi trường RStudio được xem là công cụ hiệu quả trong việc xử lý, phân tích và trực quan hóa dữ liệu nhờ vào khả năng tính toán mạnh mẽ, kho thư viện phong phú và giao diện thân thiện. Thông qua RStudio, người học có thể thực hiện các thao tác phân tích dữ liệu mô tả, trích lọc, phân tổ và thể hiện dữ liệu trực quan bằng biểu đồ một cách khoa học.

Từ những lý do đó, tác giả lựa chọn đề tài “Phân tích dữ liệu thị trường bất động sản Hoa Kỳ” với mục tiêu vận dụng R và RStudio để khai thác và khám phá bộ dữ liệu USA Real Estate Dataset. Thông qua quá trình thực hiện, người học không chỉ củng cố kiến thức và kỹ năng phân tích dữ liệu trong R mà còn hiểu rõ hơn về đặc điểm và xu hướng của thị trường bất động sản Hoa Kỳ trong thực tế.

1.2 . Mục tiêu nghiên cứu

Mục tiêu tổng quát: Phân tích, mô tả và trực quan hóa dữ liệu về thị trường bất động sản Hoa Kỳ nhằm khám phá đặc điểm, xu hướng và sự phân bố của giá nhà, diện tích, vị trí địa lý và trạng thái bất động sản thông qua việc ứng dụng ngôn ngữ R trong môi trường RStudio trên bộ dữ liệu USA Real Estate Dataset. Từ đó đưa ra các kết luận và khuyến nghị

Mục tiêu chi tiết:

Tổng hợp và mô tả các đặc điểm cơ bản của thị trường bất động sản Hoa Kỳ, bao gồm giá nhà, diện tích đất, diện tích sử dụng, số phòng và trạng thái giao dịch.

Phân tổ dữ liệu theo bang, thành phố và mã vùng để nhận diện sự khác biệt về giá trị trung bình, quy mô và phân bố giữa các khu vực.

Trực quan hóa dữ liệu bằng biểu đồ và đồ thị để minh họa xu hướng, mối quan hệ và đặc điểm nổi bật của các biến trong bộ dữ liệu.

Rút ra các nhận xét về đặc điểm và xu hướng chung của thị trường bất động sản Hoa Kỳ, đồng thời đưa ra một số khuyến nghị định hướng cho các nghiên cứu mở rộng trong tương lai.

1.3 . Đối tượng và phạm vi nghiên cứu

Đối tượng nghiên cứu: Đề tài tập trung nghiên cứu dữ liệu về thị trường bất động sản tại Hoa Kỳ, được thu thập và tổng hợp trong bộ dữ liệu USA Real Estate Dataset. Bộ dữ liệu bao gồm các thông tin cơ bản của bất động sản như giá bán, diện tích đất, diện tích sử dụng, số lượng phòng ngủ, số phòng tắm, vị trí địa lý (bang, thành phố, mã vùng) và trạng thái giao dịch (đang bán hoặc đã bán).

Phạm vi nghiên cứu:

Về không gian: Dữ liệu bao phủ các bang, thành phố và khu vực trên toàn lãnh thổ Hoa Kỳ, phản ánh đặc điểm và xu hướng của thị trường bất động sản tại từng vùng.

Về thời gian: Nghiên cứu sử dụng dữ liệu được cập nhật trong giai đoạn gần đây, phản ánh tình hình thị trường tại thời điểm thu thập.

Về nội dung: Đề tài chỉ tập trung vào phân tích mô tả và trực quan hóa dữ liệu nhằm nhận diện đặc điểm và xu hướng của thị trường, từ đó đưa ra các kết luận và giải pháp, không thực hiện các mô hình dự đoán hay hồi quy thống kê.

1.4 . Phương pháp nghiên cứu

Đề tài sử dụng phương pháp phân tích mô tả và trực quan hóa dữ liệu, được thực hiện bằng ngôn ngữ R trong môi trường RStudio. Dữ liệu được nhập từ bộ USA Real Estate Dataset, sau đó được kiểm tra, xử lý và làm sạch để đảm bảo tính chính xác trước khi phân tích. Quá trình nghiên cứu bao gồm việc tính toán các thống kê mô tả, như giá trị trung bình, trung vị, độ lệch chuẩn và phân bố của các biến, nhằm hiểu rõ đặc điểm tổng quát của dữ liệu. Tiếp theo, dữ liệu được phân tổ theo các tiêu chí như bang, thành phố hoặc trạng thái bất động sản, giúp nhận diện sự khác biệt giữa các khu vực. Kết quả được trực quan hóa bằng các biểu đồ và đồ thị thông qua các hàm và gói lệnh trong R, giúp thể hiện xu hướng, mối quan hệ và đặc điểm nổi bật của thị trường bất động sản Hoa Kỳ một cách rõ ràng và trực quan.

1.5 . Đóng góp của nghiên cứu

Đề tài “Phân tích dữ liệu thị trường bất động sản Hoa Kỳ” mang lại những đóng góp thiết thực cả về mặt học tập và ứng dụng thực tiễn. Trước hết, nghiên cứu giúp người học vận dụng ngôn ngữ R trong môi trường RStudio để thực hành các bước cơ bản trong quy trình phân tích dữ liệu: nhập dữ liệu, làm sạch, thống kê mô tả, phân tổ và trực quan hóa. Thông qua quá trình này, người học rèn luyện được kỹ năng thao tác và tư duy xử lý dữ liệu – nền tảng quan trọng trong học tập và nghiên cứu khoa học dữ liệu hiện nay. Bên cạnh đó, đề tài còn giúp minh họa rõ quy trình phân tích dữ liệu thực tế bằng các hàm và gói lệnh trong R, từ đó tạo cầu nối giữa lý thuyết thống kê và ứng dụng phần mềm. Việc trực quan hóa dữ liệu bằng biểu đồ và đồ thị giúp kết quả trở nên dễ hiểu, trực quan và có tính thuyết phục hơn, đồng thời hỗ trợ người học nhận diện nhanh các đặc điểm và xu hướng nổi bật của thị trường bất động sản Hoa Kỳ. Ngoài giá trị học tập, nghiên cứu cũng mang ý nghĩa tham khảo cho những người mới bắt đầu học R, đặc biệt là trong lĩnh vực phân tích dữ liệu kinh tế và bất động sản. Kết quả của đề tài có thể là tiền đề cho các hướng mở rộng trong tương lai như xây dựng mô hình dự báo giá nhà, phân tích nhân tố ảnh hưởng hoặc đánh giá xu hướng thị trường trên phạm vi rộng hơn.

1.6 . Kết cấu của đề tài

Chương 1: Mở đầu – Trình bày lý do chọn đề tài, mục tiêu, đối tượng, phạm vi, phương pháp, đóng góp và kết cấu của nghiên cứu.

Chương 2: Giới thiệu bộ dữ liệu – Mô tả nguồn gốc, cấu trúc, ý nghĩa và các biến trong bộ dữ liệu USA Real Estate Dataset.

Chương 3: Phân tích và trực quan hóa dữ liệu – Thực hiện các bước đọc, xử lý, thống kê mô tả, phân tổ và biểu diễn kết quả thông qua các biểu đồ, đồ thị trong RStudio.

Chương 4: Kết luận và khuyến nghị – Tóm tắt các kết quả đạt được, nêu những hạn chế của đề tài và đề xuất hướng phát triển cho các nghiên cứu sau.

2 . Tổng quan về bộ dữ liệu

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

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ỳ.

2.2 . Thông tin chung về bộ dữ liệu

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.

library(ggplot2)
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(DT)
library(readxl)
#Đọc dữ liệu
tieuluan <- read.csv("~/Downloads/TLHK3:2025/Ngôn ngữ lập trình R/realtor-data.zip.csv")
tieuluan$prev_sold_date <- as.Date(tieuluan$prev_sold_date, format = "%Y-%m-%d")
#Xem 6 dòng đầu tiên
head(tieuluan) 
#Xem 6 dòng cuối cùng 
tail(tieuluan)

Ta sử dụng sử dụng một số lệnh bên dưới để xem thông tin chung của tieuluan.

# 4. Kiểm tra kích thước bộ dữ liệu
dim(tieuluan)
## [1] 2226382      12

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.

#Xem tên các biến 
names(tieuluan)
##  [1] "brokered_by"    "status"         "price"          "bed"           
##  [5] "bath"           "acre_lot"       "street"         "city"          
##  [9] "state"          "zip_code"       "house_size"     "prev_sold_date"

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”.

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:

library(kableExtra)
## 
## Attaching package: 'kableExtra'
## The following object is masked from 'package:dplyr':
## 
##     group_rows
# Tạo bảng dữ liệu mô tả các biến bất động sản
des <- data.frame(
  STT = 1:12,
  Tên_biến = c("brokered_by", "status", "price", "bed", "bath",
               "acre_lot", "street", "city", "state", "zip_code",
               "house_size", "prev_sold_date"),
  Mô_tả = c(
    "Tên công ty hoặc đại lý môi giới bất động sản (đã mã hóa)",
    "Trạng thái bất động sản (đang bán hoặc sẵn sàng xây dựng)",
    "Giá của bất động sản (hiện tại hoặc gần nhất)",
    "Số lượng phòng ngủ của bất động sản",
    "Số lượng phòng tắm của bất động sản",
    "Diện tích đất (tính bằng mẫu Anh - acre)",
    "Tên đường (đã mã hóa để bảo mật thông tin)",
    "Tên thành phố nơi bất động sản tọa lạc",
    "Tên bang nơi bất động sản thuộc về",
    "Mã vùng bưu điện (ZIP code) của khu vực",
    "Diện tích sử dụng hoặc diện tích sàn của ngôi nhà (tính bằng feet vuông)",
    "Ngày bán gần nhất trước đó (nếu có)"
  )
)

# Hiển thị bảng đẹp
des %>%
  kable("html", align = "c", 
        col.names = c("**STT**", "**Tên biến**", "**Mô tả**"),
        caption = "<div style='text-align: center;'><b>Bảng 1. Danh sách các biến trong dữ liệu bất động sản</b></div>") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"),
                full_width = F, position = "center", font_size = 14) %>%
  row_spec(0, bold = TRUE, background = "#6495ED") %>%
  column_spec(1:3, border_right = TRUE)
Bảng 1. Danh sách các biến trong dữ liệu bất động sản
STT Tên biến Mô tả
1 brokered_by Tên công ty hoặc đại lý môi giới bất động sản (đã mã hóa)
2 status Trạng thái bất động sản (đang bán hoặc sẵn sàng xây dựng)
3 price Giá của bất động sản (hiện tại hoặc gần nhất)
4 bed Số lượng phòng ngủ của bất động sản
5 bath Số lượng phòng tắm của bất động sản
6 acre_lot Diện tích đất (tính bằng mẫu Anh - acre)
7 street Tên đường (đã mã hóa để bảo mật thông tin)
8 city Tên thành phố nơi bất động sản tọa lạc
9 state Tên bang nơi bất động sản thuộc về
10 zip_code Mã vùng bưu điện (ZIP code) của khu vực
11 house_size Diện tích sử dụng hoặc diện tích sàn của ngôi nhà (tính bằng feet vuông)
12 prev_sold_date Ngày bán gần nhất trước đó (nếu có)
#Xem cấu trúc tổng quát của dữ liệu
str(tieuluan)
## 'data.frame':    2226382 obs. of  12 variables:
##  $ brokered_by   : num  103378 52707 103379 31239 34632 ...
##  $ status        : chr  "for_sale" "for_sale" "for_sale" "for_sale" ...
##  $ price         : num  105000 80000 67000 145000 65000 179000 50000 71600 100000 300000 ...
##  $ bed           : int  3 4 2 4 6 4 3 3 2 5 ...
##  $ bath          : int  2 2 1 2 2 3 1 2 1 3 ...
##  $ acre_lot      : num  0.12 0.08 0.15 0.1 0.05 0.46 0.2 0.08 0.09 7.46 ...
##  $ street        : num  1962661 1902874 1404990 1947675 331151 ...
##  $ city          : chr  "Adjuntas" "Adjuntas" "Juana Diaz" "Ponce" ...
##  $ state         : chr  "Puerto Rico" "Puerto Rico" "Puerto Rico" "Puerto Rico" ...
##  $ zip_code      : int  601 601 795 731 680 612 639 731 730 670 ...
##  $ house_size    : num  920 1527 748 1800 NA ...
##  $ prev_sold_date: Date, format: NA NA ...

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ó 2.226.382 quan sát và 12 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ư brokered_by, price, bed, bath, acre_lot, street, zip_code và house_size là các biến định lượng, còn các biến status, city, state và prev_sold_date là chuỗi ký tự.

#Xem kiểu dữ liệu theo từng cột 
sapply(tieuluan, class)
##    brokered_by         status          price            bed           bath 
##      "numeric"    "character"      "numeric"      "integer"      "integer" 
##       acre_lot         street           city          state       zip_code 
##      "numeric"      "numeric"    "character"    "character"      "integer" 
##     house_size prev_sold_date 
##      "numeric"         "Date"

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 integer như bed, bath, zip_code, TransactionNo; kiểu numeric như brokered_by, price, acre_lot, street, house_size, house_size_m2; kiểu character như city, state, year, mucgianha, mucdientichnha; kiểu factor như status, dientichdat; 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.

2.3 . Thống kê mô tả

#Thống kê mô tả biến price
library(moments)

summary_price <- tieuluan$price
data.frame(
  Min = min(summary_price, na.rm = TRUE),
  Q1 = quantile(summary_price, 0.25, na.rm = TRUE),
  Median = median(summary_price, na.rm = TRUE),
  Mean = mean(summary_price, na.rm = TRUE),
  Q3 = quantile(summary_price, 0.75, na.rm = TRUE),
  Max = max(summary_price, na.rm = TRUE),
  SD = sd(summary_price, na.rm = TRUE),
  Variance = var(summary_price, na.rm = TRUE),
  Skewness = skewness(summary_price, na.rm = TRUE),
  Kurtosis = kurtosis(summary_price, na.rm = TRUE)
)

Nhận xét: Biến price có giá trị dao động từ 1 đến 515.000.000, cho thấy sự chênh lệch cực lớn giữa các căn nhà. Giá trung vị (380.000) thấp hơn trung bình (568.680,7), cho thấy phân bố lệch phải. Độ lệch chuẩn (1.181.521) và phương sai (1,40E+18) rất cao, cùng với skewness = 1.003.544 và kurtosis = 34.884,71, phản ánh dữ liệu có rất nhiều giá trị ngoại lai (outliers).

#Thống kê mô tả biến bed
summary_bed <- tieuluan$bed
data.frame(
  Min = min(summary_bed, na.rm = TRUE),
  Q1 = quantile(summary_bed, 0.25, na.rm = TRUE),
  Median = median(summary_bed, na.rm = TRUE),
  Mean = mean(summary_bed, na.rm = TRUE),
  Q3 = quantile(summary_bed, 0.75, na.rm = TRUE),
  Max = max(summary_bed, na.rm = TRUE),
  SD = sd(summary_bed, na.rm = TRUE),
  Variance = var(summary_bed, na.rm = TRUE),
  Skewness = skewness(summary_bed, na.rm = TRUE),
  Kurtosis = kurtosis(summary_bed, na.rm = TRUE)
)

Nhận xét: Biến bed dao động từ 1 đến 444 phòng ngủ, với trung vị (Median = 3) gần bằng trung bình (Mean = 3,36), cho thấy hầu hết căn nhà có số phòng ngủ thấp nhưng xuất hiện giá trị cực đoan rất lớn. Độ lệch chuẩn (SD = 1.363.243) và phương sai (1.858.431) cực cao, cùng với skewness = 7.499.446 và kurtosis = 21.266,57, phản ánh dữ liệu có outliers nghiêm trọng.

#Thống kê mô tả biến bath
summary_bath <- tieuluan$bath
data.frame(
  Min = min(summary_bath, na.rm = TRUE),
  Q1 = quantile(summary_bath, 0.25, na.rm = TRUE),
  Median = median(summary_bath, na.rm = TRUE),
  Mean = mean(summary_bath, na.rm = TRUE),
  Q3 = quantile(summary_bath, 0.75, na.rm = TRUE),
  Max = max(summary_bath, na.rm = TRUE),
  SD = sd(summary_bath, na.rm = TRUE),
  Variance = var(summary_bath, na.rm = TRUE),
  Skewness = skewness(summary_bath, na.rm = TRUE),
  Kurtosis = kurtosis(summary_bath, na.rm = TRUE)
)

Nhận xét: Biến bath dao động từ 1 đến 222, với trung vị (Median = 2) thấp hơn trung bình (Mean = 2,52), cho thấy hầu hết căn nhà có số phòng tắm thấp, nhưng xuất hiện giá trị cực đoan (outliers) rất cao. Độ lệch chuẩn (SD = 1.305.431) và phương sai (170.415) khá lớn, cùng với skewness = 2.324.524 và kurtosis = 2.893.225, phản ánh dữ liệu có phân bố lệch phải mạnh và đuôi dài. Khi phân tích tiếp, nên loại bỏ hoặc kiểm tra các giá trị bất thường để kết quả thống kê ổn định hơn.

#Thống kê mô tả biến acre_lot
summary_acre <- tieuluan$acre_lot
data.frame(
  Min = min(summary_acre, na.rm = TRUE),
  Q1 = quantile(summary_acre, 0.25, na.rm = TRUE),
  Median = median(summary_acre, na.rm = TRUE),
  Mean = mean(summary_acre, na.rm = TRUE),
  Q3 = quantile(summary_acre, 0.75, na.rm = TRUE),
  Max = max(summary_acre, na.rm = TRUE),
  SD = sd(summary_acre, na.rm = TRUE),
  Variance = var(summary_acre, na.rm = TRUE),
  Skewness = skewness(summary_acre, na.rm = TRUE),
  Kurtosis = kurtosis(summary_acre, na.rm = TRUE)
)

Nhận xét: Biến acre_lot dao động từ 0 đến 100.000 mẫu anh, với trung vị (Median = 0,21) thấp hơn trung bình (Mean = 11,953), cho thấy hầu hết 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 đoan (outliers) rất lớn. Độ lệch chuẩn (SD = 7.952,551) và phương sai (632.430,7) rất cao, cùng với skewness = 1.013.364 và kurtosis = 11.338,48, phản ánh dữ liệu có phân bố lệch phải mạnh và đuôi dài.

#Thống kê mô tả biến house_size
summary_house <- tieuluan$house_size
data.frame(
  Min = min(summary_house, na.rm = TRUE),
  Q1 = quantile(summary_house, 0.25, na.rm = TRUE),
  Median = median(summary_house, na.rm = TRUE),
  Mean = mean(summary_house, na.rm = TRUE),
  Q3 = quantile(summary_house, 0.75, na.rm = TRUE),
  Max = max(summary_house, na.rm = TRUE),
  SD = sd(summary_house, na.rm = TRUE),
  Variance = var(summary_house, na.rm = TRUE),
  Skewness = skewness(summary_house, na.rm = TRUE),
  Kurtosis = kurtosis(summary_house, na.rm = TRUE)
)

Nhận xét: Biến house_size dao động từ 100 đến 1.560.780 feet vuông, với trung vị (Median = 1.792) thấp hơn trung bình (Mean = 2.074.938), cho thấy phần lớn căn nhà có diện tích vừa phải nhưng tồn tại một số giá trị cực đoan (outliers) rất lớn. Độ lệch chuẩn (SD = 2.437) và phương sai (2.767.434) cao, cùng với skewness = 2.656.119 và kurtosis = 115.774,4, phản ánh dữ liệu có phân bố lệch phải mạnh và đuôi dài.

# Hàm thống kê tần số
categorical_summary <- function(var){
  freq <- table(var)
  percent <- prop.table(freq) * 100
  data.frame(Value = names(freq), Frequency = as.numeric(freq), Percent = round(as.numeric(percent),2))
}

# Chạy cho từng biến
status_summary <- categorical_summary(tieuluan$status)
city_summary <- categorical_summary(tieuluan$city)
state_summary <- categorical_summary(tieuluan$state)

status_summary
city_summary
state_summary

3 . Làm sạch dữ liệu

3.1 . Xử lý giá trị thiếu (Missing Values – NA)

# Kiểm tra xem dữ liệu có giá trị NA nào không
any(is.na(tieuluan))
## [1] TRUE

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.

# Đếm tổng số giá trị bị thiếu trong toàn bộ dataset
sum(is.na(tieuluan))
## [1] 2638697

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à 2.638.697, nghĩa là có giá trị 2.638.697 NA rong dataset.

# Đếm số lượng giá trị NA trong từng cột
colSums(is.na(tieuluan))
##    brokered_by         status          price            bed           bath 
##           4533              0           1541         481317         511771 
##       acre_lot         street           city          state       zip_code 
##         325589          10866              0              0            299 
##     house_size prev_sold_date 
##         568484         734297

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à bed (481.317 NA), bath (511.771 NA), house_size (568.484 NA), và prev_sold_date (734.297 NA). Một số biến numeric khác cũng có giá trị thiếu như acre_lot (325.589 NA) và price (1.541 NA), trong khi các biến phân loại như status, city, state hầu như không có giá trị NA. Kết quả này giúp xác định các cột cần xử lý dữ liệu thiếu trước khi phân tích.

# Liệt kê tên các cột có giá trị bị thiếu
names(tieuluan)[colSums(is.na(tieuluan)) > 0]
## [1] "brokered_by"    "price"          "bed"            "bath"          
## [5] "acre_lot"       "street"         "zip_code"       "house_size"    
## [9] "prev_sold_date"

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à: brokered_by, price, bed, bath, acre_lot, street, zip_code, house_size và prev_sold_date. Thông tin này giúp xác định những cột cần xử lý NA trước khi thực hiện phân tích hoặc trực quan hóa dữ liệu.

# Loại bỏ tất cả giá trị NA trong dữ liệu tieuluan
tieuluan <- na.omit(tieuluan)

# Kiểm tra tổng số giá trị NA còn lại (sau khi loại bỏ)
sum(is.na(tieuluan))
## [1] 0

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.

3.2 . Xác định và loại bỏ dữ liệu trùng lặp

# Xem 6 giá trị đầu tiên của kết quả duplicated()
head(duplicated(tieuluan))
## [1] FALSE FALSE FALSE FALSE FALSE FALSE

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.

# Đếm tổng số dòng bị trùng
sum(duplicated(tieuluan))
## [1] 0

Nhận xét: Sử dụng lệnh sum(duplicated()) kết quả trả về tổng số quan sát trùng lặp trong bộ dữ liệu. Trong tieuluan, kết quả là 0, nghĩa là không có dòng nào bị trùng lặp.

3.3 . Sửa lỗi dữ liệu

# . Tìm các giao dịch có giá âm hoặc bằng 0
subset(tieuluan, price <= 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.

# . Tìm các giao dịch có house_size <= 0
subset(tieuluan, house_size <= 0)

Nhận xét: Sử dụng lệnh subset(tieuluan, house_size <= 0) tìm các giao dịch có diện tích nhà 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 nhà ≤ 0, đảm bảo dữ liệu về diện tích hợp lệ để phân tích.

#  Tìm các giao dịch có bed <= 0
subset(tieuluan, bed <= 0)

Nhận xét: Sử dụng lệnh subset(tieuluan, bed <= 0) tìm các giao dịch có số phòng ngủ 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 ngủ ≤ 0, đảm bảo dữ liệu về số phòng ngủ hợp lệ để phân tích.

#  Tìm các giao dịch có bath <= 0
subset(tieuluan, 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.

# Kiểm tra giá trị status để phát hiện lỗi chính tả
unique(tieuluan$status)
## [1] "for_sale" "sold"

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.

3.4 . Chuyển đổi kiểu dữ liệu

# Chuyển biến status từ character sang factor
tieuluan$status <- as.factor(tieuluan$status)
# Nếu định dạng ngày là "YYYY-MM-DD"
tieuluan$prev_sold_date <- as.Date(tieuluan$prev_sold_date, format = "%Y-%m-%d")
# Kiểm tra lại kiểu dữ liệu của toàn bộ biến
sapply(tieuluan, class)
##    brokered_by         status          price            bed           bath 
##      "numeric"       "factor"      "numeric"      "integer"      "integer" 
##       acre_lot         street           city          state       zip_code 
##      "numeric"      "numeric"    "character"    "character"      "integer" 
##     house_size prev_sold_date 
##      "numeric"         "Date"

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 brokered_by, price, acre_lot, street, house_size là kiểu numeric; các biến bed, bath, zip_code là kiểu integer; biến status là factor; các biến city, state là character; và biến prev_sold_date là kiểu Date. Thông tin này giúp xác định loại biến để lựa chọn phương pháp phân tích và trực quan hóa phù hợp.

4 . TRUY XUẤT DỮ LIỆU

4.1 . Truy cập dữ liệu

Tác giả thực hiện các lệnh để truy cập dữ liệu dưới đây:

# Lấy cột price, xem 10 giá trị đầu
head(tieuluan$price, 10)
##  [1]  110000  950000 6899000  525000  289900  384900  199999  419000  745000
## [10]  875000
# Lấy cột bed, xem 12 giá trị cuối
tail(tieuluan$bed, 12)
##  [1] 4 3 3 4 3 4 4 4 3 6 2 5
# Lấy cột status, xem 15 giá trị đầu
head(tieuluan$status, 15)
##  [1] for_sale for_sale for_sale for_sale for_sale for_sale for_sale for_sale
##  [9] for_sale for_sale for_sale for_sale for_sale for_sale for_sale
## Levels: for_sale sold
# Lấy cột house_size bằng [, "column_name"]
head(tieuluan[, "house_size"], 10)   # Xem 10 giá trị đầu cột diện tích nhà
##  [1] 1192 5000 4600 2314 1276 1476 1968 1607 2847 4366
# Lấy cột acre_lot bằng [, column index]
head(tieuluan[, 6], 10)       # Xem 10 giá trị đầu cột thứ 6 (acre_lot)
##  [1] 0.09 0.99 0.83 0.45 0.36 0.46 1.76 2.00 0.56 1.50
# Lấy nhiều cột cùng lúc bằng tên
head(tieuluan[, c("price", "bed", "house_size")], 10)  
# Xem 10 giá trị đầu của các cột price, bed, house_size


# Lấy nhiều cột cùng lúc theo index
head(tieuluan[, c(3,4,11)], 10)  
# Cột 3: price, 4: bed, 11: house_size, 10 giá trị đầu
# Lấy dòng đầu tiên
tieuluan[1, ]
# Lấy 10 dòng đầu tiên
tieuluan[1:10, ]
# Lấy dòng cuối cùng
tieuluan[nrow(tieuluan), ]
# Lấy 5 dòng cuối cùng bằng tail()
tail(tieuluan, 5)
# Lấy dòng thứ 100
tieuluan[100, ]
#  Lấy các dòng có giá > 300000
tieuluan[tieuluan$price > 300000, ]
# Lấy các dòng có trạng thái for_sale
tieuluan[tieuluan$status == "for_sale", ]
# Lấy các dòng có >=4 phòng ngủ và giá < 200000
tieuluan[tieuluan$bed >= 4 & tieuluan$price < 200000, ]

4.2 . Lọc dữ liệu theo điều kiện

Tác giả thực hiện các lệnh lọc dữ liệu cơ bản theo điều kiện:

# Lấy tất cả nhà đang for_sale
tieuluan[tieuluan$status == "for_sale", ]
# Lấy tất cả nhà đã sold
tieuluan[tieuluan$status == "sold", ]
# Lấy các nhà giá > 300000
tieuluan[tieuluan$price > 300000, ]
# Lấy các nhà giá từ 100000 đến 200000
tieuluan[tieuluan$price >= 100000 & tieuluan$price <= 200000, ]
# Lấy các nhà có >=4 phòng ngủ
tieuluan[tieuluan$bed >= 4, ]
# Lấy các nhà >=4 phòng ngủ và giá < 200000
tieuluan[tieuluan$bed >= 4 & tieuluan$price < 200000, ]
# Lấy các nhà có house_size > 1500
tieuluan[tieuluan$house_size > 1500, ]
# Lấy các nhà ở thành phố "Ponce"
tieuluan[tieuluan$city == "Ponce", ]

4.3 . Truy cập một giá trị cụ thể

Tác gỉ thuwch hiện một số lệnh sau đây để truy cập một giá trị cụ thể:

# Giá của dòng đầu tiên
tieuluan[1, "price"]
## [1] 110000
# Thành phố của dòng thứ 5
tieuluan[5, "city"]
## [1] "Agawam"
# Số phòng ngủ của dòng thứ 10
tieuluan[10, "bed"]
## [1] 4
# Trạng thái của dòng cuối cùng
tieuluan[nrow(tieuluan), "status"]
## [1] sold
## Levels: for_sale sold
# Dùng $ để lấy giá của dòng thứ 3
tieuluan$price[3]
## [1] 6899000
# Dùng which.max() để tìm dòng có giá cao nhất
tieuluan[which.max(tieuluan$price), ]
#  Dùng which.min() để tìm dòng có giá thấp nhất
tieuluan[which.min(tieuluan$price), ]
#  Dùng which() để tìm tất cả nhà có >=4 phòng ngủ
tieuluan[which(tieuluan$bed >= 4), ]
#  Dùng which() để tìm tất cả nhà có trạng thái "sold"
tieuluan[which(tieuluan$status == "sold"), ]
#  Kết hợp which.max() và select cột price để chỉ lấy giá cao nhất
tieuluan$price[which.max(tieuluan$price)]
## [1] 5.15e+08

4.4 . Thêm và sửa 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:

#-----------------------------
# 5. Thêm và sửa dữ liệu (chỉnh sửa)
#-----------------------------

# 1. Chỉnh lại trạng thái ở dòng đầu tiên
tieuluan$status[1] <- "FOR_SALE"
## Warning in `[<-.factor`(`*tmp*`, 1, value = structure(c(NA, 1L, 1L, 1L, :
## invalid factor level, NA generated
# 2. Cập nhật lại tên thành phố cho dòng thứ 5
tieuluan$city[5] <- "San Juan"

# 4. Xóa dòng thứ 3 khỏi dữ liệu
tieuluan <- tieuluan[-3, ]

# 6. Sửa giá dòng thứ 2 tăng 10%
tieuluan$price[2] <- tieuluan$price[2] * 1.10

# 7. Cập nhật price dòng cuối cùng tăng 5%
tieuluan$price[nrow(tieuluan)] <- tieuluan$price[nrow(tieuluan)] * 1.05

# 8. Sửa giá dòng thứ 4 giảm 7%
tieuluan$price[4] <- tieuluan$price[4] * 0.93

# 9. Sửa trạng thái dòng thứ 6 thành "SOLD"
tieuluan$status[6] <- "SOLD"
## Warning in `[<-.factor`(`*tmp*`, 6, value = structure(c(NA, 1L, 1L, 1L, :
## invalid factor level, NA generated
# 10. Xóa tất cả dòng có price <= 0
tieuluan <- tieuluan[tieuluan$price > 0, ]

tieuluan <- na.omit(tieuluan)

# 3. Thêm cột đánh số thứ tự giao dịch
tieuluan$TransactionNo <- 1:nrow(tieuluan)

5 . Phân tổ các biến

5.1 . Phân tổ theo khoảng giá trị

#Trích xuất cột house_size từ đơn vị feet² sang m² 
tieuluan$house_size_m2 <- tieuluan$house_size * 0.092903
# Trích xuất cột năm 
tieuluan$year <- substr(tieuluan$prev_sold_date, 1, 4)
  • Nhận xét : Tác giả trích xuất năm từ biến prev_sold_date để tạo biến mới year, giúp thuận tiện cho việc phân tích và so sánh dữ liệu theo từng năm.
#Phân tổ biến Price theo mức giá
tieuluan <- tieuluan %>%
  mutate(
    mucgianha = case_when(
      is.na(price) ~ NA_character_,        # giữ nguyên NA
      price < 100000 ~ "Rất rẻ",           # dưới 100 nghìn USD
      price >= 100000 & price < 300000 ~ "Rẻ", 
      price >= 300000 & price < 600000 ~ "Trung bình",
      price >= 600000 & price < 1000000 ~ "Mắc",
      price >= 1000000 ~ "Rất mắc"         # từ 1 triệu USD trở lên
    )
  )
  • Nhận xét : Tác giả thực hiện phân loại “Price” thành biến “mucgianha” theo các mức từ “Rất rẻ” (giá dưới 100.000 USD ), “Rẻ” (giá từ 100.000 USD đến dưới 300.000 USD ), “Trung bình” (giá từ 300.000 USD đến dưới 600.000 USD), “Mắc” (giá từ 600.000 USD đến dưới 1.000.000 USD) “Rất mắc” (giá triệu USD trở lên). Kết quả nhận được là mỗi bất động sản được gán nhãn mức giá tương ứng, thuận tiện cho phân tích và thống kê theo nhóm.
#Phân tổ biến House_size theo diện tích
tieuluan <- tieuluan %>%
  mutate(
    mucdientichnha = case_when(
      is.na(house_size) ~ NA_character_,
      house_size < 1500 ~ "Nhỏ",              
      house_size >= 1500 & house_size < 4000 ~ "Trung bình", 
      house_size >= 4000 ~ "Lớn"              
    )
  )
  • Nhận xét : Tác giả thực hiện phân tổ biến house_size thành biến mới mucdientichnha với ba mức “Nhỏ” (diện tích dưới 1.500 feet vuông), “Trung bình” (diện tích lớn hơn hoặc bằng 1.500 feet vuông đến dưới 4.000 feet vuông) và “Lớn” (diện tích từ 4.000 feet vuông trở lên) . Kết quả giúp phân loại các bất động sản theo quy mô diện tích, thuận tiện cho việc phân tích và so sánh giữa các nhóm.

5.2 . Phân tổ biến acre_lot theo diện tích đất

## . Phân tổ biến acre_lot theo diện tích đất
tieuluan <- tieuluan %>%
  mutate(
    dientichdat = cut(
      acre_lot,
      breaks = c(0, 0.2, 0.5, 1, 5, Inf),
      labels = c("Rất nhỏ", "Nhỏ", "Vừa", "Lớn", "Rất lớn"),
      include.lowest = TRUE
    )
  )


table(tieuluan$dientichdat)
## 
## Rất nhỏ     Nhỏ     Vừa     Lớn Rất lớn 
##  536325  323172   89153   98059   38344

Nhận xét: Sử dụng lệnh cut() phân tổ biến acre_lot thành biến mới dientichdat với 5 nhóm: “Rất nhỏ” (diện tích từ 0 đến 0.2 acre), “Nhỏ” (từ 0.2 đến 0.5 acre), “Vừa” (từ 0.5 đến 1 acre), “Lớn” (từ 1 đến 5 acre) và “Rất lớn” (lớn hơn 5 acre). Việc phân loại này giúp dễ dàng phân tích phân phối diện tích đất của các bất động sản và so sánh giữa các nhóm khác nhau.

5.3 . Phân tổ các dữ liệu theo điều kiện cụ thể

#Nhà có giá trên 500,000 USD, diện tích nhà lớn hơn 185m², đang rao bán
data1 <- subset(
  tieuluan,
  price > 500000 &
    house_size_m2 > 185 &
    status == "for_sale"
)
head(data1)

Nhận xét: Nhóm bất động sản này bao gồm các nhà có giá trên 500.000 USD, diện tích lớn hơn 185 m² và đang ở trạng thái “for_sale”. Nhóm này có 123.714 quan sát, chiếm khoảng 11,4% tổng số quan sát. Mặc dù chiếm tỷ lệ nhỏ trong toàn bộ dữ liệu, nhóm này đại diện cho phân khúc nhà cao cấp, có giá trị lớn và tiềm năng thị trường đáng chú ý. Nhóm nhà cao cấp này phản ánh nhu cầu thị trường cho bất động sản giá trị lớn, cho thấy tiềm năng lợi nhuận cao cho nhà đầu tư và các công ty môi giới. Đồng thời, tỷ lệ quan sát thấp cũng cho thấy phân khúc này ít phổ biến, nhấn mạnh tính chọn lọc và đặc thù của thị trường cao cấp. ### . Nhà có giá thuộc nhóm “Mắc” hoặc “Rất mắc” và đang rao bán”

#Nhà có giá thuộc nhóm “Mắc” hoặc “Rất mắc” và đang rao bán"
data2 <- subset(
  tieuluan,
  mucgianha %in% c("Mắc", "Rất mắc") &
    status == "for_sale"
)
head(data2)

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à đang ở trạng thái “for_sale”. Nhóm này có 130.827 quan sát, chiếm 12,07% trên tổng số quan sát, đại diện cho phân khúc nhà cao cấp với giá trị lớn và diện tích rộng, hướng đến khách hàng có khả năng tài chính cao. Nhóm này phản ánh xu hướng phát triển của thị trường bất động sản cao cấp, cho thấy tiềm năng lợi nhuận và sự chú trọng của nhà đầu tư vào phân khúc giá trị lớn. Đồng thời, phân khúc này cũng cho thấy nhu cầu ổn định từ khách hàng giàu có, giúp các doanh nghiệp định hướng chiến lược kinh doanh và marketing phù hợp.

#Nhóm bất động sản thuộc bang California và diện tích nhà thuộc nhóm “Lớn”

data3 <- subset(
  tieuluan,
  state == "California" &
    mucdientichnha %in% c("Lớn")
)
head(data3)

Nhận xét: Nhóm bất động sản này gồm các nhà nằm tại bang California và có diện tích nhà thuộc nhóm “Lớn”, với 6.423 quan sát, chiếm khoảng 0,59% tổng số dữ liệu. Nhóm này cho thấy sự khan hiếm của các bất động sản quy mô rộng và giá trị cao tại California. Những căn nhà này thường hướng đến khách hàng tìm không gian sống rộng rãi, tiện nghi, đồng thời phản ánh tiềm năng lợi nhuận cao cho nhà đầu tư do nguồn cung hạn chế.

#Nhà có từ 4 phòng ngủ trở lên và diện tích đất thuộc nhóm “Đất lớn” hoặc “Đất rất lớn”
data4 <- subset(
  tieuluan,
  bed >= 4 &
    dientichdat %in% c("Lớn", "Rất lớn")
)
head(data4)

Nhận xét: Nhóm bất động sản này gồm các nhà có từ 4 phòng ngủ trở lên và diện tích đất thuộc nhóm “Lớn” hoặc “Rất lớn”, với 56.009 quan sát, chiếm khoảng 5,17% tổng số quan sát. Nhóm này phản ánh các bất động sản quy mô rộng, phù hợp với nhu cầu sinh hoạt của gia đình đông người. Những căn nhà này hướng đến khách hàng cần không gian sống thoải mái và tiện nghi, đồng thời cho thấy tiềm năng đầu tư ổn định trong phân khúc nhà có diện tích đất lớn.

#Nhà thuộc bang Texas, diện tích nhà trung bình, và giá thuộc nhóm “Trung bình” hoặc “Mắc”
data5 <- subset(
  tieuluan,
  state == "Texas" &
    mucdientichnha == "Trung bình" &
    mucgianha %in% c("Trung bình", "Mắc")
)
head(data5)

Nhận xét: Nhóm bất động sản này gồm các nhà thuộc bang Texas, có diện tích ở mức “Trung bình” và giá thuộc nhóm “Trung bình” hoặc “Mắc”, với 49.973 quan sát, chiếm khoảng 4,61% tổng số quan sát. Nhóm này đại diện cho phân khúc nhà phổ biến trên thị trường, thể hiện sự cân bằng giữa giá trị và diện tích. Những căn nhà này phù hợp với khách hàng có thu nhập khá, mong muốn không gian sống tiện nghi, ổn định và hợp lý về chi phí, đồng thời phản ánh nhu cầu phổ biến trong thị trường bất động sản trung cấp.

#Nhà có ít nhất 9 phòng ngủ, 4 phòng tắm trở lên, và diện tích đất thuộc nhóm “Đất lớn” hoặc “Đất rất lớn”.

data6 <- subset(
  tieuluan,
  bed >= 9 &
    bath >= 4 &
    dientichdat %in% c("Lớn", "Rất lớn")
)
head(data6)

Nhận xét: Nhóm bất động sản này gồm các nhà có ít nhất 9 phòng ngủ, từ 4 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 chỉ 533 quan sát, chiếm khoảng 0,049% tổng số quan sát. Nhóm này phản ánh sự hiếm có của các bất động sản quy mô lớn, thường thuộc phân khúc cao cấp. Những căn nhà này hướng đến các gia đình đông người hoặc khách hàng mong muốn không gian sống rộng rãi, tiện nghi và riêng tư, đồng thời thể hiện tiềm năng lợi nhuận cao do nguồn cung hạn chế.

#Bất động sản ở bang Florida, đang rao bán, và giá thuộc nhóm “Rẻ” hoặc “Trung bình”

#Bất động sản ở bang Florida, đang rao bán, và giá thuộc nhóm “Rẻ” hoặc “Trung bình”
data7 <- subset(
  tieuluan,
  state == "Florida" &
    status == "for_sale" &
    mucgianha %in% c("Rẻ", "Trung bình")
)
head(data7)

Nhận xét: Nhóm bất động sản này gồm các nhà nằm tại bang Florida, đang ở trạng thái “for_sale” và có giá thuộc nhóm “Rẻ” hoặc “Trung bình”, với 39.593 quan sát, chiếm khoảng 3,65% trong tổng số quan sát. Nhóm này đại diện cho phân khúc phổ biến, dễ tiếp cận trên thị trường. Những căn nhà này phù hợp với người mua có thu nhập trung bình hoặc nhà đầu tư tìm bất động sản giá hợp lý, phản ánh nhu cầu nhà ở thực tế cao và tiềm năng sinh lời ổn định.

# Nhà ở bang New York, đã bán (Sold), và mức giá nhà thuộc nhóm “Mắc” hoặc “Rất mắc”
data8 <- subset(
  tieuluan,
  state == "New York" &
    status == "sold" &
    mucgianha %in% c("Mắc", "Rất mắc")
)
head(data8)

Nhận xét: Nhóm bất động sản này gồm các nhà ở bang New York, đã bán và có giá trị giao dịch thuộc nhóm “Cao” hoặc “Rất cao”, với 3.008 quan sát, chiếm khoảng 0,28% trong tổng số quan sát. Nhóm này phản ánh phân khúc cao cấp ít phổ biến nhưng vẫn có giao dịch thành công. Những căn nhà này hướng đến khách hàng có khả năng tài chính cao, đồng thời thể hiện nguồn cung hạn chế và nhu cầu có chọn lọc trong thị trường bất động sản cao cấp tại New York.

#Nhà giá “Rất rẻ” hoặc “Rẻ”, diện tích nhà “Nhỏ”, ít hơn 2 phòng ngủ, đang rao bán, và nằm ngoài bang Florida
data9 <- subset(
  tieuluan,
  mucgianha %in% c("Rất rẻ", "Rẻ") &
    mucdientichnha == "Nhỏ" &
    bed < 2 &
    status == "for_sale" &
    state != "Florida"
)
head(data9)

Nhận xét: Nhóm bất động sản này gồm các nhà có giá “Rất rẻ” hoặc “Rẻ”, diện tích thuộc nhóm “Nhỏ”, ít hơn 2 phòng ngủ, đang rao bán và nằm ngoài bang Florida, với 3.367 quan sát, chiếm khoảng 0,31% trong tổng quan sát. Nhóm này đại diện cho bất động sản quy mô nhỏ, giá thấp. Những căn nhà này phù hợp với người mua có ngân sách hạn chế, người độc thân, hoặc nhà đầu tư muốn sở hữu tài sản nhỏ để cho thuê hoặc đầu tư dài hạn với chi phí thấp.

5.3.1 . Nhà bán từ năm 2020 trở đi, giá nhóm “Cao” hoặc “Rất cao”, và ở bang California

#. Nhà bán từ năm 2020 trở đi, giá "Rẻ", và ở bang California
data10 <- subset(
  tieuluan,
  year >= 2020 &
    mucgianha %in% c("Rẻ") &
    state == "California"
)
head(data10)

Nhận xét: Nhóm bất động sản này gồm các nhà ở bang California, được bán từ năm 2020 trở đi và có giá thuộc nhóm “Rẻ”, với 4.691 quan sát, chiếm khoảng 0,43% trong tổng số 2.226.382 quan sát. Nhóm này đại diện cho phân khúc bất động sản giá thấp, xuất hiện nhiều hơn sau thời kỳ đại dịch. Điều này phản ánh xu hướng tìm kiếm nhà ở giá phải chăng và nhu cầu giao dịch ổn định của người mua có thu nhập trung bình hoặc thấp.

6 . Phân tích 1 đến 3 biến trong bộ dữ liệu

# Thống kê mô tả biến price
thongke1 <- tieuluan %>%
  summarise(
    Sogiaodich = n(),
    Giatritb = mean(price, na.rm = TRUE),
    max = max(price, na.rm = TRUE),
    min = min(price, na.rm = TRUE),
    Trungvi = median(price, na.rm = TRUE),
    Dolechchuan = sd(price, na.rm = TRUE),
    Q1 = quantile(price, 0.25, na.rm = TRUE),
    Q3 = quantile(price, 0.75, na.rm = TRUE)
  )

head(thongke1)

Dựa vào bảng thông kê trên

  • Tổng giá trị giao dịch là 1,085,053 giao dịch

  • Giá trị trung bình của giá trị giao dịch là 568,685.7 USD.

  • Trung vị: 380,000 USD.

  • Giá trị tối thiểu và tối đa: 1 USD đến 515,000,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: 1,181,535 USD, cho thấy mức độ biến động cao giữa các giao dịch

  • Q1 và Q3: 240,000 USD và 600,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.

#Thống kê mô tả cho biến house_size_m2
thongke2 <- tieuluan %>%
  summarise(
    Sogiaodich = n(),
    Giatritb = mean(house_size_m2, na.rm = TRUE),
    max = max(house_size_m2, na.rm = TRUE),
    min = min(house_size_m2, na.rm = TRUE),
    Trungvi = median(house_size_m2, na.rm = TRUE),
    Dolechchuan = sd(house_size_m2, na.rm = TRUE),
    Q1 = quantile(house_size_m2, 0.25, na.rm = TRUE),
    Q3 = quantile(house_size_m2, 0.75, na.rm = TRUE)
  )

head(thongke2)

Dựa vào bảng thống kê trên:

  • Tổng số giao dịch: 1,085,053 giao dịch.

  • Diện tích nhà trung bình: 192.77 m².

  • Trung vị: 166.48 m².

  • Giá trị nhỏ nhất và lớn nhất: từ 9.29 m² đến 145,001.1 m², cho thấy khoảng cách rất lớn, phản ánh sự chênh lệch đáng kể giữa các loại nhà, từ rất nhỏ đến siêu lớn.

  • Độ lệch chuẩn: 257.10 m², cao hơn cả giá trị trung bình, chứng tỏ mức độ biến động diện tích giữa các nhà rất cao.

  • Q1 và Q3: lần lượt là 125.14 m² và 226.40 m², cho thấy phần lớn nhà có diện tích ở mức trung bình, dao động trong khoảng từ 125 đến 226 m².

#tính thống kê mô tả theo mucgianha và mucdientichnha
thongke3 <- tieuluan %>%
  group_by(mucgianha, mucdientichnha) %>%
  summarise(
    Soluong = n(),
    Giatritb = mean(price, na.rm = TRUE),
    max = max(price, na.rm = TRUE),
    min = min(price, na.rm = TRUE),
    Trungvi = median(price, na.rm = TRUE),
    Dolechchuan = sd(price, na.rm = TRUE),
    Q1 = quantile(price, 0.25, na.rm = TRUE),
    Q3 = quantile(price, 0.75, na.rm = TRUE)
  ) %>%
  arrange(mucgianha, mucdientichnha)
## `summarise()` has grouped output by 'mucgianha'. You can override using the
## `.groups` argument.
head(thongke3)

Dựa vào bảng thống kê trên:

  • Số lượng giao dịch giữa các nhóm không đồng đều, trong đó nhóm Rẻ – Nhỏ và Rẻ – Trung bình chiếm số lượng lớn nhất, cho thấy phân khúc nhà giá rẻ, diện tích nhỏ được giao dịch phổ biến hơn.

  • Giá trung bình tăng dần theo phân khúc:

    • Rất rẻ: khoảng 63.000–71.000 USD,

    • Rẻ: khoảng 199.000–229.000 USD,

    • Trung bình: khoảng 414.000–487.000 USD,

    • Mắc: khoảng 762.000–801.000 USD,

    • Rất mắc: từ 1,52–3,37 triệu USD,

→ cho thấy sự phân tầng giá rõ rệt và hợp lý giữa các nhóm giá.

  • Độ lệch chuẩn (SD) tăng mạnh ở các nhóm cao cấp:

    • Nhóm Rẻ và Trung bình: chỉ khoảng 50.000–84.000 USD,

    • Nhóm Mắc: khoảng 110.000 USD,

    • Trong khi nhóm Rất mắc: dao động từ 1,18–5,63 triệu USD,

→ điều này chứng tỏ phân khúc cao cấp có mức biến động giá lớn hơn nhiều, phản ánh sự đa dạng về quy mô và vị trí.

  • Khoảng giá Q1–Q3 cho thấy phần lớn giao dịch tập trung trong các khoảng:

    • Rất rẻ: 40.000–90.000 USD,

    • Rẻ: 150.000–275.000 USD,

    • Trung bình: 350.000–550.000 USD,

    • Mắc: 670.000–899.000 USD,

    • Rất mắc: 1,15–3,50 triệu USD,

→ phản ánh mức giá phổ biến tương ứng với từng phân khúc.

  • Giá tối thiểu – tối đa trải rộng từ 1 USD đến 165 triệu USD, cho thấy sự chênh lệch cực lớn về giá trị bất động sản, minh chứng thị trường trong dữ liệu này bao gồm cả phân khúc dân cư phổ thông lẫn siêu cao cấp.
#tính thống kê mô tả theo status và mucgianha
thongke4 <- tieuluan %>%
  group_by(status, mucgianha) %>%
  summarise(
    Soluong = n(),
    Giatritb = mean(price, na.rm = TRUE),
    max = max(price, na.rm = TRUE),
    min = min(price, na.rm = TRUE),
    Trungvi = median(price, na.rm = TRUE),
    Dolechchuan = sd(price, na.rm = TRUE),
    Q1 = quantile(price, 0.25, na.rm = TRUE),
    Q3 = quantile(price, 0.75, na.rm = TRUE)
  ) %>%
  arrange(status, mucgianha)
## `summarise()` has grouped output by 'status'. You can override using the
## `.groups` argument.
head(thongke4)

Dựa vào bảng thống kê mô tả theo trạng thái (for_sale/sold) và mức giá (mucgianha):

  • Số lượng giao dịch: dao động khá lớn, từ 20.396 giao dịch (for_sale – Rất rẻ) đến 233.230 giao dịch (sold – Trung bình). Nhóm giao dịch phổ biến nhất là phân khúc tầm trung bình, cho thấy đây là phân khúc được ưa chuộng và phổ biến trên thị trường.

  • Giá trung bình và trung vị:

    • Rất rẻ: trung bình khoảng 70.000 USD, trung vị 74.900 USD,

    • Rẻ: trung bình 213.000 USD, trung vị 219.000 USD,

    • Trung bình: trung bình 430.000 USD, trung vị 420.000 USD,

    • Mắc: trung bình 767.000–764.000 USD, trung vị 749.000 USD,

    • Rất mắc: trung bình 2,54–1,94 triệu USD, trung vị 1,6–1,49 triệu USD,

→ thể hiện sự phân tầng giá rõ rệt theo phân khúc.

  • Độ lệch chuẩn (SD) tăng theo giá:

    • Phân khúc thấp: ~22.000–56.000 USD,

    • Phân khúc cao: ~113.000–4.3 triệu USD,

→ cho thấy biến động giá lớn hơn ở phân khúc cao cấp, giá trị bất động sản đa dạng.

  • Khoảng Q1–Q3:

    • Rất rẻ: 55.000 – 89.000 USD,

    • Rẻ: 168.000 – 260.000 USD,

    • Trung bình: 359.000 – 499.000 USD,

    • Mắc: 674.500 – 850.000 USD,

    • Rất mắc: 1,27 – 2,50 triệu USD,

→ phản ánh phần lớn giao dịch tập trung trong khoảng giá đặc trưng của từng phân khúc.

  • Giá tối thiểu – tối đa trải rộng từ 1 USD đến 515 triệu USD, cho thấy thị trường bao gồm cả bất động sản phổ thông lẫn siêu cao cấp, đồng thời minh chứng biến động giá cực lớn ở phân khúc cao cấp.
#tính thống kê mô tả theo status, mucgianha, và mucdientichnha
thongke5 <- tieuluan %>%
  group_by(status, mucgianha, mucdientichnha) %>%
  summarise(
    Soluong = n(),
    Giatritb = mean(price, na.rm = TRUE),
    max = max(price, na.rm = TRUE),
    min = min(price, na.rm = TRUE),
    Trungvi = median(price, na.rm = TRUE),
    Dolechchuan = sd(price, na.rm = TRUE),
    Q1 = quantile(price, 0.25, na.rm = TRUE),
    Q3 = quantile(price, 0.75, na.rm = TRUE)
  ) %>%
  arrange(status, mucgianha, mucdientichnha)
## `summarise()` has grouped output by 'status', 'mucgianha'. You can override
## using the `.groups` argument.
head(thongke5)

Dựa vào bảng thống kê mô tả theo trạng thái (for_sale/sold) và mức giá (mucgianha):

  • Số lượng giao dịch: dao động từ 3.181 (for_sale – Rất mắc – Nhỏ) đến 233.230 (sold – Trung bình – Trung bình). Nhóm giao dịch phổ biến nhất là phân khúc Trung bình, cho thấy đây là phân khúc được ưa chuộng trên thị trường.

  • Giá trung bình và trung vị:

    • Rất rẻ: trung bình ~70.000 USD, trung vị ~74.850 USD

    • Rẻ: trung bình ~213.000 USD, trung vị ~219.000 USD

    • Trung bình: trung bình ~430.000 USD, trung vị ~420.000 USD

    • Mắc: trung bình ~764.000–804.000 USD, trung vị ~749.000–799.900 USD

    • Rất mắc: trung bình ~1,69–3,67 triệu USD, trung vị ~1,29–2,1 triệu USD

  • Độ lệch chuẩn (SD) tăng theo giá, từ ~22.000–56.000 USD ở phân khúc thấp lên ~113.000–5,48 triệu USD ở phân khúc cao → biến động giá lớn hơn ở phân khúc cao cấp.

  • Khoảng Q1–Q3:

    • Rất rẻ: 55.000 – 89.000 USD

    • Rẻ: 168.000 – 260.000 USD

    • Trung bình: 359.000 – 499.000 USD

    • Mắc: 674.500 – 850.000 USD

    • Rất mắc: 1,27 – 3,79 triệu USD → phần lớn giao dịch nằm trong khoảng giá đặc trưng của từng phân khúc.

  • Giá tối thiểu – tối đa: từ 1 USD đến 515 triệu USD, thể hiện thị trường bao gồm bất động sản phổ thông lẫn siêu cao cấp, biến động giá cực lớn ở phân khúc cao.

#tính thống kê mô tả theo mucgianha,bed,bath
thongke6 <- tieuluan %>%
  group_by(mucgianha, bed, bath) %>%
  summarise(
    Soluong = n(),
    Giatritb = mean(price, na.rm = TRUE),
    max = max(price, na.rm = TRUE),
    min = min(price, na.rm = TRUE),
    Trungvi = median(price, na.rm = TRUE),
    Dolechchuan = sd(price, na.rm = TRUE),
    Q1 = quantile(price, 0.25, na.rm = TRUE),
    Q3 = quantile(price, 0.75, na.rm = TRUE)
  ) %>%
  arrange(mucgianha, bed, bath)
## `summarise()` has grouped output by 'mucgianha', 'bed'. You can override using
## the `.groups` argument.
head(thongke6)

Số lượng giao dịch:

  • Số lượng giao dịch dao động khá lớn, từ 1 giao dịch (Mắc – 1 phòng ngủ – 6 phòng tắm) đến 28.600 giao dịch (Mắc – 3 phòng ngủ – 2 phòng tắm). Nhóm giao dịch phổ biến nhất là 3 phòng ngủ – 2 phòng tắm, cho thấy đây là nhóm căn hộ cao cấp được ưa chuộng và phổ biến trên thị trường.

  • Giá trung bình và trung vị:

    • 1 phòng ngủ: trung bình khoảng 762.000 USD, trung vị 749.000 USD

    • 2 phòng ngủ: trung bình khoảng 759.000–880.000 USD, trung vị 735.000–880.000 USD

    • 3 phòng ngủ: trung bình khoảng 751.000–803.000 USD, trung vị 729.000–787.500 USD

→ Thể hiện sự phân tầng giá rõ rệt theo số phòng, nhóm nhiều phòng có giá cao hơn trung bình.

  • Độ lệch chuẩn (SD) tăng theo số phòng:

    • 1 phòng ngủ: ~102.000–127.000 USD

    • 2 phòng ngủ: ~112.000–138.000 USD

    • 3 phòng ngủ: ~107.000–155.000 USD

→ Cho thấy biến động giá lớn hơn ở những căn hộ nhiều phòng, giá trị bất động sản đa dạng hơn.

  • Khoảng Q1–Q3:

    • 1 phòng ngủ: 675.000 – 840.000 USD

    • 2 phòng ngủ: 659.900 – 895.000 USD

    • 3 phòng ngủ: 658.000 – 932.000 USD

→ Phản ánh phần lớn giao dịch tập trung trong khoảng giá đặc trưng của từng nhóm, giá trị bất động sản tập trung theo số phòng.

  • Giá tối thiểu – tối đa: Từ 600.000 USD đến 999.999 USD, thể hiện thị trường bao gồm cả bất động sản phổ thông lẫn cao cấp.

7 . VẼ ĐỒ THỊ CƠ BẢN VỚI R

# 2️⃣ Biểu đồ đường (Line Plot): Giá theo thứ tự quan sát
plot(tieuluan$price, type = "l", col = "darkred",
     main = "Xu hướng giá",
     xlab = "Thứ tự quan sát", ylab = "Giá (USD)")

Nhận xét: Biểu đồ thể hiện xu hướng giá nhà theo thứ tự quan sát. Dễ thấy rằng phần lớn các mức giá nằm ở khoảng thấp, chỉ có một số ít điểm có giá trị tăng vọt lên rất cao — đây có thể là những ngoại lệ (outliers) do giá nhà siêu đắt hoặc đặc biệt hiếm. Nhìn chung, dữ liệu giá có sự phân tán lớn, không ổn định và xuất hiện nhiều dao động mạnh, cho thấy thị trường nhà ở có sự chênh lệch đáng kể giữa các bất động sản.

# 3️⃣ Biểu đồ cột (Bar Plot): Số lượng nhà theo trạng thái bán

# Tạo bảng tần suất của trạng thái bất động sản
status_count <- table(tieuluan$status)

# Vẽ biểu đồ cột và lưu vị trí các cột
bp <- barplot(status_count,
              main = "Số lượng nhà theo trạng thái",
              xlab = "Trạng thái",
              ylab = "Số lượng",
              col = c("blue", "#FF4FF0"),
              ylim = c(0, max(status_count) * 1.3))  # tăng giới hạn trục Y để không bị che

# Thêm nhãn số lượng trên đỉnh cột (cao hơn một chút)
text(x = bp,
     y = status_count + max(status_count)*0.05,   # đẩy số lên trên 5% chiều cao max
     labels = status_count,
     pos = 3,              # đặt phía trên cột
     cex = 0.9,            # cỡ chữ
     font = 2,             # chữ in đậm
     col = "black")        # màu chữ

Nhận xét: Biểu đồ cho thấy sự phân bố số lượng nhà theo trạng thái. Trong đó, số lượng nhà đã bán (sold) là 606,957 căn, cao hơn đáng kể so với nhà đang rao bán (for_sale) với 478,096 căn. Điều này cho thấy phần lớn bất động sản trong dữ liệu đã được giao dịch thành công, phản ánh thị trường nhà ở có nhu cầu mua cao và tốc độ tiêu thụ tốt. Tuy nhiên, vẫn còn một lượng lớn nhà đang chờ bán, cho thấy nguồn cung vẫn khá dồi dào.

# 6️⃣ Biểu đồ tròn (Pie Chart): Tỷ lệ nhà theo trạng thái

# Tạo bảng đếm số lượng từng trạng thái (for_sale, sold,...)
status_count <- table(tieuluan$status)

# Tính tỷ lệ phần trăm cho từng nhóm
percent <- round(100 * status_count / sum(status_count), 1)   # Làm tròn 1 chữ số thập phân

# Tạo nhãn hiển thị cả tên và tỷ lệ %
labels <- paste(names(status_count), "-", percent, "%")

# Vẽ biểu đồ tròn với nhãn % rõ ràng
pie(status_count,
    labels = labels,                         # Hiển thị nhãn gồm tên + %
    main = "Tỷ lệ nhà theo trạng thái",      # Tiêu đề biểu đồ
    col = c("blue", "#FF4FF0"),           # Màu sắc từng phần
    border = "white")                        # Viền trắng cho rõ ràng

Nhận xét: Biểu đồ tròn thể hiện tỷ lệ nhà theo trạng thái cho thấy nhà đã bán (sold) chiếm 55.9%, cao hơn so với nhà đang rao bán (for_sale) là 44.1%. Điều này cho thấy phần lớn bất động sản trong dữ liệu đã được giao dịch thành công, phản ánh thị trường có sức mua tốt. Tuy nhiên, tỷ lệ nhà còn đang rao bán vẫn khá lớn, chứng tỏ nguồn cung vẫn dồi dào và thị trường vẫn đang trong trạng thái hoạt động sôi động.

 #Biểu đồ hộp (Box Plot): Giá theo trạng thái bán
boxplot(price ~ status, data = tieuluan,
        main = "So sánh giá giữa các trạng thái bất động sản",
        xlab = "Trạng thái", ylab = "Giá (USD)",
        col = c("orange", "lightblue"))

Nhận xét: Biểu đồ hộp cho thấy giá nhà ở hai trạng thái for_sale và sold có phân bố khá tương đồng, với phần lớn các giá trị tập trung ở mức thấp và xuất hiện một số ngoại lệ (outliers) có giá rất cao. Điều này cho thấy đa số nhà có giá trung bình thấp, trong khi chỉ một số ít bất động sản có giá trị đặc biệt lớn. Nhìn chung, không có sự khác biệt rõ ràng giữa giá nhà đang bán và giá nhà đã bán, chứng tỏ mức giá trung bình giữa hai nhóm tương đối giống nhau.

boxplot(price ~ status,
        data = tieuluan[tieuluan$price <= 1e7, ],
        main = "So sánh giá giữa các trạng thái (≤ 10 triệu USD)",
        xlab = "Trạng thái",
        ylab = "Giá (USD)",
        col = c("#FF6E00", "green"))

Nhận xét: Biểu đồ hộp thể hiện sự so sánh giá nhà giữa hai trạng thái for_sale và sold (giới hạn ở mức ≤ 10 triệu USD). Nhìn chung, phân bố giá ở hai nhóm khá tương đồng, với phần lớn các giá trị tập trung ở mức thấp và chỉ có một số ít ngoại lệ có giá cao. Giá trung vị của hai nhóm gần như ngang nhau, cho thấy mức giá trung bình giữa nhà đang bán và nhà đã bán không chênh lệch nhiều. Tuy nhiên, phạm vi giá của nhóm for_sale có vẻ rộng hơn một chút, thể hiện sự đa dạng hơn về giá trong các bất động sản đang được rao bán.

# 8️⃣ Biểu đồ hộp (Boxplot) cho số phòng ngủ
boxplot(tieuluan$bed,
        main = "Phân phối số phòng ngủ",
        ylab = "Số lượng phòng ngủ",
        col = "#9D00FF")

Nhận xét: Biểu đồ hộp cho thấy phần lớn các căn nhà có số phòng ngủ ở mức thấp, tập trung chủ yếu từ 2 đến 5 phòng ngủ. Tuy nhiên, có một số ngoại lệ (outliers) với số lượng phòng ngủ rất cao, thậm chí vượt quá 400, cho thấy sự tồn tại của một vài bất động sản đặc biệt lớn hoặc dữ liệu bất thường. Nhìn chung, phân bố số phòng ngủ lệch phải mạnh, tức là đa số nhà có ít phòng ngủ, còn các trường hợp có nhiều phòng chỉ chiếm tỷ lệ rất nhỏ.

# Biểu đồ hộp (Box Plot): Phân phối số lượng phòng ngủ của các bất động sản có <= 10 phòng
boxplot(tieuluan$bed[tieuluan$bed <= 10],   # Lấy các giá trị bed nhỏ hơn hoặc bằng 10
        main = "Phân phối số phòng ngủ (<= 10)",  # Tiêu đề biểu đồ
        ylab = "Số lượng phòng ngủ",              # Nhãn trục tung
        col = "#9D00FF")                        # Màu của hộp

Nhận xét:Biểu đồ hộp cho thấy phần lớn các căn nhà có số phòng ngủ tập trung trong khoảng từ 2 đến 4 phòng, tức là đa số bất động sản có quy mô vừa phải. Trung vị nằm khoảng 3 phòng ngủ, phản ánh mức phổ biến nhất trong dữ liệu. Tuy nhiên, vẫn có một số ngoại lệ (outliers) với số lượng phòng ngủ cao hơn (từ 6 đến 10 phòng), cho thấy sự tồn tại của một vài căn nhà đặc biệt lớn so với phần còn lại. Nhìn chung, phân bố hơi lệch phải, nghĩa là hầu hết các căn nhà có ít phòng ngủ, còn những căn có nhiều phòng chỉ chiếm tỷ lệ nhỏ.

# 1️⃣ Biểu đồ cột thể hiện tần suất số phòng ngủ
bedroom_freq <- table(tieuluan$bed)

barplot(bedroom_freq,
        main = "Tần suất số phòng ngủ",
        xlab = "Số phòng ngủ", ylab = "Số lượng nhà",
        col = "yellow",
        ylim = c(0, max(bedroom_freq) * 1.2)) # Chừa chỗ hiển thị số

# Hiển thị số lượng trên đầu cột
text(x = seq_along(bedroom_freq),
     y = bedroom_freq,
     labels = bedroom_freq,
     pos = 3, cex = 0.8, col = "black")

Nhận xét:Biểu đồ cho thấy đa số các căn nhà có từ 1 đến 4 phòng ngủ, trong đó 3 phòng ngủ chiếm tỷ lệ cao nhất. Khi số phòng ngủ tăng lên, số lượng nhà giảm mạnh, gần như rất ít căn có trên 10 phòng. Điều này cho thấy phần lớn bất động sản thuộc loại quy mô vừa và nhỏ, phù hợp với nhu cầu của các hộ gia đình. Nhìn chung, phân bố lệch phải rõ rệt, tức là tập trung nhiều ở nhóm ít phòng và giảm dần khi số phòng tăng.

# 2️⃣ Biểu đồ cột thể hiện tần suất số phòng tắm
bathroom_freq <- table(tieuluan$bath)

barplot(bathroom_freq,
        main = "Tần suất số phòng tắm",
        xlab = "Số phòng tắm", ylab = "Số lượng nhà",
        col = "lightcoral",
        ylim = c(0, max(bathroom_freq) * 1.2))

# Hiển thị số lượng trên đầu cột
text(x = seq_along(bathroom_freq),
     y = bathroom_freq,
     labels = bathroom_freq,
     pos = 3, cex = 0.8, col = "black")

Nhận xét: Biểu đồ cho thấy đa số các căn nhà có từ 1 đến 3 phòng tắm, trong đó 2 phòng tắm là phổ biến nhất. Khi số phòng tắm tăng lên, tần suất giảm rõ rệt, hầu như rất ít căn có trên 10 phòng tắm. Điều này phản ánh rằng phần lớn bất động sản có quy mô sinh hoạt trung bình, phù hợp với nhu cầu hộ gia đình thông thường. Nhìn chung, phân bố lệch phải, tức là tập trung chủ yếu ở nhóm ít phòng tắm và giảm dần khi số phòng tăng.

# 9️⃣ Biểu đồ cột (Barplot) — 10 thành phố có nhiều nhà nhất
# 🟢 B1: Lấy top 10 thành phố có nhiều nhà nhất
top_cities <- sort(table(tieuluan$city), decreasing = TRUE)[1:10]

# 🟢 B2: Vẽ biểu đồ cột
bp <- barplot(top_cities,
              las = 2,                       # Xoay nhãn trục X cho dễ đọc
              col = "turquoise",
              main = "Top 10 thành phố có nhiều nhà nhất",
              ylab = "Số lượng nhà",
              cex.names = 0.8)

# 🟢 B3: Thêm số lên đỉnh cột
text(x = bp, 
     y = top_cities, 
     labels = top_cities, 
     pos = 3,               # Hiển thị phía trên đầu cột
     cex = 0.8, 
     col = "black",
     font = 2)              # In đậm số

Nhận xét:Biểu đồ cho thấy Houston là thành phố có số lượng nhà nhiều nhất, vượt trội so với các thành phố còn lại. Các vị trí tiếp theo lần lượt là Tucson, Phoenix, Los Angeles và Dallas, nhưng số lượng nhà thấp hơn đáng kể. Nhìn chung, sự chênh lệch giữa Houston và nhóm còn lại khá lớn, cho thấy thị trường nhà ở tại Houston có quy mô nổi bật hơn so với các khu vực khác.

# 🍩 Biểu đồ tròn (Pie Chart) — Top 10 bang có nhiều nhà nhất
library(dplyr)

# 🟢 B1: Lấy top 10 bang có nhiều nhà nhất
top_state <- tieuluan %>%
  count(state, sort = TRUE) %>%
  top_n(10, n)

# 🟢 B2: Vẽ biểu đồ tròn không có đường viền
pie(top_state$n,
    labels = paste(top_state$state, round(100 * top_state$n / sum(top_state$n), 1), "%"),
    main = "Top 10 bang có nhiều nhà nhất",
    col = rainbow(10),
    border = NA)   # Bỏ đường phân chia giữa các mảnh

Nhận xét:Biểu đồ cho thấy California là bang có số lượng nhà nhiều nhất, chiếm khoảng 23,8%, vượt trội so với các bang khác. Florida và Texas lần lượt đứng thứ hai và ba với tỷ lệ lần lượt 16,2% và 16%. Các bang còn lại như Arizona, Pennsylvania, Georgia, Washington hay New York chiếm tỷ lệ nhỏ hơn, dưới 8%. Nhìn chung, nhà tập trung chủ yếu ở các bang lớn và đông dân, phản ánh sự phát triển mạnh của thị trường bất động sản tại những khu vực này.

# 1️⃣ Đếm số lượng nhà theo thành phố
city_count <- sort(table(tieuluan$city), decreasing = FALSE)

# 2️⃣ Lấy 10 thành phố có ít nhà nhất
city_min10 <- head(city_count, 10)

# 3️⃣ Vẽ biểu đồ cột ngang
barplot(city_min10,
        horiz = TRUE,
        main = "Top 10 thành phố có ÍT nhà nhất",
        xlab = "Số lượng nhà",
        col = "#FF66A3",
        las = 1)  # Xoay nhãn trục Y cho dễ đọc

# 4️⃣ Thêm số lượng bên phải mỗi cột
text(x = city_min10,
     y = seq_along(city_min10),
     labels = city_min10,
     pos = 4,   # Hiện bên phải cột
     cex = 0.8)

Nhận xét: Biểu đồ thể hiện 10 thành phố có ít nhà nhất. Dễ thấy rằng tất cả các thành phố trong danh sách như Adin, Addyston, Addington Township, hay Abbott đều chỉ có khoảng 1 căn nhà, gần như không có sự khác biệt đáng kể giữa các thành phố. Điều này cho thấy đây là những khu vực dân cư cực kỳ thưa thớt hoặc ít được ghi nhận trong dữ liệu, có thể là vùng nông thôn, khu vực hẻo lánh, hoặc chỉ có số lượng nhà ở rất hạn chế.

# 1️⃣ Đếm số lượng nhà theo bang
state_count <- sort(table(tieuluan$state), decreasing = FALSE)

# 2️⃣ Lấy 10 bang có ít nhà nhất
state_min10 <- head(state_count, 10)

# 3️⃣ Vẽ biểu đồ cột ngang
barplot(state_min10,
        horiz = TRUE,
        main = "Top 10 bang có ÍT nhà nhất",
        xlab = "Số lượng nhà",
        col = "#006600",
        las = 1)

# 4️⃣ Thêm số lượng bên phải mỗi cột
text(x = state_min10,
     y = seq_along(state_min10),
     labels = state_min10,
     pos = 4,
     cex = 0.8)

Nhận xét: Biểu đồ thể hiện số lượng nhà ở của 10 bang có ít nhà nhất. Trong đó, Mississippi có nhiều nhà nhất trong nhóm (gần 2.000 căn), cao hơn đáng kể so với các bang khác. North Dakota và New Hampshire lần lượt đứng thứ hai và ba với khoảng 1.200 và 770 căn. Ở chiều ngược lại, Puerto Rico và đặc biệt là Virgin Islands có số lượng nhà rất ít, chỉ vài trăm căn hoặc ít hơn. Điều này cho thấy sự chênh lệch khá lớn giữa các bang — có thể do khác biệt về quy mô dân số, diện tích đất ở hoặc mức độ phát triển đô thị.

# 🍩 Biểu đồ tròn — Tỷ lệ nhà ở 10 bang có ít nhà nhất
# 🟠 1️⃣ Lấy top 10 bang có ít nhà nhất
state_freq <- sort(table(tieuluan$state))    # Đếm số lượng nhà theo bang
top10_states <- head(state_freq, 10)             # Lấy 10 bang ít nhà nhất

# 🟠 2️⃣ Tính tỷ lệ %
percent_labels <- round(top10_states / sum(top10_states) * 100, 2)
labels <- paste(names(top10_states), "-", percent_labels, "%")

# 🟠 3️⃣ Vẽ biểu đồ tròn (không viền giữa các mảnh)
pie(top10_states,
    labels = labels,
    main = "Tỷ lệ nhà ở 10 bang có ít nhà nhất",
    col = rainbow(length(top10_states)),
    border = NA)  # Loại bỏ đường phân chia

Nhận xét: Biểu đồ cho thấy trong 10 bang có ít nhà nhất, Mississippi vẫn chiếm tỷ lệ lớn nhất (32.78%), nghĩa là số nhà ở đây nhiều hơn hẳn các bang còn lại trong nhóm. North Dakota và New Hampshire đứng kế tiếp với khoảng 17.52% và 11.06%. Các bang như Alaska, Puerto Rico và đặc biệt là Virgin Islands có tỷ lệ rất nhỏ, thể hiện số lượng nhà rất ít. Nhìn chung, biểu đồ cho thấy sự chênh lệch rõ rệt giữa các bang — có nơi vẫn có khá nhiều nhà, trong khi một số vùng rất ít, có thể do diện tích nhỏ, dân cư thưa hoặc điều kiện sống khác nhau.

# 🔟 Biểu đồ phân tán (Scatter Plot - log scale, có lọc dữ liệu)
tieuluan_log <- subset(tieuluan, acre_lot > 0 & house_size > 0)

plot(log10(tieuluan_log$acre_lot), log10(tieuluan_log$house_size),
     main = "Mối quan hệ giữa diện tích đất và diện tích nhà (thang log)",
     xlab = "Log10(Acre_lot)", ylab = "Log10(House Size)",
     col = "lightpink", pch = 19, cex = 0.5)

# Thêm đường hồi quy tuyến tính
abline(lm(log10(house_size) ~ log10(acre_lot), data = tieuluan_log), col = "black", lwd = 3)

Nhận xét: Biểu đồ thể hiện mối quan hệ thuận chiều nhẹ giữa diện tích đất và diện tích nhà trên thang log, thể hiện qua đường hồi quy có độ dốc nhỏ dương. Khi diện tích đất tăng, diện tích nhà cũng có xu hướng tăng, nhưng mức độ tương quan không mạnh, do các điểm dữ liệu phân tán khá rộng. Điều này cho thấy dù lô đất lớn thường đi kèm nhà rộng hơn, song diện tích nhà còn phụ thuộc vào thiết kế, mục đích sử dụng và mật độ xây dựng của từng khu vực.

plot(
log(tieuluan$house_size), log(tieuluan$price),
  main = "Log-Log Plot: Diện tích nhà và Giá bán",
  xlab = "log(Diện tích nhà)",
  ylab = "log(Giá bán)",
  col = "lightgreen", pch = 19
)
abline(lm(log(price) ~ log(house_size), data = tieuluan), col = "red", lwd = 3)

Nhận xét: Biểu đồ log-log cho thấy mối quan hệ thuận chiều giữa diện tích nhà và giá bán, thể hiện qua đường hồi quy có độ dốc dương. Khi diện tích nhà tăng, giá bán cũng có xu hướng tăng theo, dù mức độ tăng không hoàn toàn tỷ lệ thuận. Các điểm dữ liệu phân tán khá rộng, cho thấy ngoài diện tích, giá nhà còn chịu ảnh hưởng bởi nhiều yếu tố khác như vị trí, tiện ích, hay chất lượng xây dựng. Nhìn chung, kết quả khẳng định diện tích là một trong những yếu tố quan trọng tác động đến giá bất động sản.

7.1 . Trực quan hóa bằng ggplot2

#Số lượng nhà theo mức diện tích & trạng thái bán
ggplot(tieuluan, aes(x = mucdientichnha, fill = status)) +
  geom_bar(position = "dodge") +
  geom_text(stat = "count", aes(label = ..count..),
            position = position_dodge(width = 0.9), vjust = -0.3, size = 3) +
  scale_fill_manual(values = c("#9A7", "red")) +
  labs(title = "Trạng thái bán theo mức diện tích nhà",
       x = "Mức diện tích", y = "Số lượng nhà") +
  theme_minimal()
## Warning: The dot-dot notation (`..count..`) was deprecated in ggplot2 3.4.0.
## ℹ Please use `after_stat(count)` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

Nhận xét: Biểu đồ cho thấy nhà có diện tích “trung bình” chiếm số lượng lớn nhất ở cả hai trạng thái, với 296.236 căn đang rao bán và 367.486 căn đã bán, chứng tỏ đây là phân khúc phổ biến và dễ tiêu thụ nhất trên thị trường. Nhà có diện tích “nhỏ” cũng ghi nhận lượng lớn, đặc biệt 216.536 căn đã bán so với 147.819 căn đang rao bán, phản ánh nhu cầu cao với loại hình nhà phù hợp thu nhập trung bình. Ngược lại, nhà “lớn” có số lượng ít nhất (34.041 rao bán, 22.935 đã bán), cho thấy phân khúc này kén người mua và có tính thanh khoản thấp.

ggplot(tieuluan %>% filter(status == "sold"), 
       aes(x = mucgianha, fill = mucgianha)) +
  geom_bar() +
  geom_text(stat = "count", aes(label = ..count..), 
            hjust = -0.2, size = 4) +
  coord_flip() +
  labs(
    title = "Số lượng nhà đã bán theo mức giá",
    x = "Mức giá",
    y = "Số lượng nhà"
  ) +
  scale_fill_manual(values = c("#023E8A", "#0077B6", "#00B4D8", "#48CAE4", "#90EE90")) +
  theme_minimal(base_size = 13) +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    legend.position = "none"
  )

Nhận xét: Biểu đồ cho thấy phần lớn các căn nhà đã bán thuộc nhóm giá “trung bình” và “rẻ”, lần lượt 231.774 và 203.941 căn, chiếm tỷ trọng lớn nhất. Trong khi đó, các nhóm “mắc” và “rất mắc” có số lượng thấp hơn, lần lượt 93.698 và 49.159 căn, còn “rất rẻ” chỉ đạt 26.930 căn. Điều này cho thấy phân khúc giá tầm trung và rẻ có sức mua mạnh nhất, phản ánh nhu cầu thị trường tập trung chủ yếu vào các loại nhà có giá phù hợp với thu nhập của đa số người dân, trong khi phân khúc cao cấp có tính thanh khoản thấp hơn.

ggplot(tieuluan %>% filter(status == "for_sale"), 
       aes(x = mucgianha, fill = mucgianha)) +
  geom_bar() +
  geom_text(stat = "count", aes(label = ..count..), 
            hjust = -0.2, size = 4) +
  coord_flip() +
  labs(
    title = "Số lượng nhà đang rao bán theo mức giá",
    x = "Mức giá",
    y = "Số lượng nhà"
  ) +
  scale_fill_manual(values = c("#7B2CBF", "#9D4EDD", "#C77DFF", "#E45A84", "#FF006E")) +
  theme_minimal(base_size = 13) +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    legend.position = "none"
  )

Nhận xét: Biểu đồ cho thấy nhà đang rao bán chủ yếu thuộc nhóm giá “trung bình”, chiếm số lượng lớn nhất với 181.893 căn, tiếp theo là “rẻ” với 145.924 căn. Các nhóm “mắc” và “rất mắc” có số lượng thấp hơn, lần lượt 77.858 và 52.969 căn, trong khi nhóm “rất rẻ” chỉ có 20.396 căn. Điều này phản ánh thị trường tập trung mạnh vào phân khúc trung bình và rẻ, phù hợp với nhu cầu và khả năng chi trả của phần lớn người mua nhà, còn phân khúc cao cấp ít được rao bán hơn, cho thấy tính thanh khoản thấp và kén khách ở mức giá cao.

# Chuẩn bị dữ liệu
pie_data <- tieuluan %>%
  group_by(status, mucdientichnha) %>%
  summarise(count = n()) %>%
  mutate(ty_le = count / sum(count) * 100)
## `summarise()` has grouped output by 'status'. You can override using the
## `.groups` argument.
# Vẽ biểu đồ tròn với màu từ vàng sang hồng
ggplot(pie_data, aes(x = "", y = ty_le, fill = mucdientichnha)) +
  geom_col(width = 1, color = "white") +
  coord_polar(theta = "y") +
  facet_wrap(~status) +
  geom_text(aes(label = paste0(round(ty_le, 1), "%")),
            position = position_stack(vjust = 0.5), color = "darkblue", size = 4) +
  scale_fill_manual(values = c("#FFD700", "#FFB6C1", "#FF69B4", "#FF1493")) +
  labs(title = "Tỷ lệ trạng thái theo mức diện tích nhà",
       fill = "Mức diện tích") +
  theme_void(base_size = 13) +
  theme(plot.title = element_text(hjust = 0.5, face = "bold"))

Nhận xét: Biểu đồ cho thấy ở cả hai trạng thái “đang bán” (for sale) và “đã bán” (sold), nhà có diện tích trung bình chiếm tỷ lệ cao nhất, lần lượt 62% và 60,5%. Tiếp theo là nhóm nhỏ, chiếm 30,9% ở nhà đang bán và 35,7% ở nhà đã bán. Nhóm lớn chiếm tỷ lệ rất thấp, chỉ khoảng 7,1% và 3,8%. Điều này cho thấy thị trường chủ yếu tập trung vào phân khúc nhà diện tích nhỏ và trung bình, phù hợp với nhu cầu và khả năng tài chính của đa số người mua. Các căn có diện tích lớn ít giao dịch hơn, hàm ý rằng phân khúc cao cấp kém sôi động và kén người mua hơn.

# Lọc nhà đã bán
sold_data <- tieuluan %>% filter(status == "sold")

# Tính tỷ lệ theo nhóm diện tích đất
data_pie <- sold_data %>%
  count(dientichdat) %>%
  mutate(tyle = round(n / sum(n) * 100, 2),
         label = paste0(dientichdat, " - ", tyle, "%"))

# Vẽ biểu đồ tròn
ggplot(data_pie, aes(x = "", y = n, fill = dientichdat)) +
  geom_bar(stat = "identity", width = 1) +
  coord_polar("y") +
  geom_text(aes(label = label),
            position = position_stack(vjust = 0.5),
            size = 4) +
  labs(title = "Tỷ lệ nhà đã bán theo diện tích đất") +
  theme_void() +
  theme(plot.title = element_text(hjust = 0.5, face = "bold"))

Nhận xét: Biểu đồ tròn cho thấy phần lớn nhà đã bán có diện tích đất rất nhỏ, chiếm 52,19% tổng số, tiếp đến là nhóm nhỏ với 28,88%. Các nhóm vừa, lớn và rất lớn chiếm tỷ lệ thấp hơn, lần lượt là 7,6%, 8,25% và 3,08%. Kết quả này cho thấy nguồn cung và nhu cầu giao dịch chủ yếu tập trung ở phân khúc nhà có diện tích nhỏ và rất nhỏ, phù hợp với khả năng tài chính của phần lớn người mua. Ngược lại, các căn có diện tích lớn chiếm tỷ trọng thấp, phản ánh thị trường nhà đất cao cấp kém sôi động hơn so với phân khúc bình dân.

#  Lọc nhà đang cho thuê
rent_data <- tieuluan %>% filter(status == "for_sale")

#  Tính tỷ lệ theo nhóm diện tích đất
data_pie_rent <- rent_data %>%
  count(dientichdat) %>%
  mutate(tyle = round(n / sum(n) * 100, 2),
         label = paste0(dientichdat, " - ", tyle, "%"))

#  Vẽ biểu đồ tròn
ggplot(data_pie_rent, aes(x = "", y = n, fill = dientichdat)) +
  geom_bar(stat = "identity", width = 1) +
  coord_polar("y") +
  geom_text(aes(label = label),
            position = position_stack(vjust = 0.5),
            size = 4) +
  labs(title = "Tỷ lệ nhà đang cho thuê theo diện tích đất") +
  theme_void() +
  theme(plot.title = element_text(hjust = 0.5, face = "bold"))

Nhận xét: Biểu đồ tròn cho thấy phần lớn nhà đang cho thuê có diện tích đất rất nhỏ, chiếm 45,92% tổng số, tiếp đến là nhóm nhỏ với 30,93%. Các nhóm vừa, lớn và rất lớn chiếm tỷ lệ thấp hơn, lần lượt là 9%, 10,03% và 4,12%. Điều này cho thấy nguồn cung nhà cho thuê chủ yếu thuộc phân khúc diện tích nhỏ và rất nhỏ, phù hợp với nhu cầu ở thực hoặc thuê ngắn hạn tại khu vực đô thị. Ngược lại, các căn có diện tích lớn chiếm tỷ trọng thấp, hàm ý rằng thị trường cho thuê ít tập trung vào phân khúc nhà cao cấp hoặc diện tích rộng.

library(dplyr)

freq_table <- tieuluan %>%
  group_by(mucgianha, mucdientichnha) %>%
  summarise(count = n()) %>%
  ungroup()
## `summarise()` has grouped output by 'mucgianha'. You can override using the
## `.groups` argument.
ggplot(freq_table, aes(x = mucdientichnha, y = mucgianha, fill = count)) +
  geom_tile(color = "white") +
  scale_fill_gradient(low = "lightyellow", high = "darkred") +
  theme_minimal() +
  labs(x = "Diện tích nhà", y = "Mức giá nhà", fill = "Số lượng")

Nhận xét: Biểu đồ thể hiện mối quan hệ giữa diện tích và mức giá nhà thông qua số lượng quan sát. Phần lớn các căn nhà tập trung ở nhóm diện tích nhỏ và trung bình, trong đó nổi bật nhất là nhóm “trung bình – diện tích trung bình” với số lượng cao nhất (khoảng trên 300.000 căn). Nhóm “rẻ – nhỏ” và “mắc – trung bình” cũng chiếm tỷ trọng đáng kể, phản ánh xu hướng thị trường tập trung nhiều vào phân khúc nhà có diện tích vừa phải, giá tầm trung. Ngược lại, nhóm “rất mắc” và “rất rẻ” có số lượng thấp, cho thấy phân khúc quá cao cấp hoặc quá rẻ ít phổ biến. Điều này hàm ý rằng thị trường bất động sản chủ yếu phục vụ nhu cầu ở thực, hướng tới nhà có giá và diện tích trung bình, thay vì các phân khúc cực đoan.

ggplot(tieuluan, aes(x = log(house_size_m2 + 1), y = log(price + 1), color = mucgianha)) +
  geom_point(alpha = 0.2) +  # alpha thấp vì dataset lớn
  theme_minimal() +
  labs(
    x = "log(Diện tích nhà m²)",
    y = "log(Giá nhà)",
    color = "Mức giá"
  )

Nhận xét: Biểu đồ thể hiện mối quan hệ tỷ lệ thuận giữa diện tích và giá nhà, khi log(diện tích nhà) tăng thì log(giá nhà) cũng tăng tương ứng. Phần lớn các căn nhà có log(diện tích từ 4,5–7) và log(giá từ 10–15), thể hiện phân khúc phổ biến trên thị trường. Nhóm “rất mắc” tập trung ở vùng giá trên 15, tương ứng với các căn có diện tích lớn và giá trị cao, trong khi “rẻ” và “rất rẻ” nằm ở vùng giá dưới 11, chủ yếu là nhà nhỏ. Tuy nhiên, các mức giá vẫn chồng lấn đáng kể, cho thấy giá nhà không chỉ phụ thuộc vào diện tích mà còn chịu ảnh hưởng bởi vị trí, chất lượng xây dựng và tiện ích xung quanh, phản ánh sự đa dạng và phân hóa rõ rệt của thị trường bất động sản.