Đặng Thùy Dung - MSSV: 2221000296
Đỗ Nguyễn Nhật Minh - MSSV: 2321000336
Giảng viên hướng dẫn: ThS. Trần Mạnh Tường
LỜI CẢM ƠN
Nhóm thực hiện xin gửi lời cảm ơn sâu sắc đến giảng viên hướng dẫn ThS.Trần Mạnh Tường đã tận tình hướng dẫn và giải đáp những thắc mắc trong suốt quá trình thực hiện đề tài. Vì sự hạn chế về kiến thức cũng như kỹ năng nên đề tài còn những thiếu sót. Kính mong thầy đánh giá và đóng góp cải thiện để đề tài được hoàn thiện hơn trong tương lai.
PHẦN 1: PHÂN TÍCH HÀNH VI MUA SẮM CỦA KHÁCH HÀNG THEO ĐẶC ĐIỂM NHÂN KHẨU HỌC
library(readxl)
## Warning: package 'readxl' was built under R version 4.4.3
library(data.table)
## Warning: package 'data.table' was built under R version 4.4.3
library(dplyr)
## Warning: package 'dplyr' was built under R version 4.4.3
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:data.table':
##
## between, first, last
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(tidyr)
## Warning: package 'tidyr' was built under R version 4.4.3
# 1. Đọc dữ liệu
file_path <- "customers_data.xlsx"
data <- read_excel(file_path)
# 2. Xem tổng quan kích thước dữ liệu
num_rows <- nrow(data) # số quan sát
num_cols <- ncol(data) # số biến
cat("Số quan sát:", num_rows, "\n")
## Số quan sát: 100000
cat("Số biến:", num_cols, "\n")
## Số biến: 12
# 3. Tên các biến trong bộ dữ liệu
names(data)
## [1] "id" "age" "gender"
## [4] "income" "education" "region"
## [7] "loyalty_status" "purchase_frequency" "purchase_amount"
## [10] "product_category" "promotion_usage" "satisfaction_score"
# 4. Kiểm tra kiểu dữ liệu của từng biến
sapply(data, class)
## id age gender income
## "numeric" "numeric" "character" "numeric"
## education region loyalty_status purchase_frequency
## "character" "character" "character" "character"
## purchase_amount product_category promotion_usage satisfaction_score
## "numeric" "character" "numeric" "numeric"
# 5. Kiểm tra giá trị thiếu
missing_total <- sum(is.na(data))
missing_by_var <- colSums(is.na(data))
cat("Tổng số giá trị thiếu:", missing_total, "\n")
## Tổng số giá trị thiếu: 0
missing_by_var
## id age gender income
## 0 0 0 0
## education region loyalty_status purchase_frequency
## 0 0 0 0
## purchase_amount product_category promotion_usage satisfaction_score
## 0 0 0 0
# 6. Kiểm tra các dòng bị trùng lặp
dup_total <- sum(duplicated(data))
cat("Số quan sát trùng lặp:", dup_total, "\n")
## Số quan sát trùng lặp: 0
# 7. Kiểm tra cấu trúc chi tiết của dữ liệu
str(data) # Xem cấu trúc: tên biến, kiểu dữ liệu, ví dụ giá trị
## tibble [100,000 × 12] (S3: tbl_df/tbl/data.frame)
## $ id : num [1:100000] 1 2 3 4 5 6 7 8 9 10 ...
## $ age : num [1:100000] 27 29 37 30 31 38 32 24 27 28 ...
## $ gender : chr [1:100000] "Male" "Male" "Male" "Male" ...
## $ income : num [1:100000] 40682 15317 38849 11568 46952 ...
## $ education : chr [1:100000] "Bachelor" "Masters" "Bachelor" "HighSchool" ...
## $ region : chr [1:100000] "East" "West" "West" "South" ...
## $ loyalty_status : chr [1:100000] "Gold" "Regular" "Silver" "Regular" ...
## $ purchase_frequency: chr [1:100000] "frequent" "rare" "rare" "frequent" ...
## $ purchase_amount : num [1:100000] 18249 4557 11822 4098 19685 ...
## $ product_category : chr [1:100000] "Books" "Clothing" "Clothing" "Food" ...
## $ promotion_usage : num [1:100000] 0 1 0 0 1 0 0 0 0 0 ...
## $ satisfaction_score: num [1:100000] 6 6 6 7 5 5 7 5 5 6 ...
# 8. Tóm tắt mô tả thống kê cơ bản (cho mọi biến)
summary(data) # Trung bình, min, max, quartile, v.v.
## id age gender income
## Min. : 1 Min. :12 Length:100000 Min. : 5000
## 1st Qu.: 25001 1st Qu.:27 Class :character 1st Qu.:16272
## Median : 50001 Median :30 Mode :character Median :27585
## Mean : 50001 Mean :30 Mean :27516
## 3rd Qu.: 75000 3rd Qu.:33 3rd Qu.:38747
## Max. :100000 Max. :49 Max. :50000
## education region loyalty_status purchase_frequency
## Length:100000 Length:100000 Length:100000 Length:100000
## Class :character Class :character Class :character Class :character
## Mode :character Mode :character Mode :character Mode :character
##
##
##
## purchase_amount product_category promotion_usage satisfaction_score
## Min. : 1118 Length:100000 Min. :0.0000 Min. : 0.00
## 1st Qu.: 5583 Class :character 1st Qu.:0.0000 1st Qu.: 4.00
## Median : 9452 Mode :character Median :0.0000 Median : 5.00
## Mean : 9635 Mean :0.3008 Mean : 5.01
## 3rd Qu.:13350 3rd Qu.:1.0000 3rd Qu.: 6.00
## Max. :26204 Max. :1.0000 Max. :10.00
# 9. Kiểm tra dữ liệu rỗng hoặc khoảng trắng trong biến ký tự
char_vars <- names(Filter(is.character, data))
for (v in char_vars) {
empty_count <- sum(trimws(data[[v]]) == "", na.rm = TRUE)
cat("Biến", v, "có", empty_count, "giá trị rỗng\n")
}
## Biến gender có 0 giá trị rỗng
## Biến education có 0 giá trị rỗng
## Biến region có 0 giá trị rỗng
## Biến loyalty_status có 0 giá trị rỗng
## Biến purchase_frequency có 0 giá trị rỗng
## Biến product_category có 0 giá trị rỗng
# 10. Xem trước vài dòng đầu của dữ liệu
head(data, 10)
## # A tibble: 10 × 12
## id age gender income education region loyalty_status purchase_frequency
## <dbl> <dbl> <chr> <dbl> <chr> <chr> <chr> <chr>
## 1 1 27 Male 40682 Bachelor East Gold frequent
## 2 2 29 Male 15317 Masters West Regular rare
## 3 3 37 Male 38849 Bachelor West Silver rare
## 4 4 30 Male 11568 HighSchool South Regular frequent
## 5 5 31 Female 46952 College North Regular occasional
## 6 6 38 Male 7347 Bachelor South Silver occasional
## 7 7 32 Female 8265 Bachelor South Silver frequent
## 8 8 24 Female 47773 HighSchool North Regular rare
## 9 9 27 Male 19154 College East Regular occasional
## 10 10 28 Female 24666 HighSchool North Regular rare
## # ℹ 4 more variables: purchase_amount <dbl>, product_category <chr>,
## # promotion_usage <dbl>, satisfaction_score <dbl>
library(knitr)
## Warning: package 'knitr' was built under R version 4.4.3
library(kableExtra)
## Warning: package 'kableExtra' was built under R version 4.4.3
##
## Attaching package: 'kableExtra'
## The following object is masked from 'package:dplyr':
##
## group_rows
#1.. Chuẩn hóa tên biến về dạng chuẩn
names(data) <- trimws(names(data))
names(data) <- gsub(" ", "_", names(data))
names(data) <- tolower(names(data))
#2. Loại bỏ trùng lặp
data <- distinct(data)
#3. Chuyển kiểu dữ liệu
data$region <- as.factor(data$region)
data$loyalty_status <- as.factor(data$loyalty_status)
data$promotion_usage <- as.factor(data$promotion_usage)
data$income <- as.numeric(data$income)
data$purchase_amount <- as.numeric(data$purchase_amount)
str(data)
## tibble [100,000 × 12] (S3: tbl_df/tbl/data.frame)
## $ id : num [1:100000] 1 2 3 4 5 6 7 8 9 10 ...
## $ age : num [1:100000] 27 29 37 30 31 38 32 24 27 28 ...
## $ gender : chr [1:100000] "Male" "Male" "Male" "Male" ...
## $ income : num [1:100000] 40682 15317 38849 11568 46952 ...
## $ education : chr [1:100000] "Bachelor" "Masters" "Bachelor" "HighSchool" ...
## $ region : Factor w/ 4 levels "East","North",..: 1 4 4 3 2 3 3 2 1 2 ...
## $ loyalty_status : Factor w/ 3 levels "Gold","Regular",..: 1 2 3 2 2 3 3 2 2 2 ...
## $ purchase_frequency: chr [1:100000] "frequent" "rare" "rare" "frequent" ...
## $ purchase_amount : num [1:100000] 18249 4557 11822 4098 19685 ...
## $ product_category : chr [1:100000] "Books" "Clothing" "Clothing" "Food" ...
## $ promotion_usage : Factor w/ 2 levels "0","1": 1 2 1 1 2 1 1 1 1 1 ...
## $ satisfaction_score: num [1:100000] 6 6 6 7 5 5 7 5 5 6 ...
#4. Tạo bảng mô tả với 4 cột: Biến, Ý nghĩa, Kiểu dữ liệu, Loại biến
variable_description <- data.frame(
"Biến" = c("id", "age", "gender", "income", "education", "region",
"loyalty_status", "purchase_frequency", "purchase_amount",
"product_category", "promotion_usage", "satisfaction_score"),
"Ý nghĩa" = c(
"Mã định danh khách hàng",
"Tuổi của khách hàng",
"Giới tính của khách hàng (Nam/Nữ)",
"Thu nhập hằng năm (USD)",
"Trình độ học vấn (HighSchool/College/Bachelor/Masters)",
"Khu vực sinh sống",
"Mức độ trung thành (Bronze/Silver/Gold/Platinum)",
"Tần suất mua hàng trong kỳ",
"Số tiền chi tiêu trong một lần mua (USD)",
"Loại sản phẩm đã mua",
"Có sử dụng khuyến mãi hay không (Yes/No)",
"Mức độ hài lòng (1–10)"
),
"Kiểu dữ liệu" = c(
"integer", # id
"integer", # age
"character", # gender
"integer", # income
"character", # education
"character", # region
"character", # loyalty_status
"character", # purchase_frequency
"integer", # purchase_amount
"character", # product_category
"integer", # promotion_usage
"integer" # satisfaction_score
),
"Loại biến" = c(
"Định danh", # id
"Định lượng", # age
"Định tính", # gender
"Định lượng", # income
"Định tính", # education
"Định tính", # region
"Định tính", # loyalty_status
"Định tính", # purchase_frequency
"Định lượng", # purchase_amount
"Định tính", # product_category
"Định lượng", # promotion_usage
"Định lượng" # satisfaction_score
)
)
#5. Hiển thị bảng
variable_description %>%
kbl(caption = "Bảng 1. Mô tả các biến trong bộ dữ liệu") %>%
kable_styling(
full_width = FALSE,
position = "center",
bootstrap_options = c("striped", "hover", "condensed", "responsive")
)
| Biến | Ý.nghĩa | Kiểu.dữ.liệu | Loại.biến |
|---|---|---|---|
| id | Mã định danh khách hàng | integer | Định danh |
| age | Tuổi của khách hàng | integer | Định lượng |
| gender | Giới tính của khách hàng (Nam/Nữ) | character | Định tính |
| income | Thu nhập hằng năm (USD) | integer | Định lượng |
| education | Trình độ học vấn (HighSchool/College/Bachelor/Masters) | character | Định tính |
| region | Khu vực sinh sống | character | Định tính |
| loyalty_status | Mức độ trung thành (Bronze/Silver/Gold/Platinum) | character | Định tính |
| purchase_frequency | Tần suất mua hàng trong kỳ | character | Định tính |
| purchase_amount | Số tiền chi tiêu trong một lần mua (USD) | integer | Định lượng |
| product_category | Loại sản phẩm đã mua | character | Định tính |
| promotion_usage | Có sử dụng khuyến mãi hay không (Yes/No) | integer | Định lượng |
| satisfaction_score | Mức độ hài lòng (1–10) | integer | Định lượng |
#6. Chuẩn hóa tên cột
names(data) <- tolower(names(data))
#7. Loại bỏ giá trị âm hoặc 0 trong purchase_amount
data <- filter(data, purchase_amount > 0)
#8. Mã hóa promotion_usage thành nhãn
data$promotion_usage <- factor(data$promotion_usage,
levels = c(0, 1),
labels = c("No", "Yes"))
#9. Tạo biến mới: thu nhập trung bình theo khu vực
region_income <- data %>%
group_by(region) %>%
summarise(mean_income = mean(income, na.rm = TRUE))
#10. Chuẩn hóa income
data$income_scaled <- scale(data$income)
#11. Thêm biến nhóm tuổi
data$age_group <- cut(data$age, breaks = c(18, 30, 45, 60, 100),
labels = c("18-30", "31-45", "46-60", "60+"))
#12. Tạo biến nhóm tuổi (AgeGroup) từ biến age
library(dplyr)
data <- data %>%
mutate(
AgeGroup = case_when(
age < 25 ~ "Dưới 25",
age >= 25 & age < 35 ~ "25-34",
age >= 35 & age < 45 ~ "35-44",
age >= 45 & age < 55 ~ "45-54",
age >= 55 ~ "55 trở lên",
TRUE ~ NA_character_
)
)
# 13. Kiểm tra lại xem đã tạo được chưa
table(data$AgeGroup)
##
## 25-34 35-44 45-54 Dưới 25
## 73316 15732 62 10890
# 1. Tổng quan lại cấu trúc dữ liệu
str(data)
## tibble [100,000 × 15] (S3: tbl_df/tbl/data.frame)
## $ id : num [1:100000] 1 2 3 4 5 6 7 8 9 10 ...
## $ age : num [1:100000] 27 29 37 30 31 38 32 24 27 28 ...
## $ gender : chr [1:100000] "Male" "Male" "Male" "Male" ...
## $ income : num [1:100000] 40682 15317 38849 11568 46952 ...
## $ education : chr [1:100000] "Bachelor" "Masters" "Bachelor" "HighSchool" ...
## $ region : Factor w/ 4 levels "East","North",..: 1 4 4 3 2 3 3 2 1 2 ...
## $ loyalty_status : Factor w/ 3 levels "Gold","Regular",..: 1 2 3 2 2 3 3 2 2 2 ...
## $ purchase_frequency: chr [1:100000] "frequent" "rare" "rare" "frequent" ...
## $ purchase_amount : num [1:100000] 18249 4557 11822 4098 19685 ...
## $ product_category : chr [1:100000] "Books" "Clothing" "Clothing" "Food" ...
## $ promotion_usage : Factor w/ 2 levels "No","Yes": 1 2 1 1 2 1 1 1 1 1 ...
## $ satisfaction_score: num [1:100000] 6 6 6 7 5 5 7 5 5 6 ...
## $ income_scaled : num [1:100000, 1] 1.013 -0.939 0.872 -1.227 1.495 ...
## ..- attr(*, "scaled:center")= num 27516
## ..- attr(*, "scaled:scale")= num 12997
## $ age_group : Factor w/ 4 levels "18-30","31-45",..: 1 1 2 1 2 2 2 1 1 1 ...
## $ AgeGroup : chr [1:100000] "25-34" "25-34" "35-44" "25-34" ...
# 2. Tóm tắt thống kê toàn bộ biến
summary(data)
## id age gender income
## Min. : 1 Min. :12 Length:100000 Min. : 5000
## 1st Qu.: 25001 1st Qu.:27 Class :character 1st Qu.:16272
## Median : 50001 Median :30 Mode :character Median :27585
## Mean : 50001 Mean :30 Mean :27516
## 3rd Qu.: 75000 3rd Qu.:33 3rd Qu.:38747
## Max. :100000 Max. :49 Max. :50000
## education region loyalty_status purchase_frequency
## Length:100000 East :30074 Gold : 9898 Length:100000
## Class :character North:19918 Regular:60138 Class :character
## Mode :character South:20073 Silver :29964 Mode :character
## West :29935
##
##
## purchase_amount product_category promotion_usage satisfaction_score
## Min. : 1118 Length:100000 No :69920 Min. : 0.00
## 1st Qu.: 5583 Class :character Yes:30080 1st Qu.: 4.00
## Median : 9452 Mode :character Median : 5.00
## Mean : 9635 Mean : 5.01
## 3rd Qu.:13350 3rd Qu.: 6.00
## Max. :26204 Max. :10.00
## income_scaled.V1 age_group AgeGroup
## Min. :-1.7324495 18-30:53918 Length:100000
## 1st Qu.:-0.8651772 31-45:45554 Class :character
## Median : 0.0052498 46-60: 27 Mode :character
## Mean : 0.0000000 60+ : 0
## 3rd Qu.: 0.8641354 NA's : 501
## Max. : 1.7299459
# 3. Tính trung bình thu nhập khách hàng
mean(data$income, na.rm = TRUE)
## [1] 27516.27
# 4. Tính trung vị thu nhập
median(data$income, na.rm = TRUE)
## [1] 27584.5
# 5. Tính độ lệch chuẩn thu nhập
sd(data$income, na.rm = TRUE)
## [1] 12996.78
# 6. Tính phương sai thu nhập
var(data$income, na.rm = TRUE)
## [1] 168916358
# 7. Tìm giá trị lớn nhất và nhỏ nhất của thu nhập
min(data$income, na.rm = TRUE)
## [1] 5000
max(data$income, na.rm = TRUE)
## [1] 50000
# 8. Tính tứ phân vị thu nhập
quantile(data$income, probs = c(0.25, 0.5, 0.75), na.rm = TRUE)
## 25% 50% 75%
## 16271.75 27584.50 38747.25
# 9. Tính hệ số biến thiên (CV) của thu nhập
cv_income <- sd(data$income, na.rm = TRUE) / mean(data$income, na.rm = TRUE)
cv_income
## [1] 0.4723308
# 10. Tần suất từng nhóm giới tính
table(data$gender)
##
## Female Male
## 50074 49926
# 11. Tỷ lệ phần trăm giới tính
prop.table(table(data$gender)) * 100
##
## Female Male
## 50.074 49.926
# 12. Thống kê theo vùng (Region)
table(data$region)
##
## East North South West
## 30074 19918 20073 29935
# 13. Trung bình thu nhập theo giới tính
aggregate(income ~ gender, data = data, FUN = mean)
## gender income
## 1 Female 27507.95
## 2 Male 27524.62
# 14. Trung bình thu nhập theo độ tuổi (Age Group)
aggregate(income ~ AgeGroup, data = data, FUN = mean)
## AgeGroup income
## 1 25-34 27517.88
## 2 35-44 27485.33
## 3 45-54 26567.61
## 4 Dưới 25 27555.51
# 15. Trung bình chi tiêu theo giới tính
aggregate(purchase_amount ~ gender, data = data, FUN = mean)
## gender purchase_amount
## 1 Female 9634.405
## 2 Male 9635.178
# 16. Hệ số tương quan giữa thu nhập và chi tiêu
cor(data$income, data$purchase_amount, use = "complete.obs")
## [1] 0.9484413
# 17. Kiểm tra phân phối chuẩn của thu nhập
shapiro.test(sample(data$income, 500)) # Lấy mẫu 500 để test
##
## Shapiro-Wilk normality test
##
## data: sample(data$income, 500)
## W = 0.95492, p-value = 3.158e-11
# 18. Thống kê tần suất khách hàng theo nhóm tuổi
table(data$AgeGroup)
##
## 25-34 35-44 45-54 Dưới 25
## 73316 15732 62 10890
# 19. Tính tổng chi tiêu trung bình của toàn bộ khách hàng-
mean(data$purchase_amount, na.rm = TRUE)
## [1] 9634.791
# 20. So sánh chi tiêu trung bình giữa các vùng
aggregate(purchase_amount ~ region, data = data, FUN = mean)
## region purchase_amount
## 1 East 9615.411
## 2 North 9673.362
## 3 South 9648.787
## 4 West 9619.211
# 21. Đếm số lượng khách hàng mỗi nhóm thu nhập
table(cut(data$income, breaks = 5))
##
## (4.95e+03,1.4e+04] (1.4e+04,2.3e+04] (2.3e+04,3.2e+04] (3.2e+04,4.1e+04]
## 20061 19816 20007 20206
## (4.1e+04,5e+04]
## 19910
# 22. Phân phối thu nhập theo giới tính
aggregate(income ~ gender, data, summary)
## gender income.Min. income.1st Qu. income.Median income.Mean income.3rd Qu.
## 1 Female 5000.00 16271.50 27554.50 27507.95 38718.75
## 2 Male 5000.00 16272.50 27615.50 27524.62 38786.75
## income.Max.
## 1 49998.00
## 2 50000.00
# 23. Tính IQR (khoảng tứ phân vị)
IQR(data$income, na.rm = TRUE)
## [1] 22475.5
# 24. Tính hệ số tương quan Pearson và Spearman
cor(data$income, data$purchase_amount, method = "pearson", use = "complete.obs")
## [1] 0.9484413
cor(data$income, data$purchase_amount, method = "spearman", use = "complete.obs")
## [1] 0.9571268
# 25. Đếm số khách hàng có chi tiêu > trung bình
mean(data$purchase_amount > mean(data$purchase_amount, na.rm = TRUE))
## [1] 0.4882
library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.4.3
library(dplyr)
library(reshape2)
## Warning: package 'reshape2' was built under R version 4.4.3
##
## Attaching package: 'reshape2'
## The following object is masked from 'package:tidyr':
##
## smiths
## The following objects are masked from 'package:data.table':
##
## dcast, melt
# Biểu đồ 1. Phân phối thu nhập khách hàng
ggplot(data, aes(x = income)) +
geom_histogram(fill = "skyblue", color = "black", bins = 30) +
geom_vline(aes(xintercept = mean(income, na.rm = TRUE)), color = "red", linetype = "dashed") +
labs(title = "Biểu đồ 1. Phân phối thu nhập khách hàng", x = "Thu nhập", y = "Tần suất") +
theme_minimal()
# Biểu đồ 2. Phân phối chi tiêu khách hàng
ggplot(data, aes(x = purchase_amount)) +
geom_histogram(fill = "lightgreen", color = "black", bins = 25) +
geom_vline(aes(xintercept = mean(purchase_amount, na.rm = TRUE)), color = "red", linetype = "dotted") +
labs(title = "Biểu đồ 2. Phân phối chi tiêu khách hàng", x = "Chi tiêu", y = "Tần suất") +
theme_light()
# Biểu đồ 3. So sánh thu nhập giữa các giới tính
ggplot(data, aes(x = gender, y = income, fill = gender)) +
geom_boxplot() +
geom_jitter(width = 0.2, alpha = 0.4) +
labs(title = "Biểu đồ 3. So sánh thu nhập giữa các giới tính", x = "Giới tính", y = "Thu nhập") +
theme_bw()
# Biểu đồ 4. Chi tiêu trung bình theo vùng
ggplot(data, aes(x = region, y = purchase_amount, fill = region)) +
geom_boxplot() +
labs(title = "Biểu đồ 4. Chi tiêu trung bình theo vùng", x = "Vùng", y = "Chi tiêu") +
theme_minimal() +
coord_flip()
# Biểu đồ 5. Phân bố khách hàng theo giới tính
ggplot(data, aes(x = gender, fill = gender)) +
geom_bar() +
geom_text(stat = "count", aes(label = after_stat(count)), vjust = -0.5) +
labs(title = "Biểu đồ 5. Phân bố khách hàng theo giới tính", x = "Giới tính", y = "Số lượng") +
theme_classic()
# Biểu đồ 6. Số lượng khách hàng theo vùng
ggplot(data, aes(x = region, fill = region)) +
geom_bar() +
geom_text(stat = "count", aes(label = after_stat(count)), vjust = -0.3) +
labs(title = "Biểu đồ 6. Số lượng khách hàng theo vùng địa lý", x = "Vùng", y = "Số lượng") +
theme_minimal()
# Biểu đồ 7. Chi tiêu trung bình theo giới tính
avg_purchase_amount_gender <- data %>% group_by(gender) %>% summarise(Avgpurchase_amount = mean(purchase_amount, na.rm = TRUE))
ggplot(avg_purchase_amount_gender, aes(x = gender, y = Avgpurchase_amount, fill = gender)) +
geom_col() +
geom_text(aes(label = round(Avgpurchase_amount, 0)), vjust = -0.5) +
labs(title = "Biểu đồ 7. Chi tiêu trung bình theo giới tính", y = "Chi tiêu trung bình") +
theme_light()
# Biểu đồ 8. Mối quan hệ giữa thu nhập và chi tiêu
ggplot(data, aes(x = income, y = purchase_amount, color = gender)) +
geom_point(alpha = 0.6) +
geom_smooth(method = "lm", se = FALSE, color = "black") +
labs(title = "Biểu đồ 8. Mối quan hệ giữa thu nhập và chi tiêu", x = "Thu nhập", y = "Chi tiêu") +
theme_bw()
## `geom_smooth()` using formula = 'y ~ x'
# Biểu đồ 9. Quan hệ thu nhập - chi tiêu theo từng vùng
ggplot(data, aes(x = income, y = purchase_amount, color = region)) +
geom_point(size = 2) +
geom_smooth(method = "lm", se = FALSE) +
facet_wrap(~region) +
labs(title = "Biểu đồ 9. Quan hệ thu nhập - chi tiêu theo từng vùng") +
theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'
# Biểu đồ 10. Phân phối chi tiêu theo giới tính (Violin Plot)
ggplot(data, aes(x = gender, y = purchase_amount, fill = gender)) +
geom_violin(trim = FALSE) +
geom_boxplot(width = 0.1, fill = "white") +
labs(title = "Biểu đồ 10. Phân phối chi tiêu theo giới tính", x = "Giới tính", y = "Chi tiêu") +
theme_classic()
# Biểu đồ 11. Mật độ phân phối thu nhập theo giới tính
ggplot(data, aes(x = income, fill = gender)) +
geom_density(alpha = 0.5) +
labs(title = "Biểu đồ 11. Mật độ phân phối thu nhập theo giới tính", x = "Thu nhập", y = "Mật độ") +
theme_light()
# Biểu đồ 12. Chi tiêu trung bình theo nhóm tuổi
avg_age <- data %>% group_by(AgeGroup) %>% summarise(Avgpurchase_amount = mean(purchase_amount, na.rm = TRUE))
ggplot(avg_age, aes(x = AgeGroup, y = Avgpurchase_amount, group = 1)) +
geom_line(color = "blue") +
geom_point(size = 3) +
labs(title = "Biểu đồ 12. Chi tiêu trung bình theo nhóm tuổi", x = "Nhóm tuổi", y = "Chi tiêu trung bình") +
theme_minimal()
# Biểu đồ 13. Tỷ trọng khách hàng theo giới tính (Pie Chart)
gender_share <- data %>% count(gender)
ggplot(gender_share, aes(x = "", y = n, fill = gender)) +
geom_col(width = 1) +
coord_polar("y") +
labs(title = "Biểu đồ 13. Tỷ trọng khách hàng theo giới tính") +
theme_void()
# Biểu đồ 14. Tỷ trọng khách hàng theo vùng (Pie Chart)
region_share <- data %>% count(region)
ggplot(region_share, aes(x = "", y = n, fill = region)) +
geom_col(width = 1) +
coord_polar("y") +
labs(title = "Biểu đồ 14. Tỷ trọng khách hàng theo vùng") +
theme_void()
# Biểu đồ 15. Ma trận tương quan giữa các biến số (Heatmap)
num_vars <- select_if(data, is.numeric)
corr_matrix <- cor(num_vars, use = "complete.obs")
melted_corr <- melt(corr_matrix)
ggplot(melted_corr, aes(Var1, Var2, fill = value)) +
geom_tile() +
scale_fill_gradient2(low = "red", high = "blue", mid = "white") +
labs(title = "Biểu đồ 15. Ma trận tương quan giữa các biến số") +
theme_minimal()
# Biểu đồ 16. So sánh chi tiêu theo giới tính và vùng
ggplot(data, aes(x = gender, y = purchase_amount, fill = gender)) +
geom_boxplot() +
facet_wrap(~region) +
labs(title = "Biểu đồ 16. So sánh chi tiêu theo giới tính và vùng") +
theme_bw()
# Biểu đồ 17. Thu nhập trung bình theo vùng (Lollipop Chart)
avg_income_region <- data %>% group_by(region) %>% summarise(Avgincome = mean(income, na.rm = TRUE))
ggplot(avg_income_region, aes(x = reorder(region, Avgincome), y = Avgincome)) +
geom_segment(aes(xend = region, y = 0, yend = Avgincome), color = "gray") +
geom_point(size = 4, color = "blue") +
labs(title = "Biểu đồ 17. Thu nhập trung bình theo vùng", x = "Vùng", y = "Thu nhập trung bình") +
theme_light() +
coord_flip()
# Biểu đồ 18. Chi tiêu trung bình theo giới tính và vùng
avg_purchase_amount <- data %>% group_by(region, gender) %>% summarise(Avgpurchase_amount = mean(purchase_amount, na.rm = TRUE))
## `summarise()` has grouped output by 'region'. You can override using the
## `.groups` argument.
ggplot(avg_purchase_amount, aes(x = region, y = Avgpurchase_amount, fill = gender)) +
geom_col(position = "dodge") +
labs(title = "Biểu đồ 18. Chi tiêu trung bình theo giới tính và vùng", x = "Vùng", y = "Chi tiêu trung bình") +
theme_minimal()
# Biểu đồ 19. Phân phối chi tiêu theo vùng
ggplot(data, aes(x = purchase_amount, fill = region)) +
geom_histogram(alpha = 0.6, position = "identity", bins = 30) +
labs(title = "Biểu đồ 19. Phân phối chi tiêu theo vùng", x = "Chi tiêu", y = "Tần suất") +
theme_light()
# Biểu đồ 20. Quan hệ giữa thu nhập và chi tiêu (vẽ kèm trendline)
ggplot(data, aes(x = income, y = purchase_amount)) +
geom_point(aes(color = region), alpha = 0.7) +
geom_smooth(method = "lm", se = FALSE, color = "black") +
labs(title = "Biểu đồ 20. Quan hệ giữa thu nhập và chi tiêu (có đường xu hướng)",
x = "Thu nhập", y = "Chi tiêu") +
theme_classic()
## `geom_smooth()` using formula = 'y ~ x'