#Ngày 6: Hồi qui logistic
#Việc 1. Dữ liệu "Bone data.csv" và gọi dữ liệu này là “os”

dbone <- read.csv("E:\\HOPT\\PTDLR\\DATA\\Bone data.csv")
head(dbone)
##   id    sex age weight height prior.fx fnbmd smoking fx
## 1  1   Male  73     98    175        0  1.08       1  0
## 2  2 Female  68     72    166        0  0.97       0  0
## 3  3   Male  68     87    184        0  1.01       0  0
## 4  4 Female  62     72    173        0  0.84       1  0
## 5  5   Male  61     72    173        0  0.81       1  0
## 6  6 Female  76     57    156        0  0.74       0  0
dim(dbone)
## [1] 2162    9
#Việc 2. Đánh giá mối liên quan giữa hút thuốc (smoking) và nguy cơ gãy xương (fx)
#2.1 Thực hiện mô hình hồi qui logistic đánh giá mối liên quan giữa hút thuốc và nguy cơ gãy xương. Viết 1 câu văn giải thích kết quả

m.1 = glm(fx ~ smoking, family = binomial, data = dbone)
summary(m.1)
## 
## Call:
## glm(formula = fx ~ smoking, family = binomial, data = dbone)
## 
## Coefficients:
##             Estimate Std. Error z value Pr(>|z|)    
## (Intercept) -1.03006    0.06442 -15.990   <2e-16 ***
## smoking     -0.13796    0.10081  -1.368    0.171    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 2441.4  on 2161  degrees of freedom
## Residual deviance: 2439.5  on 2160  degrees of freedom
## AIC: 2443.5
## 
## Number of Fisher Scoring iterations: 4
#thư viện epiDisplay dành cho phân tích dữ liệu y tế và dịch tễ học (epidemiology). Nó cung cấp các hàm thân thiện, 
#Mục đích   Ví dụ hàm
#1. Tóm tắt biến định tính (categorical)    tab1()
#2.Tóm tắt biến định lượng (numeric)    tabstat()
#3. Thống kê mô tả toàn bộ dữ liệu  des()
#4.Phân tích hồi quy logistic   logistic.display()
#5.Phân tích hồi quy tuyến tính regress.display()
#6Kiểm định thống kê đơn giản   ci.mean() – tính CI, ci.prop()

library(epiDisplay)
## Loading required package: foreign
## Loading required package: survival
## Loading required package: MASS
## Loading required package: nnet
logistic.display(m.1)
## 
## Logistic regression predicting fx 
##  
##                  OR(95%CI)         P(Wald's test) P(LR-test)
## smoking: 1 vs 0  0.87 (0.71,1.06)  0.171          0.17      
##                                                             
## Log-likelihood = -1219.7469
## No. of observations = 2162
## AIC value = 2443.4938
#Kiểm tra biến fx (gãy xương) và smoke (hút thuốc). Nếu cần, chuyển về factor:
#dbone$fx <- factor(dbone$fx, levels = c(0, 1), labels = c("Không gãy", "Gãy"))
#dbone$smoke <- factor(dbone$smoking, levels = c(0, 1), labels = c("Không hút", "Hút thuốc"))


# 1. Đọc dữ liệu
dbone <- read.csv("E:/HOPT/PTDLR/DATA/Bone data.csv")  # chỉnh đường dẫn nếu cần

# 2. Kiểm tra tên và định dạng biến
str(dbone)
## 'data.frame':    2162 obs. of  9 variables:
##  $ id      : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ sex     : chr  "Male" "Female" "Male" "Female" ...
##  $ age     : int  73 68 68 62 61 76 63 64 76 64 ...
##  $ weight  : int  98 72 87 72 72 57 97 85 48 89 ...
##  $ height  : int  175 166 184 173 173 156 173 167 153 166 ...
##  $ prior.fx: int  0 0 0 0 0 0 0 0 0 0 ...
##  $ fnbmd   : num  1.08 0.97 1.01 0.84 0.81 0.74 1.01 0.86 0.65 0.98 ...
##  $ smoking : int  1 0 0 1 1 0 1 0 0 0 ...
##  $ fx      : int  0 0 0 0 0 0 0 0 0 0 ...
names(dbone)
## [1] "id"       "sex"      "age"      "weight"   "height"   "prior.fx" "fnbmd"   
## [8] "smoking"  "fx"
# 3. Kiểm tra phân bố biến smoking
table(dbone$smoking, useNA = "always")
## 
##    0    1 <NA> 
## 1243  919    0
# 4. Tạo biến phân loại từ biến smoking
# Nếu smoking là 0/1:
dbone$smoking <- factor(dbone$smoking, levels = c(0, 1),labels = c("Không hút", "Hút thuốc"))

# 5. Kiểm tra lại sau khi chuyển đổi
table(dbone$smoking)
## 
## Không hút Hút thuốc 
##      1243       919
# 6. Chuyển fx thành biến nhị phân dạng factor nếu chưa
dbone$fx <- factor(dbone$fx, levels = c(0, 1),labels = c("Không gãy", "Gãy"))

# 7. Xây dựng mô hình hồi quy logistic
model_logit <- glm(fx ~ smoking, data = dbone, family = binomial)

# 8. Xem kết quả
summary(model_logit)
## 
## Call:
## glm(formula = fx ~ smoking, family = binomial, data = dbone)
## 
## Coefficients:
##                  Estimate Std. Error z value Pr(>|z|)    
## (Intercept)      -1.03006    0.06442 -15.990   <2e-16 ***
## smokingHút thuốc -0.13796    0.10081  -1.368    0.171    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 2441.4  on 2161  degrees of freedom
## Residual deviance: 2439.5  on 2160  degrees of freedom
## AIC: 2443.5
## 
## Number of Fisher Scoring iterations: 4
# 9. (Tùy chọn) Hiển thị mô hình đẹp hơn bằng gói epiDisplay
# install.packages("epiDisplay")  # nếu chưa có
library(epiDisplay)
logistic.display(model_logit)
## 
## Logistic regression predicting fx : Gãy vs Không gãy 
##  
##                                 OR(95%CI)         P(Wald's test) P(LR-test)
## smoking: Hút thuốc vs Không hút 0.87 (0.71,1.06)  0.171          0.17      
##                                                                            
## Log-likelihood = -1219.7469
## No. of observations = 2162
## AIC value = 2443.4938
#Thực hiện mô hình hồi qui logistic đánh giá mối liên quan giữa hút thuốc và nguy cơ gãy xương
logistic_model <- glm(fx ~ smoking, data = dbone, family = binomial)

summary(logistic_model)
## 
## Call:
## glm(formula = fx ~ smoking, family = binomial, data = dbone)
## 
## Coefficients:
##                  Estimate Std. Error z value Pr(>|z|)    
## (Intercept)      -1.03006    0.06442 -15.990   <2e-16 ***
## smokingHút thuốc -0.13796    0.10081  -1.368    0.171    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 2441.4  on 2161  degrees of freedom
## Residual deviance: 2439.5  on 2160  degrees of freedom
## AIC: 2443.5
## 
## Number of Fisher Scoring iterations: 4
#Việc 3. Đánh giá mối liên quan độc lập giữa hút thuốc (smoking) và nguy cơ gãy xương (fx)sau khi hiệu chỉnh cho ảnh hưởng nhiễu của giới tính (sex)
#3.1 Thực hiện mô hình hối qui logistic đánh giá mối liên quan độc lập giữa hút thuốc và nguy cơ gãy xương
#Giới tính là yếu tố gây nhiễu
library(compareGroups)
createTable(compareGroups(sex ~ smoking + fx, data = dbone))
## 
## --------Summary descriptives table by 'sex'---------
## 
## _______________________________________________ 
##                 Female       Male     p.overall 
##                 N=1317       N=845              
## ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ 
## smoking:                               <0.001   
##     Không hút 923 (70.1%) 320 (37.9%)           
##     Hút thuốc 394 (29.9%) 525 (62.1%)           
## fx:                                    <0.001   
##     Không gãy 916 (69.6%) 701 (83.0%)           
##     Gãy       401 (30.4%) 144 (17.0%)           
## ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
#Hiệu chỉnh nhiễu
dbone$gender = ifelse(dbone$sex == "Male", 1, 0)
m.2 = glm(fx ~ smoking + gender, family = binomial, data = dbone)
logistic.display(m.2)
## 
## Logistic regression predicting fx : Gãy vs Không gãy 
##  
##                                 crude OR(95%CI)   adj. OR(95%CI)   
## smoking: Hút thuốc vs Không hút 0.87 (0.71,1.06)  1.1 (0.89,1.36)  
##                                                                    
## gender: 1 vs 0                  0.47 (0.38,0.58)  0.45 (0.36,0.57) 
##                                                                    
##                                 P(Wald's test) P(LR-test)
## smoking: Hút thuốc vs Không hút 0.357          0.358     
##                                                          
## gender: 1 vs 0                  < 0.001        < 0.001   
##                                                          
## Log-likelihood = -1194.7997
## No. of observations = 2162
## AIC value = 2395.5994
#Y văn ghi nhận giới tính (sex) là yếu tố gây nhiễu. Bạn thực hiện mô hinh hồi qui logistic đa biến đánh giá mối liên quan độc lập giữa hút thuốc và nguy cơ gãy xương

logistic_model_multivariate <- glm(fx ~ smoking + sex, data = dbone, family = binomial)

summary(logistic_model_multivariate)
## 
## Call:
## glm(formula = fx ~ smoking + sex, family = binomial, data = dbone)
## 
## Coefficients:
##                  Estimate Std. Error z value Pr(>|z|)    
## (Intercept)      -0.85598    0.06835 -12.523  < 2e-16 ***
## smokingHút thuốc  0.09872    0.10724   0.921    0.357    
## sexMale          -0.78880    0.11493  -6.863 6.73e-12 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 2441.4  on 2161  degrees of freedom
## Residual deviance: 2389.6  on 2159  degrees of freedom
## AIC: 2395.6
## 
## Number of Fisher Scoring iterations: 4
#Việc 4. Giả sử là mô hình dự báo nguy cơ gãy xương gồm tuổi, giới tính, mật độ xương ở cổ xương đùi và cân nặng. 
#4.1 Hãy đánh giá tầm quan trọng của các biến số dự báo trên.

#cài caret mục đích
# Huấn luyện mô hình dự báo Classification (phân loại) và Regression (hồi quy)
#Hỗ trợ hơn 200 mô hình Hỗ trợ từ glm, rpart, svm, rf, xgb, v.v.
# Tiền xử lý dữ liệu    Chuẩn hóa, xử lý NA, chuyển đổi biến, PCA
# Resampling tự động    Cross-validation, bootstrap, LOOCV
# So sánh mô hình   Tự động đánh giá độ chính xác các thuật toán

#install.packages("caret")
library(caret)
## Loading required package: ggplot2
## 
## Attaching package: 'ggplot2'
## The following object is masked from 'package:epiDisplay':
## 
##     alpha
## Loading required package: lattice
## 
## Attaching package: 'lattice'
## The following object is masked from 'package:epiDisplay':
## 
##     dotplot
## 
## Attaching package: 'caret'
## The following object is masked from 'package:survival':
## 
##     cluster
#xử lý nhiểu data
str(dbone$fx)
##  Factor w/ 2 levels "Không gãy","Gãy": 1 1 1 1 1 1 1 1 1 1 ...
table(dbone$fx)
## 
## Không gãy       Gãy 
##      1617       545
# Chuyển fx về kiểu nhị phân numeric

# Tạo lại biến nhị phân
dbone$fx_bin <- ifelse(dbone$fx == "Gãy", 1,
                       ifelse(dbone$fx == "Không gãy", 0, NA))


dbone$fx_bin <- as.numeric(as.character(dbone$fx))
## Warning: NAs introduced by coercion
dbone_clean <- na.omit(dbone[, c("fx_bin", "gender", "age", "fnbmd", "weight")])


table(dbone$fx_bin, useNA = "always")
## 
## <NA> 
## 2162
nrow(dbone_clean)  # Phải > 0
## [1] 0
colSums(is.na(dbone[, c("fx_bin", "gender", "age", "fnbmd", "weight")]))
## fx_bin gender    age  fnbmd weight 
##   2162      0      0     40      1
table(dbone$fx, useNA = "always")
## 
## Không gãy       Gãy      <NA> 
##      1617       545         0
str(dbone$fx)
##  Factor w/ 2 levels "Không gãy","Gãy": 1 1 1 1 1 1 1 1 1 1 ...
#fix all
# Đọc dữ liệu
# Với Windows:
dbone <- read.csv("E:\\HOPT\\PTDLR\\DATA\\Bone data.csv", fileEncoding = "UTF-8-BOM")


# Kiểm tra biến fx
table(dbone$fx, useNA = "always")
## 
##    0    1 <NA> 
## 1617  545    0
str(dbone$fx)
##  int [1:2162] 0 0 0 0 0 0 0 0 0 0 ...
dbone$gender <- ifelse(dbone$sex == "Male", 1, 0)

dbone_clean <- na.omit(dbone[, c("fx", "gender", "age", "fnbmd", "weight")])

m.rel <- glm(fx ~ gender + age + fnbmd + weight, family = binomial, data = dbone_clean)

summary(m.rel)
## 
## Call:
## glm(formula = fx ~ gender + age + fnbmd + weight, family = binomial, 
##     data = dbone_clean)
## 
## Coefficients:
##              Estimate Std. Error z value Pr(>|z|)    
## (Intercept)  0.806796   0.770234   1.047   0.2949    
## gender      -0.294860   0.128077  -2.302   0.0213 *  
## age          0.019647   0.007824   2.511   0.0120 *  
## fnbmd       -4.322857   0.495777  -8.719   <2e-16 ***
## weight       0.004078   0.004949   0.824   0.4100    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 2395.8  on 2120  degrees of freedom
## Residual deviance: 2203.3  on 2116  degrees of freedom
## AIC: 2213.3
## 
## Number of Fisher Scoring iterations: 4
library(caret)
m.rel = glm(fx ~ gender + age + fnbmd + weight, family = binomial, data = dbone)
varImp(m.rel, scale = FALSE)
##          Overall
## gender 2.3022178
## age    2.5112611
## fnbmd  8.7193666
## weight 0.8239425
#Việc 5. Xây dựng mô hình dự báo nguy cơ gãy xương
#5.1 Tìm mô hình dự báo nguy cơ gãy xương bằng phương pháp BMA
library(BMA)
## Loading required package: leaps
## Loading required package: robustbase
## 
## Attaching package: 'robustbase'
## The following object is masked from 'package:survival':
## 
##     heart
## Loading required package: inline
## Loading required package: rrcov
## Scalable Robust Estimators with High Breakdown Point (version 1.7-7)
dbone2 = na.omit(dbone)
xvars = dbone2[, c("sex", "age", "weight", "height", "fnbmd", "smoking", "prior.fx")]
yvar = dbone2[, c("fx")]

m.bma = bic.glm(xvars, yvar, strict = FALSE, OR = 20, glm.family = "binomial")
summary(m.bma)
## 
## Call:
## bic.glm.data.frame(x = xvars, y = yvar, glm.family = "binomial",     strict = FALSE, OR = 20)
## 
## 
##   4  models were selected
##  Best  4  models (cumulative posterior probability =  1 ): 
## 
##            p!=0    EV        SD        model 1     model 2     model 3   
## Intercept  100     2.249962  0.674258   2.509e+00   2.340e+00   1.140e+00
## sex         18.2  -0.048048  0.114551       .      -2.578e-01       .    
## age         16.2   0.002663  0.006838       .           .       1.602e-02
## weight       0.0   0.000000  0.000000       .           .           .    
## height       0.0   0.000000  0.000000       .           .           .    
## fnbmd      100.0  -4.487636  0.436674  -4.595e+00  -4.279e+00  -4.302e+00
## smoking      0.0   0.000000  0.000000       .           .           .    
## prior.fx   100.0   0.530729  0.134289   5.306e-01   5.445e-01   5.156e-01
##                                                                          
## nVar                                      2           3           3      
## BIC                                    -1.402e+04  -1.402e+04  -1.402e+04
## post prob                               0.696       0.142       0.122    
##            model 4   
## Intercept   7.978e-01
## sex        -2.851e-01
## age         1.780e-02
## weight          .    
## height          .    
## fnbmd      -3.918e+00
## smoking         .    
## prior.fx    5.296e-01
##                      
## nVar          4      
## BIC        -1.402e+04
## post prob   0.040
imageplot.bma(m.bma)

#5.2 Viết phương trình của mô hình dự báo 
install.packages("epiDisplay")  # chỉ cần 1 lần
## Warning: package 'epiDisplay' is in use and will not be installed
library(epiDisplay)

dbone2$fnbmd.sd = dbone2$fnbmd/0.15
m.3 = glm(fx ~ fnbmd.sd, family = binomial, data = dbone2)
logistic.display(m.3)
## 
## Logistic regression predicting fx 
##  
##                       OR(95%CI)         P(Wald's test) P(LR-test)
## fnbmd.sd (cont. var.) 0.49 (0.43,0.54)  < 0.001        < 0.001   
##                                                                  
## Log-likelihood = -1106.8757
## No. of observations = 2121
## AIC value = 2217.7514
#xây dựng mô hình tối ưu dự báo gãy xương từ những biến số như tuổi (age), giới tính (sex), cân nặng (weight), chiều cao (height), mật độ xương (fnbmd), hút thuốc là (smoking) và tiền căn gãy xương (prior.fx). Dùng phương pháp Bayesian Model Averaging từ gói lệnh BMA”
# Gọi thư viện nếu chưa
library(BMA)

# Mô hình BMA  
bma_model <- bic.glm(fx ~ age + sex + weight + height + fnbmd + smoking + prior.fx,
                     data = dbone,
                     glm.family = "binomial")

# Hiển thị kết quả
summary(bma_model)
## 
## Call:
## bic.glm.formula(f = fx ~ age + sex + weight + height + fnbmd +     smoking + prior.fx, data = dbone, glm.family = "binomial")
## 
## 
##   4  models were selected
##  Best  4  models (cumulative posterior probability =  1 ): 
## 
##            p!=0    EV        SD        model 1     model 2     model 3   
## Intercept  100     2.249962  0.674258   2.509e+00   2.340e+00   1.140e+00
## age         16.2   0.002663  0.006838       .           .       1.602e-02
## sexMale     18.2  -0.048048  0.114551       .      -2.578e-01       .    
## weight       0.0   0.000000  0.000000       .           .           .    
## height       0.0   0.000000  0.000000       .           .           .    
## fnbmd      100.0  -4.487636  0.436674  -4.595e+00  -4.279e+00  -4.302e+00
## smoking      0.0   0.000000  0.000000       .           .           .    
## prior.fx   100.0   0.530729  0.134289   5.306e-01   5.445e-01   5.156e-01
##                                                                          
## nVar                                      2           3           3      
## BIC                                    -1.402e+04  -1.402e+04  -1.402e+04
## post prob                               0.696       0.142       0.122    
##            model 4   
## Intercept   7.978e-01
## age         1.780e-02
## sexMale    -2.851e-01
## weight          .    
## height          .    
## fnbmd      -3.918e+00
## smoking         .    
## prior.fx    5.296e-01
##                      
## nVar          4      
## BIC        -1.402e+04
## post prob   0.040    
## 
##   41  observations deleted due to missingness.

Kết luận