Trước hết load data và convert text features về factor:
# Load data:
rm(list = ls())
library(tidyverse)
<- read_csv("survey.csv")
survey
<- read_csv("spending.csv")
spending
<- read_csv("player.csv")
player
::read_excel("Legend.xlsx") -> df_legend
readxl
#=========================
# Question 1
#=========================
# Convert text columns to factor:
%>%
spending mutate_if(is.character, as.factor) %>%
select(-ID) -> df_question1
R codes cho DBSCAN tìm noise/outliers:
# DBSCAN for finding outliers:
library(dbscan)
library(fpc)
library(cluster)
daisy(df_question1, metric = "gower") -> diss_mat
::dbscan(diss_mat, eps = 0.2, minPts = 3) -> db
dbscan
%>%
spending mutate(db_cluster = db$cluster, ID = NULL) -> df_db
Đoạn mã gốc gợi ý trong đề thi tạo ra plot không đủ tốt để chỉ ra các insights thu được từ DBSCAN. Dưới đây là giải pháp khác. Vì các features thuộc về hai nhóm nên chúng ta sử dụng barplot cho categorical và boxplot cho numeric và nên để riêng biệt. R codes như sau:
# Different solution for ploting:
%>%
df_db select(1:9, 16) %>%
gather(a, Type, -db_cluster) %>%
mutate(db_cluster = as.factor(db_cluster)) %>%
group_by(db_cluster, Type, a) %>%
count() %>%
ggplot(aes(db_cluster, n, fill = Type)) +
geom_col(position = "fill") +
facet_wrap(~ a) +
labs(x = NULL, title = "Figure 1: Yes/No Rate by categorical features")
Figure 1 chỉ ra rằng, ví dụ, tỉ lệ Yes/No sử dụng dịch CarService là không có gì khác biệt giữa hai nhóm. Nhưng riêng Shop (mua sắm) thì nhóm 1 trả lời Yes là nhiều hơn. Chỗ này có thể chém gió rằng các managers nên hướng vào việc lôi kéo nhóm 0 để nâng tỉ lệ Yes. Bạn chém gió tương tự.
%>%
df_db select(10:16) %>%
gather(Variable, Value, -db_cluster) %>%
mutate(db_cluster = as.factor(db_cluster)) %>%
ggplot(aes(db_cluster, Value, fill = db_cluster, color = db_cluster)) +
geom_boxplot(alpha = 0.4) +
facet_wrap(~ Variable, scales = "free") +
labs(x = NULL, title = "Figure 2: Mean difference by categorical features")
Figure 2 chỉ ra rằng hành vi chi tiêu/tiêu dùng của hai nhóm có khác biệt khá rõ theo hai hướng. Hướng thứ nhất là nhóm DayPV, DinePV, và RSPV. Ở nhóm thứ nhất thì 0 là nhóm mà mean và median đều cao hơn. Hướng thứ hai là các metrics còn lại và xu hướng là ngược lại.
Ý này có thể được làm rõ hơn, cụ thể hơn ở yêu cầu ..summary comparing the characteristics... Thường thì managers thích kiểu báo cáo này. Dưới đây là hành vi tiêu dùng của hai nhóm được mô tả bằng một số thống kê chủ yếu:
# Brief summary comparing the characteristics of
# that small group of VIP players to those of the regular VIP players:
library(knitr)
%>%
df_db select(10:16) %>%
gather(Variable, Value, -db_cluster) %>%
mutate(db_cluster = as.factor(db_cluster)) -> df_report
%>%
df_report group_by(db_cluster, Variable) %>%
summarise(MEDIAN = median(Value), MEAN = mean(Value), MIN = min(Value), MAX = max(Value), SD = sd(Value), N = n()) %>%
arrange(Variable) %>%
mutate_if(is.numeric, function(x) {round(x, 0)}) %>%
kable(caption = "Table 1: Summary comparing the characteristics")
db_cluster | Variable | MEDIAN | MEAN | MIN | MAX | SD | N |
---|---|---|---|---|---|---|---|
0 | DayPV | 5 | 5 | 2 | 10 | 3 | 11 |
1 | DayPV | 4 | 4 | 1 | 10 | 2 | 239 |
0 | DinePV | 627 | 507 | 212 | 790 | 229 | 11 |
1 | DinePV | 478 | 495 | 200 | 793 | 174 | 239 |
0 | GamePV | 6012 | 6475 | 475 | 14736 | 5131 | 11 |
1 | GamePV | 7303 | 7490 | 388 | 14998 | 4136 | 239 |
0 | NonGamePV | 2414 | 2490 | 1147 | 3977 | 1059 | 11 |
1 | NonGamePV | 2487 | 2472 | 1001 | 3964 | 891 | 239 |
0 | RSPV | 426 | 391 | 103 | 593 | 187 | 11 |
1 | RSPV | 336 | 346 | 100 | 598 | 146 | 239 |
0 | SpendPV | 9071 | 9863 | 3528 | 18296 | 5457 | 11 |
1 | SpendPV | 10605 | 10803 | 2148 | 19162 | 4228 | 239 |
Nhìn vào báo cáo này có thể thấy, ví dụ, nhóm 1 có trung bình GamePV cao hơn đáng kể. Bạn, ví dụ, có thể củng cố vững chắc hơn nhận định của mình bằng cách sử dụng t-test để chỉ ra sự khác biệt về trung bình này là có ý nghĩa thống kê hay không như sau:
%>%
df_report filter(Variable == "GamePV") %>%
t.test(Value ~ db_cluster, data = .)
##
## Welch Two Sample t-test
##
## data: Value by db_cluster
## t = -0.64684, df = 10.607, p-value = 0.5315
## alternative hypothesis: true difference in means between group 0 and group 1 is not equal to 0
## 95 percent confidence interval:
## -4486.430 2455.523
## sample estimates:
## mean in group 0 mean in group 1
## 6474.941 7490.395
Dễ thấy rằng mean in group 0 là 6474.941 làm tròn thành 6475 và kết quả này trình bày ở Table 1 trước đó. Còn của t-test là p-value = 0.5315.