Báo cáo này thực hiện phân tích thống kê toàn diện bao gồm:
# ===============================================
# THAY ĐỔI PHẦN NÀY VỚI DỮ LIỆU THỰC TẾ CỦA BẠN
# ===============================================
# Cách 1: Đọc từ file CSV
# data <- read.csv("duong_dan_file.csv", header = TRUE, stringsAsFactors = TRUE)
# Cách 2: Đọc từ file Excel
# library(readxl)
# data <- read_excel("duong_dan_file.xlsx")
# Cách 3: Sử dụng dữ liệu mẫu (để minh họa)
set.seed(123)
n <- 150
data <- data.frame(
ID = 1:n,
Nhom = sample(c("A", "B", "C"), n, replace = TRUE),
Gioi_tinh = sample(c("Nam", "Nu"), n, replace = TRUE),
Diem_thi = round(rnorm(n, mean = 70, sd = 12), 1),
Thu_nhap = round(rnorm(n, mean = 15, sd = 5), 1),
Muc_do_hai_long = sample(1:5, n, replace = TRUE, prob = c(0.1, 0.15, 0.4, 0.25, 0.1)),
Tuoi = round(rnorm(n, mean = 35, sd = 8)),
Thanh_cong = sample(c("Co", "Khong"), n, replace = TRUE, prob = c(0.6, 0.4))
)
# Xem cấu trúc dữ liệu
str(data)## 'data.frame': 150 obs. of 8 variables:
## $ ID : int 1 2 3 4 5 6 7 8 9 10 ...
## $ Nhom : chr "C" "C" "C" "B" ...
## $ Gioi_tinh : chr "Nam" "Nam" "Nu" "Nu" ...
## $ Diem_thi : num 74.3 94.1 55.9 60.9 66 66.6 73.8 92.1 58.2 96.4 ...
## $ Thu_nhap : num 18.4 14 19.2 13.5 16.6 8.2 16.5 21.9 15.8 20.3 ...
## $ Muc_do_hai_long: int 5 5 3 1 4 3 4 3 3 4 ...
## $ Tuoi : num 20 35 24 26 41 38 28 40 40 36 ...
## $ Thanh_cong : chr "Khong" "Co" "Co" "Khong" ...
Nhận xét: Dữ liệu gồm 150 quan sát và 8 biến.
# Bảng tần số
freq_nhom <- table(data$Nhom)
freq_nhom_pct <- prop.table(freq_nhom) * 100
# Tạo bảng đẹp
freq_table_nhom <- data.frame(
Nhom = names(freq_nhom),
Tan_so = as.numeric(freq_nhom),
Ti_le_phan_tram = round(as.numeric(freq_nhom_pct), 2)
)
kable(freq_table_nhom,
caption = "Bảng tần số biến Nhóm",
col.names = c("Nhóm", "Tần số", "Tỉ lệ (%)")) %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE)| Nhóm | Tần số | Tỉ lệ (%) |
|---|---|---|
| A | 42 | 28 |
| B | 54 | 36 |
| C | 54 | 36 |
freq_gender <- table(data$Gioi_tinh)
freq_gender_pct <- prop.table(freq_gender) * 100
freq_table_gender <- data.frame(
Gioi_tinh = names(freq_gender),
Tan_so = as.numeric(freq_gender),
Ti_le_phan_tram = round(as.numeric(freq_gender_pct), 2)
)
kable(freq_table_gender,
caption = "Bảng tần số biến Giới tính",
col.names = c("Giới tính", "Tần số", "Tỉ lệ (%)")) %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE)| Giới tính | Tần số | Tỉ lệ (%) |
|---|---|---|
| Nam | 78 | 52 |
| Nu | 72 | 48 |
cross_table <- table(data$Nhom, data$Gioi_tinh)
kable(cross_table,
caption = "Bảng chéo: Nhóm × Giới tính") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE)| Nam | Nu | |
|---|---|---|
| A | 22 | 20 |
| B | 27 | 27 |
| C | 29 | 25 |
# Tạo các khoảng phân tổ
breaks_diem <- seq(min(data$Diem_thi), max(data$Diem_thi), length.out = 8)
diem_cut <- cut(data$Diem_thi, breaks = breaks_diem, include.lowest = TRUE)
# Bảng phân tổ
freq_diem <- table(diem_cut)
freq_diem_pct <- prop.table(freq_diem) * 100
freq_table_diem <- data.frame(
Khoang = names(freq_diem),
Tan_so = as.numeric(freq_diem),
Ti_le_phan_tram = round(as.numeric(freq_diem_pct), 2),
Tan_so_tich_luy = cumsum(as.numeric(freq_diem)),
Ti_le_tich_luy = round(cumsum(as.numeric(freq_diem_pct)), 2)
)
kable(freq_table_diem,
caption = "Bảng phân tổ biến Điểm thi",
col.names = c("Khoảng", "Tần số", "Tỉ lệ (%)", "Tần số tích lũy", "Tỉ lệ tích lũy (%)")) %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE)| Khoảng | Tần số | Tỉ lệ (%) | Tần số tích lũy | Tỉ lệ tích lũy (%) |
|---|---|---|---|---|
| [30.3,40.6] | 1 | 0.67 | 1 | 0.67 |
| (40.6,50.9] | 9 | 6.00 | 10 | 6.67 |
| (50.9,61.2] | 30 | 20.00 | 40 | 26.67 |
| (61.2,71.6] | 39 | 26.00 | 79 | 52.67 |
| (71.6,81.9] | 49 | 32.67 | 128 | 85.33 |
| (81.9,92.2] | 15 | 10.00 | 143 | 95.33 |
| (92.2,102] | 7 | 4.67 | 150 | 100.00 |
breaks_income <- seq(min(data$Thu_nhap), max(data$Thu_nhap), length.out = 8)
income_cut <- cut(data$Thu_nhap, breaks = breaks_income, include.lowest = TRUE)
freq_income <- table(income_cut)
freq_income_pct <- prop.table(freq_income) * 100
freq_table_income <- data.frame(
Khoang = names(freq_income),
Tan_so = as.numeric(freq_income),
Ti_le_phan_tram = round(as.numeric(freq_income_pct), 2),
Tan_so_tich_luy = cumsum(as.numeric(freq_income)),
Ti_le_tich_luy = round(cumsum(as.numeric(freq_income_pct)), 2)
)
kable(freq_table_income,
caption = "Bảng phân tổ biến Thu nhập",
col.names = c("Khoảng", "Tần số", "Tỉ lệ (%)", "Tần số tích lũy", "Tỉ lệ tích lũy (%)")) %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE)| Khoảng | Tần số | Tỉ lệ (%) | Tần số tích lũy | Tỉ lệ tích lũy (%) |
|---|---|---|---|---|
| [-0.2,3.66] | 3 | 2.00 | 3 | 2.00 |
| (3.66,7.51] | 8 | 5.33 | 11 | 7.33 |
| (7.51,11.4] | 28 | 18.67 | 39 | 26.00 |
| (11.4,15.2] | 35 | 23.33 | 74 | 49.33 |
| (15.2,19.1] | 49 | 32.67 | 123 | 82.00 |
| (19.1,22.9] | 22 | 14.67 | 145 | 96.67 |
| (22.9,26.8] | 5 | 3.33 | 150 | 100.00 |
p1 <- ggplot(data, aes(x = Nhom, fill = Nhom)) +
geom_bar(stat = "count", color = "black") +
geom_text(stat = "count", aes(label = ..count..), vjust = -0.5) +
labs(title = "Biểu đồ tần số - Nhóm", x = "Nhóm", y = "Tần số") +
theme_minimal() +
theme(legend.position = "none")
p2 <- ggplot(data, aes(x = Gioi_tinh, fill = Gioi_tinh)) +
geom_bar(stat = "count", color = "black") +
geom_text(stat = "count", aes(label = ..count..), vjust = -0.5) +
labs(title = "Biểu đồ tần số - Giới tính", x = "Giới tính", y = "Tần số") +
theme_minimal() +
theme(legend.position = "none")
grid.arrange(p1, p2, ncol = 2)freq_nhom_df <- data.frame(
Nhom = names(freq_nhom),
Count = as.numeric(freq_nhom)
)
ggplot(freq_nhom_df, aes(x = "", y = Count, fill = Nhom)) +
geom_bar(stat = "identity", width = 1, color = "white") +
coord_polar("y", start = 0) +
geom_text(aes(label = paste0(Nhom, "\n", Count)),
position = position_stack(vjust = 0.5)) +
labs(title = "Biểu đồ tròn - Phân bố Nhóm") +
theme_void() +
theme(legend.position = "right")h1 <- ggplot(data, aes(x = Diem_thi)) +
geom_histogram(aes(y = ..density..), bins = 20, fill = "skyblue", color = "black", alpha = 0.7) +
geom_density(color = "red", size = 1) +
labs(title = "Histogram - Điểm thi", x = "Điểm thi", y = "Mật độ") +
theme_minimal()
h2 <- ggplot(data, aes(x = Thu_nhap)) +
geom_histogram(aes(y = ..density..), bins = 20, fill = "lightgreen", color = "black", alpha = 0.7) +
geom_density(color = "red", size = 1) +
labs(title = "Histogram - Thu nhập", x = "Thu nhập (triệu)", y = "Mật độ") +
theme_minimal()
grid.arrange(h1, h2, ncol = 2)b1 <- ggplot(data, aes(x = Nhom, y = Diem_thi, fill = Nhom)) +
geom_boxplot() +
labs(title = "Boxplot - Điểm thi theo Nhóm", x = "Nhóm", y = "Điểm thi") +
theme_minimal() +
theme(legend.position = "none")
b2 <- ggplot(data, aes(x = Gioi_tinh, y = Thu_nhap, fill = Gioi_tinh)) +
geom_boxplot() +
labs(title = "Boxplot - Thu nhập theo Giới tính", x = "Giới tính", y = "Thu nhập") +
theme_minimal() +
theme(legend.position = "none")
grid.arrange(b1, b2, ncol = 2)ggplot(data, aes(x = Diem_thi, y = Thu_nhap, color = Nhom)) +
geom_point(size = 3, alpha = 0.6) +
geom_smooth(method = "lm", se = TRUE, color = "darkblue") +
labs(title = "Biểu đồ phân tán - Điểm thi vs Thu nhập",
x = "Điểm thi", y = "Thu nhập (triệu)") +
theme_minimal()# Hàm tính các đại lượng thống kê
calc_stats <- function(x) {
c(
Mean = mean(x, na.rm = TRUE),
Median = median(x, na.rm = TRUE),
Mode = as.numeric(names(sort(table(x), decreasing = TRUE)[1])),
Min = min(x, na.rm = TRUE),
Max = max(x, na.rm = TRUE),
Range = max(x, na.rm = TRUE) - min(x, na.rm = TRUE),
Q1 = quantile(x, 0.25, na.rm = TRUE),
Q3 = quantile(x, 0.75, na.rm = TRUE),
IQR = IQR(x, na.rm = TRUE),
Variance = var(x, na.rm = TRUE),
SD = sd(x, na.rm = TRUE),
CV = (sd(x, na.rm = TRUE) / mean(x, na.rm = TRUE)) * 100,
Skewness = moments::skewness(x, na.rm = TRUE),
Kurtosis = moments::kurtosis(x, na.rm = TRUE)
)
}
# Tính toán cho các biến số
stats_diem <- calc_stats(data$Diem_thi)
stats_income <- calc_stats(data$Thu_nhap)
stats_age <- calc_stats(data$Tuoi)
# Tạo bảng tổng hợp
stats_table <- data.frame(
Dai_luong = c("Trung bình (Mean)", "Trung vị (Median)", "Mode",
"Giá trị nhỏ nhất", "Giá trị lớn nhất", "Khoảng biến thiên",
"Tứ phân vị Q1", "Tứ phân vị Q3", "Khoảng tứ phân vị IQR",
"Phương sai", "Độ lệch chuẩn", "Hệ số biến thiên CV (%)",
"Độ lệch (Skewness)", "Độ nhọn (Kurtosis)"),
Diem_thi = round(stats_diem, 2),
Thu_nhap = round(stats_income, 2),
Tuoi = round(stats_age, 2)
)
kable(stats_table,
caption = "Bảng tổng hợp các đại lượng thống kê mô tả",
col.names = c("Đại lượng", "Điểm thi", "Thu nhập", "Tuổi")) %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE)| Đại lượng | Điểm thi | Thu nhập | Tuổi | |
|---|---|---|---|---|
| Mean | Trung bình (Mean) | 69.99 | 14.55 | 34.63 |
| Median | Trung vị (Median) | 69.65 | 15.30 | 35.00 |
| Mode | Mode | 75.60 | 11.80 | 36.00 |
| Min | Giá trị nhỏ nhất | 30.30 | -0.20 | 11.00 |
| Max | Giá trị lớn nhất | 102.50 | 26.80 | 59.00 |
| Range | Khoảng biến thiên | 72.20 | 27.00 | 48.00 |
| Q1.25% | Tứ phân vị Q1 | 60.40 | 10.98 | 29.25 |
| Q3.75% | Tứ phân vị Q3 | 79.38 | 17.90 | 40.00 |
| IQR | Khoảng tứ phân vị IQR | 18.98 | 6.92 | 10.75 |
| Variance | Phương sai | 167.49 | 24.69 | 60.10 |
| SD | Độ lệch chuẩn | 12.94 | 4.97 | 7.75 |
| CV | Hệ số biến thiên CV (%) | 18.49 | 34.14 | 22.39 |
| Skewness | Độ lệch (Skewness) | -0.02 | -0.22 | 0.00 |
| Kurtosis | Độ nhọn (Kurtosis) | 2.93 | 2.92 | 3.43 |
# Thống kê Điểm thi theo Nhóm
stats_by_nhom <- data %>%
group_by(Nhom) %>%
summarise(
N = n(),
Mean = round(mean(Diem_thi), 2),
Median = round(median(Diem_thi), 2),
SD = round(sd(Diem_thi), 2),
Min = round(min(Diem_thi), 2),
Max = round(max(Diem_thi), 2)
)
kable(stats_by_nhom,
caption = "Thống kê Điểm thi theo Nhóm",
col.names = c("Nhóm", "N", "TB", "Trung vị", "Độ lệch chuẩn", "Min", "Max")) %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE)| Nhóm | N | TB | Trung vị | Độ lệch chuẩn | Min | Max |
|---|---|---|---|---|---|---|
| A | 42 | 71.04 | 69.10 | 14.58 | 44.8 | 102.5 |
| B | 54 | 67.53 | 67.05 | 12.82 | 30.3 | 92.1 |
| C | 54 | 71.62 | 74.10 | 11.50 | 46.6 | 98.5 |
# Thống kê Thu nhập theo Giới tính
stats_by_gender <- data %>%
group_by(Gioi_tinh) %>%
summarise(
N = n(),
Mean = round(mean(Thu_nhap), 2),
Median = round(median(Thu_nhap), 2),
SD = round(sd(Thu_nhap), 2),
Min = round(min(Thu_nhap), 2),
Max = round(max(Thu_nhap), 2)
)
kable(stats_by_gender,
caption = "Thống kê Thu nhập theo Giới tính",
col.names = c("Giới tính", "N", "TB", "Trung vị", "Độ lệch chuẩn", "Min", "Max")) %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE)| Giới tính | N | TB | Trung vị | Độ lệch chuẩn | Min | Max |
|---|---|---|---|---|---|---|
| Nam | 78 | 14.03 | 14.40 | 4.95 | 1.6 | 24.3 |
| Nu | 72 | 15.12 | 15.55 | 4.96 | -0.2 | 26.8 |
# Ước lượng điểm
point_est_diem <- mean(data$Diem_thi)
# Ước lượng khoảng (95%)
ci_diem <- t.test(data$Diem_thi, conf.level = 0.95)$conf.int
cat("Ước lượng điểm trung bình Điểm thi:", round(point_est_diem, 2), "\n")## Ước lượng điểm trung bình Điểm thi: 69.99
## Khoảng tin cậy 95%: [ 67.9 , 72.07 ]
Giải thích: Với độ tin cậy 95%, trung bình điểm thi của tổng thể nằm trong khoảng [67.9, 72.07].
point_est_income <- mean(data$Thu_nhap)
ci_income <- t.test(data$Thu_nhap, conf.level = 0.95)$conf.int
cat("Ước lượng điểm trung bình Thu nhập:", round(point_est_income, 2), "triệu\n")## Ước lượng điểm trung bình Thu nhập: 14.55 triệu
## Khoảng tin cậy 95%: [ 13.75 , 15.35 ]
# Tỉ lệ thành công
success_count <- sum(data$Thanh_cong == "Co")
n_total <- nrow(data)
p_hat <- success_count / n_total
# Khoảng tin cậy cho tỉ lệ
prop_test <- prop.test(success_count, n_total, conf.level = 0.95)
cat("Ước lượng điểm tỉ lệ thành công:", round(p_hat, 4), "\n")## Ước lượng điểm tỉ lệ thành công: 0.5667
cat("Khoảng tin cậy 95%: [", round(prop_test$conf.int[1], 4), ",",
round(prop_test$conf.int[2], 4), "]\n")## Khoảng tin cậy 95%: [ 0.4834 , 0.6465 ]
Giải thích: Tỉ lệ thành công ước tính là 56.67%, với khoảng tin cậy 95% là [48.34%, 64.65%].
# Phương sai mẫu
s2 <- var(data$Diem_thi)
n <- length(data$Diem_thi)
# Khoảng tin cậy cho phương sai (dùng phân phối Chi-squared)
alpha <- 0.05
chi_lower <- qchisq(1 - alpha/2, df = n - 1)
chi_upper <- qchisq(alpha/2, df = n - 1)
var_ci_lower <- (n - 1) * s2 / chi_lower
var_ci_upper <- (n - 1) * s2 / chi_upper
cat("Ước lượng điểm phương sai Điểm thi:", round(s2, 2), "\n")## Ước lượng điểm phương sai Điểm thi: 167.49
cat("Khoảng tin cậy 95% cho phương sai: [", round(var_ci_lower, 2), ",",
round(var_ci_upper, 2), "]\n")## Khoảng tin cậy 95% cho phương sai: [ 135.13 , 213.12 ]
cat("Khoảng tin cậy 95% cho độ lệch chuẩn: [", round(sqrt(var_ci_lower), 2), ",",
round(sqrt(var_ci_upper), 2), "]\n")## Khoảng tin cậy 95% cho độ lệch chuẩn: [ 11.62 , 14.6 ]
Bài toán: Kiểm định xem điểm thi trung bình có bằng 68 không?
# H0: μ = 68
# H1: μ ≠ 68
mu0 <- 68
test_diem <- t.test(data$Diem_thi, mu = mu0, alternative = "two.sided")
print(test_diem)##
## One Sample t-test
##
## data: data$Diem_thi
## t = 1.8788, df = 149, p-value = 0.06222
## alternative hypothesis: true mean is not equal to 68
## 95 percent confidence interval:
## 67.89729 72.07338
## sample estimates:
## mean of x
## 69.98533
##
## --- KẾT LUẬN ---
## Giá trị p = 0.0622
if (test_diem$p.value < 0.05) {
cat("Kết luận: Bác bỏ H0 ở mức ý nghĩa 5%.\n")
cat("Có bằng chứng thống kê cho rằng điểm thi trung bình KHÁC ", mu0, "\n")
} else {
cat("Kết luận: Chưa đủ bằng chứng để bác bỏ H0 ở mức ý nghĩa 5%.\n")
cat("Điểm thi trung bình có thể bằng ", mu0, "\n")
}## Kết luận: Chưa đủ bằng chứng để bác bỏ H0 ở mức ý nghĩa 5%.
## Điểm thi trung bình có thể bằng 68
Bài toán: Kiểm định xem thu nhập trung bình có lớn hơn 14 triệu không?
# H0: μ ≤ 14
# H1: μ > 14
mu0_income <- 14
test_income <- t.test(data$Thu_nhap, mu = mu0_income, alternative = "greater")
print(test_income)##
## One Sample t-test
##
## data: data$Thu_nhap
## t = 1.3623, df = 149, p-value = 0.08757
## alternative hypothesis: true mean is greater than 14
## 95 percent confidence interval:
## 13.88122 Inf
## sample estimates:
## mean of x
## 14.55267
##
## --- KẾT LUẬN ---
## Giá trị p = 0.0876
if (test_income$p.value < 0.05) {
cat("Kết luận: Bác bỏ H0 ở mức ý nghĩa 5%.\n")
cat("Có bằng chứng thống kê cho rằng thu nhập trung bình LỚN HƠN ", mu0_income, " triệu\n")
} else {
cat("Kết luận: Chưa đủ bằng chứng để bác bỏ H0.\n")
}## Kết luận: Chưa đủ bằng chứng để bác bỏ H0.
Bài toán: Kiểm định xem tỉ lệ thành công có bằng 50% không?
# H0: p = 0.5
# H1: p ≠ 0.5
success_count <- sum(data$Thanh_cong == "Co")
n_total <- nrow(data)
test_prop <- prop.test(success_count, n_total, p = 0.5, alternative = "two.sided")
print(test_prop)##
## 1-sample proportions test with continuity correction
##
## data: success_count out of n_total, null probability 0.5
## X-squared = 2.4067, df = 1, p-value = 0.1208
## alternative hypothesis: true p is not equal to 0.5
## 95 percent confidence interval:
## 0.4833624 0.6465034
## sample estimates:
## p
## 0.5666667
##
## --- KẾT LUẬN ---
## Giá trị p = 0.1208
if (test_prop$p.value < 0.05) {
cat("Kết luận: Bác bỏ H0 ở mức ý nghĩa 5%.\n")
cat("Tỉ lệ thành công KHÁC 50%\n")
} else {
cat("Kết luận: Chưa đủ bằng chứng để bác bỏ H0.\n")
cat("Tỉ lệ thành công có thể bằng 50%\n")
}## Kết luận: Chưa đủ bằng chứng để bác bỏ H0.
## Tỉ lệ thành công có thể bằng 50%
Bài toán: So sánh điểm thi trung bình giữa Nam và Nữ
# Tách dữ liệu theo giới tính
diem_nam <- data$Diem_thi[data$Gioi_tinh == "Nam"]
diem_nu <- data$Diem_thi[data$Gioi_tinh == "Nu"]
# Kiểm tra phân phối chuẩn
shapiro_nam <- shapiro.test(diem_nam)
shapiro_nu <- shapiro.test(diem_nu)
cat("Kiểm định phân phối chuẩn (Shapiro-Wilk):\n")## Kiểm định phân phối chuẩn (Shapiro-Wilk):
cat("Nam: p =", round(shapiro_nam$p.value, 4),
ifelse(shapiro_nam$p.value > 0.05, "(Chuẩn)", "(Không chuẩn)"), "\n")## Nam: p = 0.6029 (Chuẩn)
cat("Nữ: p =", round(shapiro_nu$p.value, 4),
ifelse(shapiro_nu$p.value > 0.05, "(Chuẩn)", "(Không chuẩn)"), "\n\n")## Nữ: p = 0.5575 (Chuẩn)
# Kiểm định phương sai bằng nhau (Levene's test)
levene_test <- car::leveneTest(Diem_thi ~ Gioi_tinh, data = data)
cat("Kiểm định Levene (đồng phương sai): p =", round(levene_test$`Pr(>F)`[1], 4), "\n\n")## Kiểm định Levene (đồng phương sai): p = 0.3587
# Kiểm định t hai mẫu độc lập
# H0: μ_nam = μ_nữ
# H1: μ_nam ≠ μ_nữ
if (levene_test$`Pr(>F)`[1] > 0.05) {
test_two_means <- t.test(diem_nam, diem_nu, var.equal = TRUE)
cat("Sử dụng t-test với phương sai bằng nhau\n")
} else {
test_two_means <- t.test(diem_nam, diem_nu, var.equal = FALSE)
cat("Sử dụng Welch t-test (phương sai không bằng nhau)\n")
}## Sử dụng t-test với phương sai bằng nhau
##
## Two Sample t-test
##
## data: diem_nam and diem_nu
## t = -0.92463, df = 148, p-value = 0.3567
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
## -6.138321 2.225073
## sample estimates:
## mean of x mean of y
## 69.04615 71.00278
##
## --- KẾT LUẬN ---
## Giá trị p = 0.3567
if (test_two_means$p.value < 0.05) {
cat("Kết luận: Có sự KHÁC BIỆT có ý nghĩa thống kê về điểm thi giữa Nam và Nữ\n")
} else {
cat("Kết luận: KHÔNG có sự khác biệt có ý nghĩa thống kê về điểm thi giữa Nam và Nữ\n")
}## Kết luận: KHÔNG có sự khác biệt có ý nghĩa thống kê về điểm thi giữa Nam và Nữ
Bài toán mẫu: Giả sử so sánh điểm thi trước và sau (dữ liệu giả định)
# Tạo dữ liệu giả định điểm trước và sau
set.seed(456)
diem_truoc <- data$Diem_thi[1:50]
diem_sau <- diem_truoc + rnorm(50, mean = 3, sd = 5) # Tăng trung bình 3 điểm
# Kiểm định paired t-test
# H0: μ_trước = μ_sau (hay μ_d = 0)
# H1: μ_trước ≠ μ_sau
test_paired <- t.test(diem_truoc, diem_sau, paired = TRUE)
print(test_paired)##
## Paired t-test
##
## data: diem_truoc and diem_sau
## t = -5.0022, df = 49, p-value = 7.679e-06
## alternative hypothesis: true mean difference is not equal to 0
## 95 percent confidence interval:
## -5.238186 -2.235643
## sample estimates:
## mean difference
## -3.736915
##
## --- KẾT LUẬN ---
## Giá trị p = 0
if (test_paired$p.value < 0.05) {
cat("Kết luận: Có sự KHÁC BIỆT có ý nghĩa giữa điểm trước và sau\n")
} else {
cat("Kết luận: KHÔNG có sự khác biệt có ý nghĩa giữa điểm trước và sau\n")
}## Kết luận: Có sự KHÁC BIỆT có ý nghĩa giữa điểm trước và sau
Bài toán: So sánh tỉ lệ thành công giữa Nam và Nữ
##
## Co Khong
## Nam 45 33
## Nu 40 32
# Kiểm định so sánh tỉ lệ
# H0: p_nam = p_nữ
# H1: p_nam ≠ p_nữ
test_two_props <- prop.test(table_success[, "Co"], rowSums(table_success))
print(test_two_props)##
## 2-sample test for equality of proportions with continuity correction
##
## data: table_success[, "Co"] out of rowSums(table_success)
## X-squared = 0.0097894, df = 1, p-value = 0.9212
## alternative hypothesis: two.sided
## 95 percent confidence interval:
## -0.1507155 0.1934505
## sample estimates:
## prop 1 prop 2
## 0.5769231 0.5555556
##
## --- KẾT LUẬN ---
## Giá trị p = 0.9212
if (test_two_props$p.value < 0.05) {
cat("Kết luận: Tỉ lệ thành công giữa Nam và Nữ KHÁC NHAU có ý nghĩa thống kê\n")
} else {
cat("Kết luận: Tỉ lệ thành công giữa Nam và Nữ KHÔNG khác nhau có ý nghĩa thống kê\n")
}## Kết luận: Tỉ lệ thành công giữa Nam và Nữ KHÔNG khác nhau có ý nghĩa thống kê
Bài toán: So sánh phương sai điểm thi giữa Nam và Nữ
# F-test để so sánh phương sai
# H0: σ²_nam = σ²_nữ
# H1: σ²_nam ≠ σ²_nữ
test_var <- var.test(diem_nam, diem_nu)
print(test_var)##
## F test to compare two variances
##
## data: diem_nam and diem_nu
## F = 1.1801, num df = 77, denom df = 71, p-value = 0.4809
## alternative hypothesis: true ratio of variances is not equal to 1
## 95 percent confidence interval:
## 0.7436635 1.8645732
## sample estimates:
## ratio of variances
## 1.180099
##
## --- KẾT LUẬN ---
## Giá trị p = 0.4809
if (test_var$p.value < 0.05) {
cat("Kết luận: Phương sai điểm thi giữa Nam và Nữ KHÁC NHAU có ý nghĩa thống kê\n")
} else {
cat("Kết luận: Phương sai điểm thi giữa Nam và Nữ KHÔNG khác nhau có ý nghĩa thống kê\n")
}## Kết luận: Phương sai điểm thi giữa Nam và Nữ KHÔNG khác nhau có ý nghĩa thống kê
Bài toán: So sánh điểm thi trung bình giữa 3 nhóm A, B, C
# Kiểm tra giả định phân phối chuẩn cho từng nhóm
cat("Kiểm định tính chuẩn (Shapiro-Wilk) cho từng nhóm:\n")## Kiểm định tính chuẩn (Shapiro-Wilk) cho từng nhóm:
for (group in unique(data$Nhom)) {
subset_data <- data$Diem_thi[data$Nhom == group]
shapiro_result <- shapiro.test(subset_data)
cat("Nhóm", group, ": p =", round(shapiro_result$p.value, 4), "\n")
}## Nhóm C : p = 0.1522
## Nhóm B : p = 0.4625
## Nhóm A : p = 0.0894
##
## Kiểm định Levene (đồng phương sai):
## Levene's Test for Homogeneity of Variance (center = median)
## Df F value Pr(>F)
## group 2 1.0241 0.3617
## 147
##
## --- PHÂN TÍCH ANOVA ---
# H0: μ_A = μ_B = μ_C
# H1: Tồn tại ít nhất một cặp khác nhau
anova_model <- aov(Diem_thi ~ Nhom, data = data)
anova_summary <- summary(anova_model)
print(anova_summary)## Df Sum Sq Mean Sq F value Pr(>F)
## Nhom 2 518 258.8 1.557 0.214
## Residuals 147 24439 166.2
##
## --- KẾT LUẬN ANOVA ---
## Giá trị p = 0.2143
if (p_value_anova < 0.05) {
cat("Kết luận: Có sự KHÁC BIỆT có ý nghĩa thống kê về điểm thi giữa các nhóm\n")
cat("Cần thực hiện phân tích sâu (post-hoc test) để xác định nhóm nào khác nhau\n")
} else {
cat("Kết luận: KHÔNG có sự khác biệt có ý nghĩa thống kê giữa các nhóm\n")
}## Kết luận: KHÔNG có sự khác biệt có ý nghĩa thống kê giữa các nhóm
# Tukey HSD (Honest Significant Difference)
tukey_result <- TukeyHSD(anova_model, conf.level = 0.95)
print(tukey_result)## Tukey multiple comparisons of means
## 95% family-wise confidence level
##
## Fit: aov(formula = Diem_thi ~ Nhom, data = data)
##
## $Nhom
## diff lwr upr p adj
## B-A -3.512698 -9.793545 2.768148 0.3840537
## C-A 0.581746 -5.699100 6.862593 0.9738407
## C-B 4.094444 -1.780749 9.969638 0.2281275
# Vẽ biểu đồ Tukey
plot(tukey_result, las = 1, col = "blue")
title("Tukey HSD - So sánh từng cặp nhóm")##
## --- GIẢI THÍCH TUKEYHSD ---
tukey_df <- as.data.frame(tukey_result$Nhom)
tukey_df$Comparison <- rownames(tukey_df)
tukey_df <- tukey_df[, c("Comparison", "diff", "lwr", "upr", "p adj")]
kable(tukey_df,
caption = "Bảng kết quả Tukey HSD",
col.names = c("So sánh", "Chênh lệch TB", "CI dưới", "CI trên", "p điều chỉnh"),
digits = 3) %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE)| So sánh | Chênh lệch TB | CI dưới | CI trên | p điều chỉnh | |
|---|---|---|---|---|---|
| B-A | B-A | -3.513 | -9.794 | 2.768 | 0.384 |
| C-A | C-A | 0.582 | -5.699 | 6.863 | 0.974 |
| C-B | C-B | 4.094 | -1.781 | 9.970 | 0.228 |
##
## Các cặp có sự khác biệt có ý nghĩa (p < 0.05):
significant_pairs <- tukey_df[tukey_df$`p adj` < 0.05, ]
if (nrow(significant_pairs) > 0) {
print(significant_pairs$Comparison)
} else {
cat("Không có cặp nào khác biệt có ý nghĩa\n")
}## Không có cặp nào khác biệt có ý nghĩa
# Boxplot với trung bình
ggplot(data, aes(x = Nhom, y = Diem_thi, fill = Nhom)) +
geom_boxplot(alpha = 0.6) +
stat_summary(fun = mean, geom = "point", shape = 23, size = 4, fill = "red") +
stat_summary(fun = mean, geom = "line", aes(group = 1), color = "red", linetype = "dashed") +
labs(title = "Boxplot - Điểm thi theo Nhóm (Dấu đỏ = trung bình)",
x = "Nhóm", y = "Điểm thi") +
theme_minimal() +
theme(legend.position = "none")Bài toán: Kiểm định mối liên hệ giữa Nhóm và Thành công
##
## Co Khong
## A 22 20
## B 32 22
## C 31 23
# Kiểm định Chi-squared
# H0: Nhóm và Thành công độc lập
# H1: Nhóm và Thành công phụ thuộc
chi_test <- chisq.test(table_chi)
print(chi_test)##
## Pearson's Chi-squared test
##
## data: table_chi
## X-squared = 0.47404, df = 2, p-value = 0.789
##
## --- KẾT LUẬN ---
## Giá trị p = 0.789
if (chi_test$p.value < 0.05) {
cat("Kết luận: Nhóm và Thành công có MỐI LIÊN HỆ (phụ thuộc) có ý nghĩa thống kê\n")
} else {
cat("Kết luận: Nhóm và Thành công ĐỘC LẬP (không có mối liên hệ)\n")
}## Kết luận: Nhóm và Thành công ĐỘC LẬP (không có mối liên hệ)
##
## Tần số kỳ vọng:
##
## Co Khong
## A 23.8 18.2
## B 30.6 23.4
## C 30.6 23.4
##
## Residuals chuẩn hóa (|r| > 2 cho thấy ô có đóng góp lớn):
##
## Co Khong
## A -0.66 0.66
## B 0.48 -0.48
## C 0.14 -0.14
Bài toán: Kiểm định xem phân bố nhóm có đều đặn không?
# Tần số quan sát
observed <- table(data$Nhom)
# Giả thuyết: phân bố đều
# H0: p_A = p_B = p_C = 1/3
# H1: Không phải phân bố đều
expected_props <- c(1/3, 1/3, 1/3)
goodness_test <- chisq.test(observed, p = expected_props)
print(goodness_test)##
## Chi-squared test for given probabilities
##
## data: observed
## X-squared = 1.92, df = 2, p-value = 0.3829
##
## --- KẾT LUẬN ---
## Giá trị p = 0.3829
if (goodness_test$p.value < 0.05) {
cat("Kết luận: Phân bố các nhóm KHÔNG ĐỀU\n")
} else {
cat("Kết luận: Phân bố các nhóm ĐỀU (phù hợp với phân bố đều)\n")
}## Kết luận: Phân bố các nhóm ĐỀU (phù hợp với phân bố đều)
Bài toán: Kiểm định xem trung vị điểm thi có bằng 70 không?
# H0: median = 70
# H1: median ≠ 70
median0 <- 70
wilcox_one <- wilcox.test(data$Diem_thi, mu = median0, alternative = "two.sided")
print(wilcox_one)##
## Wilcoxon signed rank test with continuity correction
##
## data: data$Diem_thi
## V = 5676.5, p-value = 0.9798
## alternative hypothesis: true location is not equal to 70
##
## --- KẾT LUẬN ---
## Giá trị p = 0.9798
if (wilcox_one$p.value < 0.05) {
cat("Kết luận: Trung vị điểm thi KHÁC ", median0, "\n")
} else {
cat("Kết luận: Trung vị điểm thi có thể bằng ", median0, "\n")
}## Kết luận: Trung vị điểm thi có thể bằng 70
Bài toán: So sánh trung vị điểm thi giữa Nam và Nữ (phi tham số)
# H0: median_nam = median_nữ
# H1: median_nam ≠ median_nữ
wilcox_two <- wilcox.test(Diem_thi ~ Gioi_tinh, data = data, alternative = "two.sided")
print(wilcox_two)##
## Wilcoxon rank sum test with continuity correction
##
## data: Diem_thi by Gioi_tinh
## W = 2642, p-value = 0.5336
## alternative hypothesis: true location shift is not equal to 0
##
## --- KẾT LUẬN ---
## Giá trị p = 0.5336
if (wilcox_two$p.value < 0.05) {
cat("Kết luận: Trung vị điểm thi giữa Nam và Nữ KHÁC NHAU có ý nghĩa thống kê\n")
} else {
cat("Kết luận: Trung vị điểm thi giữa Nam và Nữ KHÔNG khác nhau có ý nghĩa thống kê\n")
}## Kết luận: Trung vị điểm thi giữa Nam và Nữ KHÔNG khác nhau có ý nghĩa thống kê
Bài toán: So sánh trung vị điểm trước và sau (dữ liệu phụ thuộc)
# Sử dụng dữ liệu paired từ Phần 5
# H0: median_trước = median_sau
# H1: median_trước ≠ median_sau
wilcox_paired <- wilcox.test(diem_truoc, diem_sau, paired = TRUE)
print(wilcox_paired)##
## Wilcoxon signed rank test with continuity correction
##
## data: diem_truoc and diem_sau
## V = 210, p-value = 3.757e-05
## alternative hypothesis: true location shift is not equal to 0
##
## --- KẾT LUẬN ---
## Giá trị p = 0
if (wilcox_paired$p.value < 0.05) {
cat("Kết luận: Trung vị điểm trước và sau KHÁC NHAU có ý nghĩa thống kê\n")
} else {
cat("Kết luận: Trung vị điểm trước và sau KHÔNG khác nhau có ý nghĩa thống kê\n")
}## Kết luận: Trung vị điểm trước và sau KHÁC NHAU có ý nghĩa thống kê
Bài toán: So sánh trung vị điểm thi giữa 3 nhóm A, B, C
# H0: median_A = median_B = median_C
# H1: Tồn tại ít nhất một cặp khác nhau
kruskal_test <- kruskal.test(Diem_thi ~ Nhom, data = data)
print(kruskal_test)##
## Kruskal-Wallis rank sum test
##
## data: Diem_thi by Nhom
## Kruskal-Wallis chi-squared = 2.7146, df = 2, p-value = 0.2574
##
## --- KẾT LUẬN ---
## Giá trị p = 0.2574
if (kruskal_test$p.value < 0.05) {
cat("Kết luận: Có sự KHÁC BIỆT có ý nghĩa về trung vị giữa các nhóm\n")
cat("Cần thực hiện post-hoc test (ví dụ: Dunn test)\n")
# Post-hoc: Dunn test
library(dunn.test)
dunn_result <- dunn.test(data$Diem_thi, data$Nhom, method = "bonferroni")
} else {
cat("Kết luận: KHÔNG có sự khác biệt có ý nghĩa về trung vị giữa các nhóm\n")
}## Kết luận: KHÔNG có sự khác biệt có ý nghĩa về trung vị giữa các nhóm
## R version 4.5.1 (2025-06-13 ucrt)
## Platform: x86_64-w64-mingw32/x64
## Running under: Windows 10 x64 (build 19045)
##
## Matrix products: default
## LAPACK version 3.12.1
##
## locale:
## [1] LC_COLLATE=English_United States.utf8
## [2] LC_CTYPE=English_United States.utf8
## [3] LC_MONETARY=English_United States.utf8
## [4] LC_NUMERIC=C
## [5] LC_TIME=English_United States.utf8
##
## time zone: Asia/Saigon
## tzcode source: internal
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] DescTools_0.99.60 agricolae_1.3-7 car_3.1-3 carData_3.0-5
## [5] nortest_1.0-4 gridExtra_2.3 kableExtra_1.4.0 knitr_1.50
## [9] lubridate_1.9.4 forcats_1.0.1 stringr_1.5.2 dplyr_1.1.4
## [13] purrr_1.1.0 readr_2.1.5 tidyr_1.3.1 tibble_3.3.0
## [17] ggplot2_4.0.0 tidyverse_2.0.0
##
## loaded via a namespace (and not attached):
## [1] tidyselect_1.2.1 Exact_3.3 viridisLite_0.4.2 rootSolve_1.8.2.4
## [5] farver_2.1.2 S7_0.2.0 fastmap_1.2.0 digest_0.6.37
## [9] timechange_0.3.0 lifecycle_1.0.4 cluster_2.1.8.1 lmom_3.2
## [13] magrittr_2.0.4 compiler_4.5.1 rlang_1.1.6 sass_0.4.10
## [17] tools_4.5.1 yaml_2.3.10 data.table_1.17.8 labeling_0.4.3
## [21] xml2_1.4.0 RColorBrewer_1.1-3 abind_1.4-8 expm_1.0-0
## [25] withr_3.0.2 grid_4.5.1 AlgDesign_1.2.1.2 e1071_1.7-16
## [29] scales_1.4.0 MASS_7.3-65 cli_3.6.5 mvtnorm_1.3-3
## [33] rmarkdown_2.30 generics_0.1.4 rstudioapi_0.17.1 httr_1.4.7
## [37] tzdb_0.5.0 readxl_1.4.5 gld_2.6.8 cachem_1.1.0
## [41] proxy_0.4-27 splines_4.5.1 cellranger_1.1.0 vctrs_0.6.5
## [45] boot_1.3-31 Matrix_1.7-3 jsonlite_2.0.0 hms_1.1.3
## [49] Formula_1.2-5 systemfonts_1.3.0 jquerylib_0.1.4 glue_1.8.0
## [53] stringi_1.8.7 gtable_0.3.6 pillar_1.11.1 htmltools_0.5.8.1
## [57] R6_2.6.1 textshaping_1.0.3 evaluate_1.0.5 lattice_0.22-7
## [61] haven_2.5.5 moments_0.14.1 bslib_0.9.0 class_7.3-23
## [65] Rcpp_1.1.0 svglite_2.2.1 nlme_3.1-168 mgcv_1.9-3
## [69] xfun_0.53 fs_1.6.6 pkgconfig_2.0.3