Cuốn sách Generalized Linear Models With Examples in R của Peter K. Dunn và Gordon K. Smyth (2018) là một tài liệu thống kê đầy đủ, trình bày khung chung của các mô hình tuyến tính tổng quát (GLM) cùng các ví dụ minh họa thực hiện bằng ngôn ngữ R. Ứng dụng của GLM rất rộng, bao gồm hồi quy tuyến tính thông thường, hồi quy logistic, các mô hình đếm (Poisson, âm), dữ liệu liên tục dương (Gamma, Inverse Gaussian), và cả tuyến tính tổng quát Tweedie. Sách trình bày khái niệm cơ bản, phương pháp ước lượng và kiểm định, cùng các vấn đề chẩn đoán, theo đúng trình tự từng chương. Phần mở đầu sau đây và mỗi chương tiếp theo sẽ tóm lược nội dung chính, công thức quan trọng và ví dụ R tương ứng (khi có). Các công thức được trình bày dưới dạng toán học canh giữa và các khối mã R được định dạng rõ ràng để dễ tham khảo.
Mô hình tuyến tính tổng quát (GLM) là một sự tổng quát hóa của mô hình hồi quy tuyến tính cổ điển, cho phép liên hệ tham số tuyến tính với biến phản hồi thông qua hàm liên kết, đồng thời cho phép phương sai phụ thuộc vào giá trị kỳ vọng.
Cụ thể, trong GLM, ta có ba thành phần chính:
Phân phối ngẫu nhiên của biến đáp ứng thuộc họ mũ cấp một (ví dụ: chuẩn, nhị thức, Poisson, Gamma, …).
Tổ hợp tuyến tính \(\eta = \mathbf{X}\boldsymbol{\beta}\) gồm các biến độc lập và hệ số ẩN.
Hàm liên kết \(g\) liên hệ kỳ vọng \(\mu=E(Y)\) với tổ hợp tuyến tính qua \(g(\mu)=\eta\). GLM do Nelder và Wedderburn đề xuất đã dùng phương pháp tổng bình phương lặp lại có trọng số (IRLS) để ước lượng cực đại xác suất cho tham số.
Trong các chương đầu, sách cũng nhắc lại các khái niệm cơ bản về mô hình thống kê: mô hình bao gồm thành phần hệ thống (phần chi tiết dự đoán thông qua \(\mathbf{X}\boldsymbol{\beta}\)) và thành phần ngẫu nhiên (phần sai số). Ví dụ, hồi quy tuyến tính chuẩn có dạng: \[y_i = \beta_0 + \beta_1 x_{i1} + \dots + \beta_p x_{ip} + \varepsilon_i,\quad \varepsilon_i \sim N(0,\sigma^2)\]
Tác giả nhấn mạnh việc trực quan hóa dữ liệu (vẽ đồ thị phân phối, biểu đồ tần suất, …) để hiểu mẫu trước khi xây mô hình, cũng như mã hóa biến phân loại thành biến giả (dummy variables) để đưa vào mô hình tuyến tính. Mục tiêu của mô hình là đánh giá và dự đoán, được xem xét qua hai tiêu chí chủ yếu: tính chính xác (accuracy) và độ gọn gàng (parsimony) của mô hình. Đồng thời, cần lưu ý giới hạn của mô hình: ví dụ, ta khác biệt giữa dữ liệu quan sát (observational) và dữ liệu thực nghiệm (experimental) khi rút ra kết luận, và cần kiểm tra tính khái quát của mô hình ra ngoài mẫu. Trong giới thiệu này, tác giả cũng cung cấp một số chỉ dẫn sơ bộ về cách sử dụng R để phân tích, chỉ ra nhiều hàm cơ bản như lm() và glm() và cách đọc kết quả, nhằm giúp sinh viên làm quen với công cụ tính toán.
Trong chương này, tác giả giới thiệu khái niệm mô hình thống kê như là một công cụ để mô tả dữ liệu thực nghiệm. Mô hình thống kê có hai thành phần: thành phần ngẫu nhiên (mô tả cách dữ liệu phát sinh thông qua phân phối xác suất) và thành phần hệ thống (mô tả các yếu tố giải thích ảnh hưởng đến biến phụ thuộc). Mỗi quan sát được giả định sinh ra từ một phân phối xác suất xác định, ví dụ một phân phối chuẩn với phương sai không đổi trong mô hình hồi quy tuyến tính cơ bản. Chương này nhấn mạnh rằng “mọi mô hình đều sai, nhưng một số rất hữu ích” (Box & Draper), nghĩa là mô hình chỉ là xấp xỉ thực tế. Các thuật ngữ quan trọng bao gồm biến phụ thuộc (hoặc biến phản hồi), biến giải thích (covariates), và tham số mô hình. Tác giả cũng đề cập đến cách xây dựng mô hình hồi quy tuyến tính cơ bản: ví dụ, phương trình hồi quy đơn giản \[y_i = \beta_0 + \beta_1 x_i + \epsilon_i,\quad \epsilon_i \sim N(0,\sigma^2)\]
# Ví dụ mô hình hồi quy tuyến tính trên dữ liệu mtcars
data(mtcars)
fit <- lm(mpg ~ wt + hp, data = mtcars)
summary(fit)
##
## Call:
## lm(formula = mpg ~ wt + hp, data = mtcars)
##
## Residuals:
## Min 1Q Median 3Q Max
## -3.941 -1.600 -0.182 1.050 5.854
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 37.22727 1.59879 23.285 < 2e-16 ***
## wt -3.87783 0.63273 -6.129 1.12e-06 ***
## hp -0.03177 0.00903 -3.519 0.00145 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 2.593 on 29 degrees of freedom
## Multiple R-squared: 0.8268, Adjusted R-squared: 0.8148
## F-statistic: 69.21 on 2 and 29 DF, p-value: 9.109e-12
Trong ví dụ trên, lm() được dùng để khớp mô hình hồi quy tuyến tính giữa biến tiêu thụ nhiên liệu mpg và các biến giải thích wt (trọng lượng xe) và hp (công suất). Kết quả summary(fit) cho biết hệ số ước lượng, sai số chuẩn và các giá trị p-value.
Ghi chú
Chương này mở rộng từ hồi quy tuyến tính đơn giản sang hồi quy tuyến tính đa biến. Mục tiêu là tìm các hệ số \(\beta_j\) tối ưu (theo tiêu chí bình phương tối tiểu) thỏa mãn: \[E[y_i|\mathbf{x}i] = \beta_0 + \beta_1 x{i1} + \dots + \beta_p x_{ip}.\]
Quá trình ước lượng thường dựa trên phép bình phương tối tiểu (OLS), cho ta nghiệm dạng đóng \(\hat{\boldsymbol{\beta}} = (X^TX)^{-1}X^T y\). Chương cũng đề cập đến cách ước lượng phương sai \(\sigma^2\) và sai số chuẩn của các hệ số.
# Hồi quy tuyến tính đa biến với tập dữ liệu iris (ví dụ minh họa)
data(iris)
fit2 <- lm(Sepal.Length ~ Sepal.Width + Petal.Length + Petal.Width, data = iris)
summary(fit2)
##
## Call:
## lm(formula = Sepal.Length ~ Sepal.Width + Petal.Length + Petal.Width,
## data = iris)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.82816 -0.21989 0.01875 0.19709 0.84570
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 1.85600 0.25078 7.401 9.85e-12 ***
## Sepal.Width 0.65084 0.06665 9.765 < 2e-16 ***
## Petal.Length 0.70913 0.05672 12.502 < 2e-16 ***
## Petal.Width -0.55648 0.12755 -4.363 2.41e-05 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.3145 on 146 degrees of freedom
## Multiple R-squared: 0.8586, Adjusted R-squared: 0.8557
## F-statistic: 295.5 on 3 and 146 DF, p-value: < 2.2e-16
Trong ví dụ trên, chúng ta sử dụng lm() với nhiều biến giải thích để dự đoán độ dài lá. Kết quả cho thấy các hệ số ước lượng, sai số và \(R^2\) tổng thể.
Ghi chú
Chương này tập trung vào chẩn đoán mô hình và chiến lược xây dựng mô hình cho hồi quy tuyến tính. Mục đích là đánh giá chất lượng của mô hình đã khớp, phát hiện các quan sát ngoại lai (outliers) hoặc ảnh hưởng lớn (influential points), và kiểm tra các giả định (tuyến tính, phân phối chuẩn của sai số, phương sai không đổi). Các loại sai số (residual) được sử dụng bao gồm dư sai số (residuals), dư sai số chuẩn hóa và độ đo Cook (Cook’s distance).
# Ví dụ trực quan hóa chẩn đoán hồi quy trên mtcars
par(mfrow = c(2, 2))
plot(fit)
Đoạn mã trên tạo ra 4 đồ thị cơ bản để kiểm tra các giả định mô hình hồi quy: đồ thị dư theo giá trị dự đoán, Q-Q plot để kiểm tra phân phối chuẩn của sai số, đồ thị Scale-Location và đồ thị ảnh hưởng (Cook’s distance).
Ghi chú - Quan sát ngoại lai có thể làm sai lệch kết quả ước lượng; cần kiểm tra residuals và Cook’s distance để phát hiện. - Nếu biểu đồ Q-Q lệch khỏi đường thẳng, phân phối sai số có thể không chuẩn. - Để cải thiện mô hình, có thể thử chuyển đổi biến (ví dụ logarithm) hoặc loại bỏ điểm ngoại lai đáng kể.
Chương này mở rộng khái niệm ước lượng không chỉ dựa trên phân phối chuẩn và bình phương tối tiểu, mà sử dụng phương pháp ước lượng cực đại hợp lý (Maximum Likelihood Estimation) cho các mô hình tổng quát hơn. Phương pháp này tìm tham số \(\boldsymbol{\beta}\) tối ưu bằng cách tối đa hóa hàm hợp lý (likelihood) của dữ liệu:
\[ L(\boldsymbol{\beta}) = \prod_{i=1}^n f(y_i; \boldsymbol{\beta}), \]
Trong đó \(f(y_i; \boldsymbol{\beta})\) là hàm mật độ/xác suất của \(y_i\). Giải thuật phổ biến để tìm ước lượng là phương pháp Newton-Raphson hoặc IRLS (phương pháp lặp có trọng số), sẽ được trình bày chi tiết ở chương sau. Chương này minh họa ý tưởng trên một ví dụ hồi quy logistic (dữ liệu nhị phân).
# Ví dụ hồi quy logistic với dữ liệu mtcars
logit_model <- glm(vs ~ mpg + wt, data = mtcars, family = binomial)
summary(logit_model)
##
## Call:
## glm(formula = vs ~ mpg + wt, family = binomial, data = mtcars)
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -12.5412 8.4660 -1.481 0.1385
## mpg 0.5241 0.2604 2.012 0.0442 *
## wt 0.5829 1.1845 0.492 0.6227
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 43.860 on 31 degrees of freedom
## Residual deviance: 25.298 on 29 degrees of freedom
## AIC: 31.298
##
## Number of Fisher Scoring iterations: 6
Trong ví dụ này, glm(…, family = binomial) được dùng để khớp mô hình logistic với biến kết quả nhị phân vs (0 hoặc 1). Kết quả cho thấy hệ số log-odds ước lượng và giá trị p-value tương ứng.
Ghi chú
Chương này định nghĩa khái niệm Mô hình tuyến tính tổng quát (GLM). GLM bao gồm ba thành phần chính:
Tùy thuộc vào phân phối của \(Y\), ta chọn hàm liên kết thích hợp (ví dụ: logit cho Bernoulli, log cho Poisson, identity cho chuẩn,…). GLM tổng quát hóa hồi quy tuyến tính bằng cách thay thế giả định phân phối chuẩn và liên kết tuyến tính qua hàm \(g\).
Ví dụ các phân phối thông dụng:
Chuẩn (Gaussian): \(g(\mu)=\mu\) (identity), phương sai không phụ thuộc (hằng).
Bernoulli/Binomial: \(g(\mu)=\mathrm{logit}(\mu)\), \(Var(Y)=\mu(1-\mu)\).
Poisson: \(g(\mu)=\log(\mu)\), \(Var(Y)=\mu\).
Gamma: \(g(\mu)=\log(\mu)\) hoặc \(g(\mu)=1/\mu\), \(Var(Y)=\phi \mu^2\).
# Ví dụ GLM: so sánh link identity và link log
set.seed(123)
x <- rnorm(100)
y <- exp(1 + 0.3*x + rnorm(100, sd = 0.2)) # y > 0 do exp
glm1 <- glm(y ~ x, family = gaussian(link = "identity"))
glm2 <- glm(y ~ x, family = gaussian(link = "log"))
summary(glm1)
##
## Call:
## glm(formula = y ~ x, family = gaussian(link = "identity"))
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 2.80666 0.05816 48.26 <2e-16 ***
## x 0.80555 0.06372 12.64 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for gaussian family taken to be 0.334907)
##
## Null deviance: 86.349 on 99 degrees of freedom
## Residual deviance: 32.821 on 98 degrees of freedom
## AIC: 178.38
##
## Number of Fisher Scoring iterations: 2
summary(glm2)
##
## Call:
## glm(formula = y ~ x, family = gaussian(link = "log"))
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 1.00209 0.02251 44.52 <2e-16 ***
## x 0.27423 0.02129 12.88 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for gaussian family taken to be 0.3286445)
##
## Null deviance: 86.349 on 99 degrees of freedom
## Residual deviance: 32.207 on 98 degrees of freedom
## AIC: 176.49
##
## Number of Fisher Scoring iterations: 4
Đoạn mã trên tạo dữ liệu giả định và khớp hai GLM với phân phối chuẩn nhưng dùng hàm liên kết khác nhau (identity và log). Kết quả hiển thị các hệ số ước lượng tương ứng.
Ghi chú
Chương này trình bày phương pháp tính toán các ước lượng của GLM, thường bằng phương pháp lặp. Do không có nghiệm đóng cho ước lượng cực đại hợp lý (ngoại trừ trường hợp Gaussian), GLM thường được ước lượng bằng phương pháp IRLS (Iteratively Reweighted Least Squares). Ý tưởng cơ bản là lặp lại công thức giống OLS nhưng với trọng số thay đổi tại mỗi bước, cho đến khi hội tụ. Chương cũng đề cập đến ma trận Fisher thông tin và các đặc trưng thống kê khác phục vụ cho ước lượng (ví dụ ma trận hiệp phương sai của ước lượng).
Phương pháp IRLS cập nhật nghiệm \(\beta\) theo dạng: \(\beta^{(t+1)} = \beta^{(t)} + (X^T W^{(t)} X)^{-1} X^T W^{(t)} (z^{(t)} - X\beta^{(t)}),\) trong đó \(W^{(t)}\) là ma trận trọng số tại lần lặp \(t\), và \(z^{(t)}\) là biến phụ hồi giả định (working response).
Ma trận trọng số \(W\) thường liên quan đến hàm phân tán: ví dụ với phân phối Poisson, \(W_{ii} = \hat{\mu}_i\).
Ma trận thông tin Fisher \(\mathcal{I}(\beta)\): \(\mathcal{I}(\beta) = X^T W X.\)
# Ví dụ GLM nhị thức trên dữ liệu kiểu thành công/thất bại
glm_model <- glm(cbind(Success, Failure) ~ x, family = binomial,
data = data.frame(x = 1:5, Success = c(1,2,3,4,5), Failure = c(9,8,7,6,5)))
summary(glm_model)
##
## Call:
## glm(formula = cbind(Success, Failure) ~ x, family = binomial,
## data = data.frame(x = 1:5, Success = c(1, 2, 3, 4, 5), Failure = c(9,
## 8, 7, 6, 5)))
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -2.4913 0.8910 -2.796 0.00517 **
## x 0.5137 0.2446 2.100 0.03575 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 5.036259 on 4 degrees of freedom
## Residual deviance: 0.094649 on 3 degrees of freedom
## AIC: 16.598
##
## Number of Fisher Scoring iterations: 4
Ở đây, chúng ta dùng glm() để ước lượng với dữ liệu dạng số thành công/thất bại cho mỗi mức \(x\). Hàm glm tự động thực hiện IRLS để tìm hệ số tối ưu.
Ghi chú
Chương này thảo luận các phương pháp kiểm định giả thuyết và suy diễn trên các mô hình GLM. Hai phương pháp phổ biến là kiểm định Wald và kiểm định tỷ lệ hợp lý (Likelihood Ratio Test, LRT). Ngoài ra, tác giả đề cập đến khoảng tin cậy (confidence intervals) và kiểm định chi-squared cho deviance. Deviance được định nghĩa là một thước đo khoảng cách giữa mô hình vừa khớp và mô hình bão hòa (mô hình tốt nhất có thể).
# So sánh hai mô hình lồng nhau bằng deviance (ví dụ với warpbreaks)
data(warpbreaks)
full_model <- glm(breaks ~ wool + tension, data = warpbreaks, family = poisson)
reduced_model <- glm(breaks ~ wool, data = warpbreaks, family = poisson)
anova(reduced_model, full_model, test="Chisq")
## Analysis of Deviance Table
##
## Model 1: breaks ~ wool
## Model 2: breaks ~ wool + tension
## Resid. Df Resid. Dev Df Deviance Pr(>Chi)
## 1 52 281.33
## 2 50 210.39 2 70.942 3.938e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Ví dụ trên cho thấy cách dùng hàm anova() để so sánh hai mô hình lồng nhau trong GLM. Giá trị p thu được dựa trên kiểm định \(\chi^2\), dựa trên sự chênh lệch deviance giữa hai mô hình.
Ghi chú
Chương này trình bày chẩn đoán cho GLM, bao gồm việc kiểm tra độ phù hợp của mô hình qua residuals và các chỉ số ảnh hưởng. Một số loại residual cho GLM: residual Pearson, residual deviance, residual deviance chuẩn hóa. Tác giả cũng thảo luận về leverage và Cook’s distance mở rộng cho GLM. Ngoài ra, có đề cập đến kiểm định độ phù hợp (độ lệch deviance so với phân phối \(\chi^2\)) và những dấu hiệu của overdispersion.
# Minh họa residuals trong GLM (với warpbreaks)
mod <- glm(breaks ~ wool + tension, data = warpbreaks, family = poisson)
par(mfrow = c(2, 2))
plot(mod)
Đoạn mã hiển thị các đồ thị chẩn đoán tương tự hồi quy tuyến tính (dư sai, dư Pearson, Q-Q plot, Cook’s distance). Từ đó có thể phát hiện quan sát có ảnh hưởng hoặc mô hình chưa phù hợp.
Ghi chú
Chương này nghiên cứu các trường hợp biến phụ thuộc là tỉ lệ hoặc số thành công/thất bại theo phân phối binomial. Ví dụ điển hình là hồi quy logistic (phân phối Bernoulli với hàm liên kết logit) hoặc GLM nhị thức chung (khi mỗi quan sát có số thử nghiệm \(n_i\)). Mô hình tổng quát: \[ Y_i \sim \text{Binomial}(n_i, \pi_i), \quad g(\pi_i) = \beta_0 + \beta_1 x_i. \]
Với hàm liên kết logit: \[\mathrm{logit}(\pi_i) = \log\frac{\pi_i}{1-\pi_i}.\]
# Hồi quy logistic (nhị thức) với dữ liệu giả định
set.seed(42)
x <- runif(100)
p <- 1 / (1 + exp(-(-1 + 2*x)))
y <- rbinom(100, size=1, prob=p)
df_bin <- data.frame(x, y)
logit_mod <- glm(y ~ x, data = df_bin, family = binomial)
summary(logit_mod)
##
## Call:
## glm(formula = y ~ x, family = binomial, data = df_bin)
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -0.5373 0.4107 -1.308 0.191
## x 1.1020 0.6820 1.616 0.106
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 138.59 on 99 degrees of freedom
## Residual deviance: 135.91 on 98 degrees of freedom
## AIC: 139.91
##
## Number of Fisher Scoring iterations: 4
Trong ví dụ trên, biến kết quả y là 0/1. Mô hình glm(…, family = binomial) ước lượng hệ số của hàm logit.
Ghi chú
Chương 10 tập trung vào các dữ liệu đếm: GLM Poisson và Negative Binomial. Mô hình Poisson thường dùng khi biến phụ thuộc là số đếm với giả định biến thiên bằng trung bình (\(Var(Y)=E(Y)\)) và dùng hàm liên kết log: \(g(\mu) = \log(\mu)\). Nếu dữ liệu có tính overdispersion (phương sai lớn hơn), GLM Poisson có thể không phù hợp; ta có thể sử dụng mô hình Negative Binomial để bao gồm thêm biến thiên.
# Ví dụ GLM Poisson và Negative Binomial
set.seed(123)
x_nb <- runif(100, 0, 5)
mu <- exp(1 + 0.5*x_nb)
y_pois <- rpois(100, lambda = mu)
y_nb <- rnbinom(100, size = 2, mu = mu) # over-dispersed
data_pois <- data.frame(x=x_nb, y=y_pois)
data_nb <- data.frame(x=x_nb, y=y_nb)
pois_mod <- glm(y ~ x, family = poisson, data = data_pois)
summary(pois_mod)
##
## Call:
## glm(formula = y ~ x, family = poisson, data = data_pois)
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 1.08957 0.08247 13.21 <2e-16 ***
## x 0.47329 0.02289 20.68 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for poisson family taken to be 1)
##
## Null deviance: 547.60 on 99 degrees of freedom
## Residual deviance: 64.83 on 98 degrees of freedom
## AIC: 477.73
##
## Number of Fisher Scoring iterations: 4
library(MASS)
nb_mod <- glm.nb(y ~ x, data = data_nb)
summary(nb_mod)
##
## Call:
## glm.nb(formula = y ~ x, data = data_nb, init.theta = 1.615587182,
## link = log)
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 0.83576 0.18804 4.445 8.81e-06 ***
## x 0.52375 0.06246 8.385 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for Negative Binomial(1.6156) family taken to be 1)
##
## Null deviance: 183.91 on 99 degrees of freedom
## Residual deviance: 111.72 on 98 degrees of freedom
## AIC: 640.88
##
## Number of Fisher Scoring iterations: 1
##
##
## Theta: 1.616
## Std. Err.: 0.283
##
## 2 x log-likelihood: -634.885
Ở trên, glm(…, family = poisson) khớp mô hình Poisson. Để dùng Negative Binomial, ta cần gói MASS và dùng glm.nb(). Kết quả summary(nb_mod) sẽ hiển thị hệ số ước lượng của mô hình Negative Binomial.
Ghi chú
Chương 11 xem xét các biến phụ thuộc liên tục dương, ví dụ thời gian hoặc khối lượng, bằng mô hình GLM phân phối Gamma hoặc Inverse Gaussian. Những phân phối này thích hợp khi dữ liệu luôn dương và có phương sai phụ thuộc vào bình phương trung bình (\(Var(Y)=\phi\mu^2\) cho Gamma). Thường dùng hàm liên kết log hoặc nghịch đảo (inverse) cho Gamma, và liên kết log cho Inverse Gaussian.
# Ví dụ GLM Gamma
set.seed(101)
x_gamma <- runif(100, 0, 5)
mu_g <- exp(2 + 0.3*x_gamma)
y_gamma <- rgamma(100, shape = 2, scale = mu_g/2) # E(Y)=mu_g, Var=k*mu^2
data_gamma <- data.frame(x=x_gamma, y=y_gamma)
gamma_mod <- glm(y ~ x, family = Gamma(link = "log"), data = data_gamma)
summary(gamma_mod)
##
## Call:
## glm(formula = y ~ x, family = Gamma(link = "log"), data = data_gamma)
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 2.4166 0.1502 16.090 < 2e-16 ***
## x 0.1392 0.0498 2.795 0.00625 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for Gamma family taken to be 0.5466223)
##
## Null deviance: 55.288 on 99 degrees of freedom
## Residual deviance: 51.331 on 98 degrees of freedom
## AIC: 736.64
##
## Number of Fisher Scoring iterations: 5
Trong ví dụ, glm(…, family = Gamma(link=“log”)) khớp mô hình Gamma với liên kết log. Kết quả cho hệ số ước lượng và ước lượng \(\phi\) (dispersion).
Ghi chú
Chương 12 giới thiệu mô hình Tweedie GLM, dùng khi dữ liệu có đặc trưng “giá trị 0 với xác suất dương và phân phối liên tục dương khi dương”. Tweedie là một họ phân phối con của phân phối hàm mũ, với tham số biến thiên \(p\). Ví dụ, \(p=1\) cho Poisson, \(p=2\) cho Gamma, và với \(1<p<2\) thì phân phối Tweedie có kết hợp tính chất rời rạc (giá trị 0) và liên tục. Tweedie thường dùng trong phân tích bảo hiểm (các tổn thất bảo hiểm) hoặc dữ liệu lượng có pha trộn rời rạc – liên tục.
# Gọi các thư viện
library(tweedie)
## Warning: package 'tweedie' was built under R version 4.3.3
library(statmod)
## Warning: package 'statmod' was built under R version 4.3.3
# Tạo dữ liệu
set.seed(202)
x_tw <- runif(100, 0, 5)
mu_tw <- exp(1 + 0.4 * x_tw)
y_tw <- rtweedie(100, mu = mu_tw, phi = 2, power = 1.5) # power = p
# Fit mô hình GLM với phân phối Tweedie
tweedie_mod <- glm(y_tw ~ x_tw, family = tweedie(var.power = 1.5, link.power = 0))
summary(tweedie_mod)
##
## Call:
## glm(formula = y_tw ~ x_tw, family = tweedie(var.power = 1.5,
## link.power = 0))
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 1.33030 0.18522 7.182 1.35e-10 ***
## x_tw 0.31903 0.05917 5.392 4.83e-07 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for Tweedie family taken to be 2.021416)
##
## Null deviance: 317.77 on 99 degrees of freedom
## Residual deviance: 259.53 on 98 degrees of freedom
## AIC: NA
##
## Number of Fisher Scoring iterations: 4
Trong đoạn mã, rtweedie được dùng để sinh dữ liệu Tweedie (ở đây \(p=1.5\)). Khi khớp mô hình, tweedie(var.power=1.5, link.power=0) sử dụng liên kết log.
Ghi chú
Chương cuối này chỉ gồm bài tập thực hành liên quan đến các nội dung đã học. Các bài tập yêu cầu người đọc áp dụng GLM để phân tích bộ dữ liệu mẫu, khớp mô hình phù hợp, thực hiện chẩn đoán, và so sánh các giả thuyết (ví dụ, sử dụng anova để so sánh các GLM lồng nhau). Đây là phần thực hành, nhằm củng cố kiến thức lý thuyết thông qua các bài tập cụ thể.
Ví dụ:
Cho dữ liệu đếm crab (về số hoa văn trên mai cua), khớp GLM Poisson/Negative Binomial và kiểm tra độ phù hợp.
Cho dữ liệu mtcars, khớp mô hình logistic phân loại xe theo biến vs, sau đó thực hiện kiểm định Likelihood Ratio so sánh với mô hình không chứa biến phụ.
Cho dữ liệu kết quả điều trị (số thành công/thất bại) và một biến giải thích \(x\), ước lượng mô hình glm(cbind(success, failure) ~ x, family=binomial) và suy diễn hệ số.
Các bài tập này giúp người học thực hành các công cụ R (glm, anova, summary, plot, …) đồng thời hiểu sâu hơn về mô hình GLM.
# Đọc dữ liệu và kiểm tra kích thước
data <- read.csv("C:/Users/HP/Downloads/Supermarket Transactions.csv", stringsAsFactors = FALSE)
dim(data); names(data)
## [1] 14059 16
## [1] "X" "PurchaseDate" "CustomerID"
## [4] "Gender" "MaritalStatus" "Homeowner"
## [7] "Children" "AnnualIncome" "City"
## [10] "StateorProvince" "Country" "ProductFamily"
## [13] "ProductDepartment" "ProductCategory" "UnitsSold"
## [16] "Revenue"
# Loại bỏ cột đánh số thừa (nếu có)
if("Unnamed..0" %in% names(data)) {
data <- subset(data, select = -c(Unnamed..0))
}
# Thông tin cấu trúc dữ liệu
str(data)
## 'data.frame': 14059 obs. of 16 variables:
## $ X : int 1 2 3 4 5 6 7 8 9 10 ...
## $ PurchaseDate : chr "2007-12-18" "2007-12-20" "2007-12-21" "2007-12-21" ...
## $ CustomerID : int 7223 7841 8374 9619 1900 6696 9673 354 1293 7938 ...
## $ Gender : chr "F" "M" "F" "M" ...
## $ MaritalStatus : chr "S" "M" "M" "M" ...
## $ Homeowner : chr "Y" "Y" "N" "Y" ...
## $ Children : int 2 5 2 3 3 3 2 2 3 1 ...
## $ AnnualIncome : chr "$30K - $50K" "$70K - $90K" "$50K - $70K" "$30K - $50K" ...
## $ City : chr "Los Angeles" "Los Angeles" "Bremerton" "Portland" ...
## $ StateorProvince : chr "CA" "CA" "WA" "OR" ...
## $ Country : chr "USA" "USA" "USA" "USA" ...
## $ ProductFamily : chr "Food" "Food" "Food" "Food" ...
## $ ProductDepartment: chr "Snack Foods" "Produce" "Snack Foods" "Snacks" ...
## $ ProductCategory : chr "Snack Foods" "Vegetables" "Snack Foods" "Candy" ...
## $ UnitsSold : int 5 5 3 4 4 3 4 6 1 2 ...
## $ Revenue : num 27.38 14.9 5.52 4.44 14 ...
# Chuyển đổi chuỗi ngày tháng sang kiểu Date trong R
data$PurchaseDate <- as.Date(data$PurchaseDate)
# Xác định khoảng thời gian ghi nhận giao dịch
range(data$PurchaseDate)
## [1] "2007-12-18" "2009-12-31"
Dữ liệu chứa các giao dịch mua hàng tại siêu thị theo từng đơn (bảng). Số dòng và số cột thể hiện quy mô và số biến quan sát. Sau khi loại bỏ cột chỉ mục thừa, ta kiểm tra cấu trúc. Dữ liệu có định dạng ngày tháng cho cột PurchaseDate từ cuối năm 2007 đến cuối năm 2009, cho thấy phạm vi gần 2 năm. Việc chuyển định dạng về Date cho phép phân tích xu hướng theo thời gian.
Supermarket Transactions là một bộ dữ liệu bao gồm 14059 quan sát và 16 biến, cụ thể là các biến:
Số thứ tự
Purchase Date: Ngày mua hàng
Customer ID: ID của khách hàng
Gender: Giới tính, với F (Female) là nữ và M (Male) là nam
Marital Status: Tình trạng hôn nhân, với S (Single) là độc thân và M(Married) là đã kết hôn
Homeowner: Đã có nhà hay chưa, với Y (Yes) là đã có nhà và N (No) là chưa có nhà
Children: Số con cái
Annual Income: Thu nhập hàng tháng
City: Thành phố đang sống
Stateor Province: Mã kí hiệu của bang
Country: Đất nước
Product Family: Nhóm sản phẩm, Food: Thực phẩm, Drink: Đồ uống và Non-Consumable: Hàng không tiêu dùng
Product Department: Nhóm sản phẩm chi tiết
Product Category: Danh mục sản phẩm
Units Sold: Doanh số bán hàng theo đơn vị
Revenue: Doanh thu
# ===================== BIẾN PURCHASEDATE =====================
# Thống kê số giao dịch theo năm và tháng
data$Year <- format(data$PurchaseDate, "%Y")
data$Month <- format(data$PurchaseDate, "%Y-%m")
table(data$Year)
##
## 2007 2008 2009
## 35 4692 9332
table(data$Month)
##
## 2007-12 2008-01 2008-02 2008-03 2008-04 2008-05 2008-06 2008-07 2008-08 2008-09
## 35 258 350 462 423 407 356 370 379 345
## 2008-10 2008-11 2008-12 2009-01 2009-02 2009-03 2009-04 2009-05 2009-06 2009-07
## 396 404 542 764 820 810 808 860 797 845
## 2009-08 2009-09 2009-10 2009-11 2009-12
## 825 827 849 807 320
# Vẽ biểu đồ tần số giao dịch theo tháng (tô đậm tháng)
library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.3.3
ggplot(data, aes(x = as.Date(paste0(Year, "-", format(as.Date(data$PurchaseDate), "%m"), "-01")))) +
geom_histogram(binwidth = 30, fill="skyblue", color="white") +
labs(title="Số giao dịch theo tháng", x="Tháng", y="Số giao dịch") +
theme_minimal()
## Warning: Use of `data$PurchaseDate` is discouraged.
## ℹ Use `PurchaseDate` instead.
Năm 2009 có nhiều giao dịch nhất (9.332 đơn), năm 2008 có ~4.692 đơn, còn năm 2007 chỉ là phần cuối năm (35 đơn), cho thấy tập dữ liệu tập trung chủ yếu 2008-2009.
Biểu đồ tần số theo tháng (giữa 2008-2009) cho thấy số giao dịch tăng dần trong năm 2009, đặc biệt tháng 5-10 năm 2009 khá cao. Cuối năm 2008 và đầu 2009 tăng vọt, có thể do các chương trình khuyến mãi mùa lễ hoặc gia tăng số khách.
Thông tin thời gian này gợi ý độ bao phủ thời gian và xu hướng tăng trưởng của điểm bán (có thể do mở rộng chuỗi hoặc gia tăng nhu cầu).
# ===================== BIẾN CUSTOMERID =====================
# Số khách hàng và số giao dịch trung bình mỗi khách
total_customers <- length(unique(data$CustomerID))
total_transactions <- nrow(data)
avg_trans_per_cust <- total_transactions / total_customers
list(total_transactions=total_transactions,
total_customers=total_customers,
avg_trans_per_customer=round(avg_trans_per_cust,2))
## $total_transactions
## [1] 14059
##
## $total_customers
## [1] 5404
##
## $avg_trans_per_customer
## [1] 2.6
Có tổng cộng r total_transactions giao dịch và r total_customers khách hàng khác nhau, trung bình mỗi khách khoảng r avg_trans_per_cust giao dịch trong khoảng thời gian 2 năm.
Điều này cho thấy hầu hết khách chỉ mua 1-2 lần, tạo nên độ đa dạng trong khách hàng. Nếu có khách mua lặp lại, đó có thể là khách quen. Dữ liệu không ngay lập tức cho biết mức độ trung thành, nhưng số lượng khách tương đối lớn so với giao dịch cho thấy thị trường khá nhiều người mua khác nhau.
# ======================== BIẾN GENDER ========================
# Tần suất theo giới tính
table(data$Gender)
##
## F M
## 7170 6889
prop.table(table(data$Gender)) * 100
##
## F M
## 50.99936 49.00064
# Vẽ biểu đồ cột cho giới tính
ggplot(data, aes(x = Gender, fill=Gender)) +
geom_bar(color="white") +
scale_fill_manual(values=c("pink","lightblue")) +
labs(title="Phân phối khách hàng theo Giới tính", x="Giới tính", y="Số lượng giao dịch") +
theme_minimal()
Phân phối cho thấy gần cân bằng giữa Nam (49%) và Nữ (51%), không chênh lệch nhiều. Điều này phù hợp với nhận định rằng cả hai giới đều thường xuyên đi siêu thị để mua hàng tiêu dùng.
Biểu đồ cột minh họa tỉ lệ bằng nhau giữa hai nhóm giới tính. Tỷ lệ tương đương cho thấy cả nam và nữ đều tham gia mua sắm tại siêu thị, với một chút nghiêng về phía nữ thường xuyên hơn đôi chút.
Trong ngữ cảnh tiêu dùng, thường nữ chiếm vai trò cao trong việc đi chợ/nấu ăn, nên tỉ lệ nữ cao hơn một chút có thể là do phụ nữ mua nhiều sản phẩm thiết yếu (như sữa, rau củ)
# ==================== BIẾN MARITALSTATUS ====================
# Tần suất theo tình trạng hôn nhân
table(data$MaritalStatus)
##
## M S
## 6866 7193
prop.table(table(data$MaritalStatus)) * 100
##
## M S
## 48.83704 51.16296
# Biểu đồ cột cho tình trạng hôn nhân
ggplot(data, aes(x = MaritalStatus, fill=MaritalStatus)) +
geom_bar(color="white") +
scale_fill_manual(values=c("orange","skyblue")) +
labs(title="Phân phối khách hàng theo Tình trạng hôn nhân",
x="Tình trạng", y="Số lượng giao dịch") +
theme_minimal()
Số lượng giao dịch của khách hàng độc thân (Single, 51%) và có gia đình (Married, 49%) gần như cân bằng.
Biểu đồ cho thấy gần bằng, hơi nghiêng về độc thân. Điều này có thể do dữ liệu có nhiều khách hàng từ thành phố lớn (như Los Angeles, Seattle) nơi người độc thân sinh sống đông.
Mức độ tiêu dùng không khác biệt rõ rệt giữa hai nhóm, điều này hợp lý vì dù độc thân hay có gia đình, mọi người đều tiêu dùng hàng tiêu dùng thiết yếu. Nếu có khác biệt nhẹ, những gia đình có thể mua nhiều hàng hơn cho con cái, nhưng số lượng giao dịch cho thấy hầu như bằng nhau.
# ======================= BIẾN HOMEOWNER =======================
# Tần suất nhà sở hữu (Y/N)
table(data$Homeowner)
##
## N Y
## 5615 8444
prop.table(table(data$Homeowner)) * 100
##
## N Y
## 39.93883 60.06117
# Biểu đồ cột cho Homeowner
ggplot(data, aes(x = Homeowner, fill=Homeowner)) +
geom_bar(color="white") +
scale_fill_manual(values=c("green","gray")) +
labs(title="Tỷ lệ Khách hàng làm chủ sở hữu nhà",
x="Homeowner (Y/N)", y="Số lượng giao dịch") +
theme_minimal()
Khoảng 60% giao dịch bởi khách là chủ sở hữu nhà (Yes), 40% là người thuê hoặc không sở hữu (No).
Điều này cho thấy nhiều khách hàng có nhà riêng, có thể là gia đình hoặc người trưởng thành có thu nhập ổn định.
Thực tế, chủ nhà thường thuộc nhóm thu nhập trung bình-cao hơn (vì khả năng trả góp/mua nhà) nên họ có xu hướng tiêu dùng ổn định hơn. Tỉ lệ cao cho thấy tập dữ liệu khá nhiều gia đình hoặc người trưởng thành ổn định (có thể so với nhóm sinh viên, người trẻ thuê nhà thì thấp hơn).
# ======================= BIẾN CHILDREN =======================
# Thống kê biến số lượng con cái trong gia đình
summary(data$Children)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.00 1.00 3.00 2.53 4.00 5.00
table(data$Children)
##
## 0 1 2 3 4 5
## 1344 2718 2839 2893 2826 1439
# Biểu đồ phân bố số lượng con cái
ggplot(data, aes(x = factor(Children))) +
geom_bar(fill="lightgreen", color="white") +
labs(title="Phân phối số lượng con cái trong gia đình",
x="Số con", y="Số lượng giao dịch") +
theme_minimal()
Số con trung bình trong gia đình là khoảng 2.53 (độ lệch chuẩn ~1.49), phân vị thứ 50 (Median) là 3 con, số gia đình có 0 con không nhiều nhất, phổ biến nhất là từ 3-4 con.
Biểu đồ cho thấy 1-2 con chiếm nhiều (khoảng 25% và 22%), nhưng nhóm 3-4 con còn cao hơn (mỗi nhóm khoảng 20-23%). Điều này cho thấy trong dữ liệu này, các gia đình khá đông con. Đây có thể là do nhiều khách hàng đến từ các khu vực có tỷ lệ sinh cao (ví dụ ở một số bang Mexico hay vùng nông thôn Mỹ).
Thực tiễn cho thấy các gia đình đông con có nhu cầu mua nhiều mặt hàng thiết yếu hơn (thức ăn, đồ dùng trẻ em), điều này được ghi nhận ở nhiều nghiên cứu về tiêu dùng gia đình lớn. Sự gia tăng đơn hàng theo số con cho thấy xu hướng này: gia đình nhiều con mua sắm nhiều hơn, làm tăng trung bình doanh thu/giao dịch (xem phần phân tích kết hợp bên dưới).
# ===================== BIẾN ANNUALINCOME =====================
# Tần suất theo nhóm thu nhập hàng năm
table(data$AnnualIncome)
##
## $10K - $30K $110K - $130K $130K - $150K $150K + $30K - $50K
## 3090 643 760 273 4601
## $50K - $70K $70K - $90K $90K - $110K
## 2370 1709 613
# Sắp xếp mức thu nhập theo thứ tự thực
income_levels <- c("$10K - $30K", "$30K - $50K", "$50K - $70K", "$70K - $90K",
"$90K - $110K", "$110K - $130K", "$130K - $150K", "$150K +")
data$AnnualIncome <- factor(data$AnnualIncome, levels = income_levels)
ggplot(data, aes(x = AnnualIncome)) +
geom_bar(fill="gold", color="white") +
labs(title="Phân phối nhóm thu nhập khách hàng",
x="Thu nhập (USD mỗi năm)", y="Số lượng giao dịch") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
Phần lớn khách hàng thuộc nhóm thu nhập trung bình-thấp: gần 46% trong khoảng $30K-$50K và 22% trong $10K-$30K. Các nhóm thu nhập cao (trên $110K) chỉ chiếm tổng khoảng 10%.
Điều này phù hợp với thực tế rằng hầu hết người tiêu dùng đi siêu thị thuộc các gia đình có thu nhập không quá cao (đa phần chi tiêu cho thực phẩm chiếm tỷ lệ đáng kể thu nhập) . Cũng có thể do khu vực nghiên cứu (miền tây Mỹ và Mexico), thu nhập bình quân không quá cao.
Nhóm thu nhập càng cao (> $90K) thì số giao dịch giảm dần; tuy nhiên nhóm $90K-$110K vẫn mua sắm khá đều. Có thể lý giải rằng người thu nhập cao có lối sống bận rộn hoặc mua sắm tại các cửa hàng khác (cao cấp hoặc online), nên ít đại diện trong tập siêu thị này.
# ========================= BIẾN CITY =========================
# Tần suất giao dịch theo thành phố (chỉ liệt kê top 10)
city_counts <- sort(table(data$City), decreasing = TRUE)
head(city_counts, 10)
##
## Salem Tacoma Los Angeles Seattle Portland
## 1386 1257 926 922 876
## Spokane San Diego Hidalgo Bremerton Beverly Hills
## 875 866 845 834 811
# Lọc các thành phố lớn (>=500 giao dịch)
top_cities <- names(city_counts[city_counts >= 800])
ggplot(subset(data, City %in% top_cities), aes(x = City)) +
geom_bar(fill="steelblue", color="white") +
labs(title="Top thành phố theo số giao dịch (>=800 đơn)", x="Thành phố", y="Số giao dịch") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
Các thành phố đứng đầu theo số giao dịch gồm Salem, Tacoma, Los Angeles, Seattle, Portland… trong đó Salem (Oregon) và Tacoma (Washington) là cao nhất (>1.200 giao dịch mỗi thành phố). Beverly Hills cũng khá cao (~811).
Những thành phố này hầu hết nằm ở vùng Tây Bắc Mỹ (WA, OR, CA), gắn với bang có tập khách hàng đông (xem phần Bang ở dưới). Sự tập trung tại Salem và Tacoma có thể do dữ liệu từ một chuỗi siêu thị lớn tại khu vực đó.
Điều thú vị là Los Angeles và Seattle cũng nổi bật, phù hợp là các trung tâm dân cư lớn. Điều này cho thấy siêu thị hoạt động chủ yếu ở khu vực Tây nước Mỹ, với lượng khách ổn định và đa dạng (đô thị lớn & vừa).
# ================== BIẾN STATE or PROVINCE & COUNTRY ==================
# Phân bố theo tiểu bang/bang/quốc gia
table(data$Country)
##
## Canada Mexico USA
## 809 3688 9562
table(data$StateorProvince)
##
## BC CA DF Guerrero Jalisco OR Veracruz WA
## 809 2733 815 383 75 2262 464 4567
## Yucatan Zacatecas
## 654 1297
# Biểu đồ số giao dịch theo quốc gia
ggplot(data, aes(x = Country)) +
geom_bar(fill="violet", color="white") +
labs(title="Phân phối giao dịch theo quốc gia", x="Quốc gia", y="Số giao dịch") +
theme_minimal()
Có 3 quốc gia trong dữ liệu: Mỹ chiếm ưu thế (9562 giao dịch ~68%), Mexico ~3690 (~26%), Canada ~809 (~6%).
Trong Mỹ, các bang lớn nhất là Washington (WA) ~4567 giao dịch, tiếp đến California (CA) và Oregon (OR). Đây đều là bang Tây Mỹ giáp Thái Bình Dương. Ở Mexico, chủ yếu là các bang như Zacatecas, DF (Mexico City), Yucatan. Thực tế này có thể do mạng lưới cửa hàng tập trung vào vùng biên giới và miền Trung Mexico.
Trên biểu đồ, Mỹ có số giao dịch gấp ~2.6 lần Mexico và gấp ~12 lần Canada. Điều này phản ánh thị trường mục tiêu chính là người Mỹ. Các số liệu địa lý cho thấy xu hướng tiêu dùng địa phương: ví dụ người Tây Bắc Thái Bình Dương mua sắm cao (Seattle, Tacoma, Portland), trong khi ở Mexico là các trung tâm dân cư lớn.
# ==================== BIẾN PRODUCTFAMILY ====================
# Tần số theo nhóm sản phẩm chính
table(data$ProductFamily)
##
## Drink Food Non-Consumable
## 1250 10153 2656
ggplot(data, aes(x = ProductFamily, fill=ProductFamily)) +
geom_bar(color="white") +
labs(title="Số giao dịch theo Product Family",
x="Nhóm sản phẩm", y="Số giao dịch") +
theme_minimal()
Có 3 nhóm lớn nhất: “Food” (~10.153 đơn, ~72% giao dịch), “Non-Consumable” (~2656, ~19%), “Drink” (~1250, ~9%).
Nhóm “Food” chiếm đa số, cho thấy siêu thị này chủ yếu bán thực phẩm thiết yếu (rau củ, thịt, sữa, v.v.), phù hợp với cửa hàng tạp hóa thông thường. Nhóm “Non-Consumable” bao gồm đồ gia dụng, đồ vệ sinh, chăm sóc cá nhân, chiếm khoảng 1/5, phản ánh nhu cầu mua sắm gia dụng kèm theo.
Nhóm “Drink” chỉ khoảng 9%, tức khách hàng thường mua nước ngọt, nước uống ít hơn so với thực phẩm và đồ dùng. Đa phần khách mua chủ yếu thực phẩm với tỉ lệ cao, điều này hợp lý vì mỗi giỏ hàng thường có các mặt hàng cơ bản.
# ================= BIẾN PRODUCTDEPARTMENT ==================
# Xem 10 sản phẩm/thể loại phụ phổ biến nhất
dept_counts <- sort(table(data$ProductDepartment), decreasing=TRUE)
head(dept_counts, 10)
##
## Produce Snack Foods Household Frozen Foods
## 1994 1600 1420 1382
## Baking Goods Canned Foods Dairy Health and Hygiene
## 1072 977 903 893
## Deli Beverages
## 699 680
# Biểu đồ top 10 Product Department
top_depts <- names(head(dept_counts,10))
ggplot(subset(data, ProductDepartment %in% top_depts),
aes(x = ProductDepartment, fill=ProductDepartment)) +
geom_bar(color="white") +
labs(title="Top 10 Ngành hàng theo số giao dịch",
x="Ngành hàng", y="Số giao dịch") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
Các ngành hàng mua nhiều nhất gồm: Produce (rau củ, 1994 đơn), Snack Foods (đồ ăn vặt, 1600), Household (đồ gia dụng, 1420), Frozen Foods (1382), Baking Goods (1072), Canned Foods (977), Dairy (903), Health & Hygiene (893), Deli (699), Beverages (680).
Sản phẩm tươi (rau củ, quả), đồ ăn nhẹ và các nhu yếu phẩm thường xuyên đứng đầu, phù hợp với nhu cầu hàng ngày. Đặc biệt, Produce (rau củ quả) cao nhất 1994 đơn, cho thấy khách ưu tiên thực phẩm tươi. Snack Foods cũng cao chứng tỏ nhu cầu đồ ăn nhanh/gấp (thường dùng cho gia đình đông con hoặc nhu cầu ăn nhẹ).
Các ngành hàng khác như đồ gia dụng, đóng hộp, đông lạnh cũng quan trọng, phản ánh việc khách vừa mua thực phẩm vừa mua thêm đồ cần thiết cho gia đình. Nhìn chung, không có ngành hàng phụ rõ rệt, vì khách hàng có xu hướng mua xen kẽ nhiều loại hàng (đa dạng hóa).
# ================= BIẾN PRODUCTCATEGORY =================
# Top 10 mục mua nhiều nhất (Product Category)
cat_counts <- sort(table(data$ProductCategory), decreasing=TRUE)
head(cat_counts, 10)
##
## Vegetables Snack Foods Dairy Fruit
## 1728 1600 903 765
## Meat Jams and Jellies Baking Goods Bread
## 761 588 484 425
## Breakfast Foods Canned Soup
## 417 404
# Biểu đồ top 10 Product Category
top_cats <- names(head(cat_counts,10))
ggplot(subset(data, ProductCategory %in% top_cats),
aes(x = ProductCategory, fill=ProductCategory)) +
geom_bar(color="white") +
labs(title="Top 10 Danh mục sản phẩm theo số giao dịch",
x="Danh mục sản phẩm", y="Số giao dịch") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
Danh mục phổ biến nhất: Vegetables (rau), Snack Foods, Dairy, Fruit (trái cây), Meat (thịt), Jams and Jellies, Baking Goods, Bread, Breakfast Foods, Canned Soup… Những danh mục này giống với các mặt hàng thường mua trong khảo sát tiêu dùng, như rau củ, sữa, đồ ăn nhẹ, trái cây… (tuân theo xu hướng ưa chuộng thực phẩm tươi và tiện lợi)
Đặc biệt, rau củ (Vegetables) cao nhất ~1728 đơn, phản ánh thói quen ăn uống lành mạnh hoặc nhu cầu hàng ngày. Sữa (Dairy) và trái cây cũng nằm trong top. Đồ ăn nhanh (Snack Foods) cũng đứng đầu cho thấy nhu cầu tiện lợi cho gia đình (như trẻ em muốn ăn vặt, hay người lớn làm việc bận).
Các mặt hàng thiết yếu khác như bánh mì (Bread), hàng sáng (Breakfast) hay đồ đóng hộp (Canned Soup) cũng phổ biến, cho thấy khách hàng mua theo thực đơn và dự phòng. Dữ liệu phù hợp với thói quen mua hàng ở Mỹ/Canada/Mexico – ưu tiên thực phẩm cơ bản, tươi sống, và một số đồ ăn tiện lợi.
# ======================= BIẾN UNITSSOLD =======================
# Thống kê cơ bản về UnitsSold
summary(data$UnitsSold)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 1.000 3.000 4.000 4.081 5.000 8.000
# Histogram phân phối UnitsSold
ggplot(data, aes(x = UnitsSold)) +
geom_histogram(binwidth=1, fill="skyblue", color="white") +
scale_x_continuous(breaks=1:8) +
labs(title="Phân phối số lượng mặt hàng (UnitsSold)",
x="Số lượng (Units)", y="Số giao dịch") +
theme_minimal()
Số lượng mặt hàng trong mỗi giao dịch trung bình khoảng 4.08 đơn vị, phổ biến nhất là 3-5 (Median=4, Q1=3, Q3=5). Có ít giao dịch chỉ 1-2 đơn vị hoặc nhiều nhất 8 đơn vị.
Biểu đồ histogram cho thấy đa phần các giao dịch mua 3-5 đơn vị, thể hiện nhiều khách hàng mua từ vài món (có thể 3-5 sản phẩm) trong mỗi lần thanh toán. Ít có người mua cực ít (1) hoặc cực nhiều (>6) đơn vị.
Đây là xu hướng hợp lý cho giao dịch tại siêu thị: một giỏ hàng điển hình nhỏ gọn, không quá nhiều món. Giá trị doanh thu trung bình cũng ở mức tương ứng (xem biến Revenue phía dưới).
# ======================== BIẾN REVENUE =======================
# Thống kê cơ bản về Revenue
summary(data$Revenue)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.53 6.84 11.25 13.00 17.37 56.70
# Histogram phân phối Revenue
ggplot(data, aes(x = Revenue)) +
geom_histogram(bins=30, fill="salmon", color="white") +
labs(title="Phân phối giá trị đơn hàng (Revenue)",
x="Doanh thu (USD)", y="Số giao dịch") +
theme_minimal()
# Quan sát tương quan giữa UnitsSold và Revenue
library(ggpubr)
## Warning: package 'ggpubr' was built under R version 4.3.3
ggplot(data, aes(x = UnitsSold, y = Revenue)) +
geom_point(alpha=0.3, color="blue") +
labs(title="Mối quan hệ giữa số lượng và doanh thu",
x="Số lượng (Units)", y="Doanh thu (USD)") +
theme_minimal() +
stat_smooth(method="lm", se=FALSE, col="red")
## `geom_smooth()` using formula = 'y ~ x'
Doanh thu mỗi giao dịch trung bình khoảng 13.00 USD (khoảng ~300k VND). Phần lớn đơn hàng nằm trong khoảng $6.84 đến $17.37 (tứ phân vị). Có những đơn rất rẻ (thấp nhất ~ $0.53, thường là sản phẩm nhỏ) và đắt nhất ~ $56.7 (có thể là nhiều đơn vị hàng đắt tiền).
Biểu đồ histogram cho thấy phần lớn giao dịch ở mức thấp (<$20), biểu đồ tỉ lệ giảm dần khi doanh thu tăng. Điều này hợp lý vì hầu hết khách mua vài món giá vừa phải.
Đồ thị scatter giữa UnitsSold và Revenue cho thấy có tương quan dương yếu (R² thấp): không phải lúc nào nhiều sản phẩm thì doanh thu cao tương ứng. Ví dụ, mua nhiều đơn vị (6-8) nhưng có thể là hàng giá rẻ, ngược lại ít đơn vị (1-2) nhưng là sản phẩm đắt (ví dụ sản phẩm dinh dưỡng cao cấp). Trung bình, càng mua nhiều đơn vị thì doanh thu có khuynh hướng tăng, nhưng độ lệch lớn cho thấy sự đa dạng giá sản phẩm.
library(dplyr)
## Warning: package 'dplyr' was built under R version 4.3.3
##
## Attaching package: 'dplyr'
## The following object is masked from 'package:MASS':
##
## select
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
# Mối quan hệ giữa số con và doanh thu trung bình
data %>% group_by(Children) %>% summarize(avg_rev=round(mean(Revenue),2), count=n())
## # A tibble: 6 × 3
## Children avg_rev count
## <int> <dbl> <int>
## 1 0 12.3 1344
## 2 1 12.4 2718
## 3 2 12.5 2839
## 4 3 13.3 2893
## 5 4 13.7 2826
## 6 5 13.8 1439
Khi nhóm theo số con: Gia đình không có con có doanh thu trung bình ~$12.29, còn gia đình có từ 5 con có trung bình ~$13.84. Xu hướng chung là càng nhiều con thì trung bình chi tiêu cao hơn (giá trị giao dịch lớn hơn) do phải mua nhiều sản phẩm hơn cho gia đình lớn.
# Tính doanh thu trung bình theo quốc gia
data %>% group_by(Country) %>% summarize(avg_rev=round(mean(Revenue),2), total_rev=sum(Revenue))
## # A tibble: 3 × 3
## Country avg_rev total_rev
## <chr> <dbl> <dbl>
## 1 Canada 13.7 11067.
## 2 Mexico 13.1 48475.
## 3 USA 12.9 123289.
Theo quốc gia: trung bình mỗi giao dịch của Canada cao nhất ($13.68), tiếp theo Mexico ($13.14) và thấp nhất ở Mỹ (~$12.89). Tuy khác không nhiều, nhưng có thể do khách Canada mua ít nhưng mỗi lần chi nhiều hơn, còn khách Mỹ có nhiều giao dịch nhưng giá trị vừa phải (có thể do khuyến mãi rộng, người mua lặp lại nhiều).
# Doanh thu trung bình theo nhóm thu nhập
data %>% group_by(AnnualIncome) %>% summarize(avg_rev=round(mean(Revenue),2), count=n())
## # A tibble: 8 × 3
## AnnualIncome avg_rev count
## <fct> <dbl> <int>
## 1 $10K - $30K 12.9 3090
## 2 $30K - $50K 13.0 4601
## 3 $50K - $70K 13.0 2370
## 4 $70K - $90K 13.0 1709
## 5 $90K - $110K 13.6 613
## 6 $110K - $130K 13.4 643
## 7 $130K - $150K 12.7 760
## 8 $150K + 12.4 273
Theo thu nhập: sự khác biệt không rõ ràng, dao động quanh 12-13.5 USD. Nhóm trung lưu ($90-110K) mua mạnh nhất (trung bình $13.55), trong khi nhóm cực cao ($150K+) ngược lại thấp ($12.35). Có thể do người thu nhập rất cao mua ở nơi khác (cửa hàng cao cấp, siêu thị khác) hoặc mua không thường xuyên tại siêu thị này.
ggplot(data, aes(x = factor(Children>0, labels=c("Không có con","Có con")), y = Revenue, fill=factor(Children>0))) +
geom_boxplot() +
labs(title="So sánh giá trị giao dịch (Revenue) theo việc có con hay không",
x="", y="Doanh thu (USD)") +
theme_minimal() +
theme(legend.position="none")
Boxplot theo có/không con cho thấy các gia đình có con có phân phối doanh thu rộng hơn (p50 cao hơn), hỗ trợ ý rằng họ chi nhiều hơn trên mỗi đơn hàng. Nhìn chung, người có con và thu nhập trung bình chi tiêu cao hơn một chút cho mỗi chuyến đi.
summary_data <- list(
transactions = total_transactions,
customers = total_customers,
perc_female = round(prop.table(table(data$Gender))*100,1),
perc_single = round(prop.table(table(data$MaritalStatus))*100,1),
avg_children = round(mean(data$Children),2),
main_country = names(sort(table(data$Country), decreasing=TRUE))[1],
avg_revenue = round(mean(data$Revenue),2)
)
summary_data
## $transactions
## [1] 14059
##
## $customers
## [1] 5404
##
## $perc_female
##
## F M
## 51 49
##
## $perc_single
##
## M S
## 48.8 51.2
##
## $avg_children
## [1] 2.53
##
## $main_country
## [1] "USA"
##
## $avg_revenue
## [1] 13
Dữ liệu cho thấy thị trường chính của chuỗi siêu thị là khu vực Tây Mỹ và Trung Mỹ (Mexico), với phần lớn khách hàng có thu nhập trung bình-thấp.
Khách hàng điển hình là các gia đình trưởng thành, đã kết hôn hoặc có con, mua trung bình ~4 mặt hàng giá tổng trung bình ~$13 mỗi lần đi chợ.
Các sản phẩm bán chạy nhất là thực phẩm tươi (rau củ quả, sữa, trái cây) và đồ ăn nhanh (Snack), phản ánh thói quen tiêu dùng sinh hoạt. Những gia đình đông con tiêu thụ nhiều hơn chút so với người không con, trong khi sự khác biệt giữa các nhóm giới tính hay tình trạng hôn nhân không lớn.
Kết quả này khớp với xu hướng tiêu dùng chung ở Bắc Mỹ, nơi bánh mì, sữa, trái cây và đồ ăn nhẹ là các mặt hàng thiết yếu phổ biến:contentReferenceoaicite:8. Quan trọng là mô hình phân tích này cho thấy mối liên hệ giữa đặc điểm khách hàng (số con, thu nhập) với giá trị mua sắm, giúp hiểu rõ hơn nhóm khách hàng mục tiêu cho siêu thị.