[R데이터분석] 로지스틱 회귀분석

근이의 개발일기·2024년 12월 9일
post-thumbnail

library(survival)
data<-colon
View(data)
library(descr)
CrossTable(dataobstruct,dataobstruct,datastatus)
Cell Contents
|-------------------------|
| N |
| Chi-square contribution |
| N / Row Total |
| N / Col Total |
| N / Table Total |
|-------------------------|

======================================
datastatusdatastatus dataobstruct 0 1 Total

0 775 723 1498
0.465 0.474
0.517 0.483 0.806
0.826 0.786
0.417 0.389

1 163 197 360
1.933 1.971
0.453 0.547 0.194
0.174 0.214
0.088 0.106

Total 938 920 1858
0.505 0.495

775197/(723163)
[1] 1.295514

💡

교차표 (CrossTable) 해석

  • CrossTable(dataobstruct,dataobstruct, datastatus)를 통해 obstruct (장폐색 유무)status (생존 여부)의 교차표를 확인했습니다.
status = 0 (생존)status = 1 (사망)합계
obstruct = 07757231498
obstruct = 1163197360
합계9389201858

교차표 해석

  • obstruct = 0 (장폐색이 없는 경우)
    • 생존: 775명, 사망: 723명
    • 생존 비율: 775 / 1498 = 0.517
    • 사망 비율: 723 / 1498 = 0.483
  • obstruct = 1 (장폐색이 있는 경우)
    • 생존: 163명, 사망: 197명
    • 생존 비율: 163 / 360 = 0.453
    • 사망 비율: 197 / 360 = 0.547

행 비율과 열 비율

  • 행 비율: 같은 행에서의 비율로, 각 상황별 상태 비율을 확인하는 데 사용합니다.
    • 예: 장폐색이 없는 사람 중 51.7%는 생존, 48.3%는 사망.
  • 열 비율: 같은 열에서의 비율로, 각 상태별로 장폐색이 있는 경우와 없는 경우를 비교하는 데 사용합니다.
    • 예: 생존한 사람들 중 82.6%는 장폐색이 없고, 17.4%는 장폐색이 있습니다.

Odds Ratio (OR) 계산

OR의 정의

  • Odds Ratio (OR) = (a d) / (b c)
  • a = 775, b = 163, c = 723, d = 197

OR=(775⋅197)(723⋅163)=152675117849=1.295OR = \frac{(775 \cdot 197)}{(723 \cdot 163)} = \frac{152675}{117849} = 1.295

OR=(723⋅163)(775⋅197)=117849152675=1.295

OR 해석

  • OR = 1.295는 장폐색이 있는 집단의 사망 확률이 장폐색이 없는 집단의 사망 확률보다 1.295배 높다는 의미입니다.

exp(0.25891)
[1] 1.295517
coef(m)
(Intercept) obstruct
-0.06945381 0.25890733
exp(coef(m))
(Intercept) obstruct
0.9329032 1.2955138
round(exp(cbind(coef(m),confint(m))),3)
Waiting for profiling to be done...
2.5 % 97.5 %
(Intercept) 0.933 0.843 1.032
obstruct 1.296 1.029 1.633

💡

로지스틱 회귀분석

  • glm() 함수를 사용하여 로지스틱 회귀분석을 수행했습니다.
  • 모델 식:

log⁡(p1−p)=β0+β1⋅obstruct\log\left(\frac{p}{1-p}\right) = \beta_0 + \beta_1 \cdot \text{obstruct}

log(1−pp)=β0+β1⋅obstruct

  • p: 사망할 확률
  • β0: 절편
  • β1: 장폐색이 있는 경우에 대한 로그 오즈의 변화량

회귀분석 결과

(Intercept)    obstruct
-0.06945381   0.25890733
  • 절편(Intercept) = -0.069: obstruct=0(장폐색이 없는 경우)일 때, 사망에 대한 로그 오즈(log-odds)는 -0.069입니다.
  • obstruct = 0.2589: obstruct=1(장폐색이 있는 경우)일 때, 사망에 대한 로그 오즈는 0.2589만큼 증가합니다.

exp(coef(m))

(Intercept)    obstruct
  0.9329032    1.2955138
  • exp(Intercept) = 0.933: 장폐색이 없는 사람의 오즈(odds) 비율은 0.933입니다.
    • 이는 사망할 확률이 사망하지 않을 확률보다 낮다는 의미입니다.
  • exp(obstruct) = 1.295: 장폐색이 있는 경우의 오즈 비율은 1.295로, 장폐색이 없는 경우보다 1.295배 더 높은 사망 가능성을 가진다는 의미입니다.

95% 신뢰구간 해석

round(exp(cbind(coef(m), confint(m))), 3)
  • 이 코드는 회귀계수(coef)와 신뢰구간(confint)을 함께 보여줍니다.
  • 신뢰구간이 1을 포함하지 않으면 유의미하다고 판단합니다.
2.5 %     97.5 %
(Intercept) 0.933   0.843   1.032
obstruct    1.296   1.029   1.633

신뢰구간 해석

  • (Intercept): 신뢰구간 [0.843, 1.032]은 1을 포함하기 때문에, 유의하지 않음. 즉, 장폐색이 없는 사람의 사망 오즈(odds)는 유의미하지 않음.

  • obstruct: 신뢰구간 [1.029, 1.633]은 1을 포함하지 않음, 따라서 유의미한 결과임.
    - obstruct = 1일 때, 장폐색이 있는 사람은 장폐색이 없는 사람에 비해 사망 가능성이 1.029배에서 1.633배 더 높다고 볼 수 있습니다.

  • 장폐색이 없는 경우에 비해 장폐색이 있는 경우 사망 위험이 1.295배 높다.

  • *신뢰구간 [1.029, 1.633]1을 포함하지 않으므로 유의미**한 결과로 볼 수 있습니다.

  • OR 해석과 로지스틱 회귀 해석은 일치합니다.

  • 교차표와 로지스틱 회귀분석 모두 장폐색이 사망에 영향을 미친다는 증거를 제공합니다.


  • 다중 로지스틱 회귀분석

    data<-read.csv("HR_comma_sep.csv")
    head(data)
    satisfaction_level last_evaluation number_project average_montly_hours
    1 0.38 0.53 2 157
    2 0.80 0.86 5 262
    3 0.11 0.88 7 272
    4 0.72 0.87 5 223
    5 0.37 0.52 2 159
    6 0.41 0.50 2 153
    time_spend_company Work_accident left promotion_last_5years department salary
    1 3 0 1 0 sales low
    2 6 0 1 0 sales medium
    3 4 0 1 0 sales medium
    4 5 0 1 0 sales low
    5 3 0 1 0 sales low
    6 3 0 1 0 sales low
    View(data)

    summary(data)
    satisfaction_level last_evaluation number_project average_montly_hours
    Min. :0.0900 Min. :0.3600 Min. :2.000 Min. : 96.0

    1st Qu.:0.4400 1st Qu.:0.5600 1st Qu.:3.000 1st Qu.:156.0

    Median :0.6400 Median :0.7200 Median :4.000 Median :200.0

    Mean :0.6128 Mean :0.7161 Mean :3.803 Mean :201.1

    3rd Qu.:0.8200 3rd Qu.:0.8700 3rd Qu.:5.000 3rd Qu.:245.0

    Max. :1.0000 Max. :1.0000 Max. :7.000 Max. :310.0

    time_spend_company Work_accident left promotion_last_5years
    Min. : 2.000 Min. :0.0000 Min. :0.0000 Min. :0.00000

    1st Qu.: 3.000 1st Qu.:0.0000 1st Qu.:0.0000 1st Qu.:0.00000

    Median : 3.000 Median :0.0000 Median :0.0000 Median :0.00000

    Mean : 3.498 Mean :0.1446 Mean :0.2381 Mean :0.02127

    3rd Qu.: 4.000 3rd Qu.:0.0000 3rd Qu.:0.0000 3rd Qu.:0.00000

    Max. :10.000 Max. :1.0000 Max. :1.0000 Max. :1.00000

    department salary

    Length:14999 Length:14999

    Class :character Class :character

    Mode :character Mode :character

    table(data$department)

    accounting hr IT management marketing product_mng
    767 739 1227 630 858 902
    RandD sales support technical
    787 4140 2229 2720

    table(data$salary)

    high low medium
    1237 7316 6446

    💡

    데이터 불러오기 및 기본 확인

    • 데이터 불러오기: read.csv("HR_comma_sep.csv")
    • 데이터 확인: head(data)로 첫 6개의 행 확인, summary(data)로 각 변수의 기초 통계량을 확인.
    • 범주형 변수 빈도 확인: table(data$department)table(data$salary)로 범주형 변수를 확인.
      • satisfaction_level : 직무 만족도
      • last_evaluation : 마지막 평가점수
      • number_project : 진행 프로젝트 수
      • average_monthly_hours : 월평균 근무시간
      • time_spend_company : 근속년수
      • work_accident : 사건사고 여부(0: 없음, 1: 있음)
      • left : 이직 여부(0: 잔류, 1: 이직)
      • promotion_last_5years: 최근 5년간 승진여부(0: 승진 x, 1: 승진)
      • department : 부서
      • salary : 임금 수준

    해석

    • salary 변수의 범주는 low, medium, high로 구분됨.
    • department의 범주는 10개의 부서로 구성됨.
    • left 변수는 이직 여부로 0 또는 1로 구성되어 있음.

    m<-glm(left~salary, family="binomial",data=data)
    summary(m)

    Call:
    glm(formula = left ~ salary, family = "binomial", data = data)

    Coefficients:
    Estimate Std. Error z value Pr(>|z|)
    (Intercept) -2.6451 0.1143 -23.14 <2e-16
    salarylow 1.7830 0.1171 15.22 <2e-16

    salarymedium 1.2856 0.1184 10.86 <2e-16 ***

    Signif. codes: 0 ‘*’ 0.001 ‘’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

    (Dispersion parameter for binomial family taken to be 1)

    Null deviance: 16465 on 14998 degrees of freedom

    Residual deviance: 16030 on 14996 degrees of freedom
    AIC: 16036

    Number of Fisher Scoring iterations: 5

    round(exp(cbind(coef(m),confint(m))),3)
    Waiting for profiling to be done...
    2.5 % 97.5 %
    (Intercept) 0.071 0.056 0.088
    salarylow 5.947 4.759 7.536
    salarymedium 3.617 2.886 4.594
    HR<-data
    HRsalary2<relevel(factor(datasalary2<-relevel(factor(datasalary), 2)
    m<-glm(left~salary2, family="binomial",data=data)
    m<-glm(left~salary2, family="binomial",data=HR)
    summary(m)

    Call:
    glm(formula = left ~ salary2, family = "binomial", data = HR)

    Coefficients:
    Estimate Std. Error z value Pr(>|z|)
    (Intercept) -0.86218 0.02559 -33.69 <2e-16
    salary2high -1.78295 0.11711 -15.22 <2e-16

    salary2medium -0.49737 0.04011 -12.40 <2e-16 ***

    Signif. codes: 0 ‘*’ 0.001 ‘’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

    (Dispersion parameter for binomial family taken to be 1)

    Null deviance: 16465 on 14998 degrees of freedom

    Residual deviance: 16030 on 14996 degrees of freedom
    AIC: 16036

    Number of Fisher Scoring iterations: 5

    round(exp(cbind(coef(m),confint(m))),3)
    Waiting for profiling to be done...
    2.5 % 97.5 %
    (Intercept) 0.422 0.402 0.444
    salary2high 0.168 0.133 0.210
    salary2medium 0.608 0.562 0.658

    💡

    카테고리형 변수의 Reference Group

    • Reference Group: R의 회귀 분석에서는 범주형 변수의 가장 앞에 있는 수준이 자동으로 Reference Group으로 설정됨.
    • Reference 변경: relevel() 함수로 Reference Group을 변경할 수 있음.
    HR$salary2 <- relevel(factor(data$salary), 2) # 'medium'을 Reference Group으로 설정

    해석

    • Reference Group은 해석의 기준이 되는 그룹으로, 다른 수준들은 이 그룹에 비해 얼마나 증가하거나 감소하는지를 보여줌.
    • *relevel()을 통해 Reference Group을 변경**하여 해석을 더 직관적으로 할 수 있음.

    단일 변수 로지스틱 회귀분석

    1. 모델 생성

      m <- glm(left ~ salary, family = "binomial", data = data)
      summary(m)
    2. 회귀 결과 해석

      • 절편(Intercept) = -2.6451
      • salarylow = 1.7830
      • salarymedium = 1.2856

      해석

      • Intercept = -2.6451: salary = high일 때, 이직할 오즈(odds)는 exp(-2.6451) ≈ 0.071. 즉, 이직할 확률이 낮음.
      • salarylow = 1.7830: salary = low일 때, 이직할 오즈가 exp(1.7830) ≈ 5.947배 증가.
      • salarymedium = 1.2856: salary = medium일 때, 이직할 오즈가 exp(1.2856) ≈ 3.617배 증가.

    범주형 변수의 Reference 변경 후 회귀분석

    1. Reference 변경

      R
      코드 복사
      HR$salary2 <- relevel(factor(data$salary), 2) # Reference를 'medium'으로 설정
      m <- glm(left ~ salary2, family = "binomial", data = HR)
      summary(m)
      
    2. 회귀 결과 해석
      - 절편(Intercept) = -0.86218
      - salary2high = -1.78295
      - salary2medium = -0.49737

      **해석**
      
      - **Intercept = -0.86218**: `salary = medium`일 때, **이직할 오즈(odds)는 exp(-0.86218) ≈ 0.422**.
      - **salary2high = -1.78295**: `salary = high`일 때, 이직할 오즈가 **exp(-1.78295) ≈ 0.168**배로 감소.
      - **salary2medium = -0.49737**: `salary = medium`과 비교할 때, 이 값은 기준(reference) 그룹이므로 0으로 처리됨.

    HRdissatisfaction<1HRdissatisfaction <- 1-HRsatisfaction_level
    m<-glm(left~dissatisfaction + salary + time_spend_company, family="binomial",data=HR)
    step(m)
    Start: AIC=13607.36
    left ~ dissatisfaction + salary + time_spend_company

    Df Deviance AIC

    13597 13607

    time_spend_company 1 13811 13819

    salary 2 14039 14045

    dissatisfaction 1 15676 15684

    Call: glm(formula = left ~ dissatisfaction + salary + time_spend_company,
    family = "binomial", data = HR)

    Coefficients:
    (Intercept) dissatisfaction salaryhigh salarymedium

    -3.2432 3.7239 -1.9859 -0.5343

    time_spend_company

    0.2116

    Degrees of Freedom: 14998 Total (i.e. Null); 14994 Residual
    Null Deviance: 16460
    Residual Deviance: 13600 AIC: 13610

    summary(m)

    Call:
    glm(formula = left ~ dissatisfaction + salary + time_spend_company,
    family = "binomial", data = HR)

    Coefficients:
    Estimate Std. Error z value Pr(>|z|)
    (Intercept) -3.24316 0.07029 -46.14 <2e-16
    dissatisfaction 3.72386 0.08852 42.07 <2e-16

    salaryhigh -1.98592 0.12461 -15.94 <2e-16
    salarymedium -0.53427 0.04436 -12.04 <2e-16

    time_spend_company 0.21159 0.01418 14.92 <2e-16 ***

    Signif. codes: 0 ‘*’ 0.001 ‘’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

    (Dispersion parameter for binomial family taken to be 1)

    Null deviance: 16465 on 14998 degrees of freedom

    Residual deviance: 13597 on 14994 degrees of freedom
    AIC: 13607

    Number of Fisher Scoring iterations: 5

    round(exp(cbind(coef(m),confint(m))),3)
    Waiting for profiling to be done...
    2.5 % 97.5 %
    (Intercept) 0.039 0.034 0.045
    dissatisfaction 41.424 34.855 49.315
    salaryhigh 0.137 0.107 0.174
    salarymedium 0.586 0.537 0.639
    time_spend_company 1.236 1.202 1.270

    💡

    다중 회귀분석 (모형 비교)

    1. 모형 생성

      R
      코드 복사
      m1 <- glm(left ~ dissatisfaction + salary + time_spend_company, family = "binomial", data = HR)
      summary(m1)
      
    2. 회귀 결과 해석

      • 절편(Intercept) = -3.2432
      • dissatisfaction = 3.7239
      • salaryhigh = -1.9859
      • salarymedium = -0.5343
      • time_spend_company = 0.2116

      해석

      • Intercept = -3.2432: 모든 독립변수가 0일 때, 이직할 오즈는 exp(-3.2432) ≈ 0.039.
      • dissatisfaction = 3.7239: 불만족도가 1 단위 증가할 때, 이직할 오즈가 exp(3.7239) ≈ 41.424배 증가.
      • salaryhigh = -1.9859: salary = high일 때, 이직할 오즈가 exp(-1.9859) ≈ 0.137배 감소.
      • salarymedium = -0.5343: salary = medium일 때, 이직할 오즈가 exp(-0.5343) ≈ 0.586배 감소.
      • time_spend_company = 0.2116: 회사 근속 연수가 1년 증가할 때, 이직할 오즈가 exp(0.2116) ≈ 1.236배 증가.

    모형 선택 (Stepwise Selection)

    1. step() 함수 사용

      step(m1)
    2. 해석
      - step 함수는 AIC(정보기준, Akaike Information Criterion)를 기준으로 최적의 모형을 선택합니다.
      - AIC가 낮을수록 좋은 모델로 평가합니다.
      - dissatisfaction, salary, time_spend_company가 최종 모델로 선택되었습니다.


    모수절약의 원칙을 따르려면 모델을 여러개 세우고 비교해본다! → 해당 데이터에서는 이직에 영향을 미치는 데이터들로만 이루어져있기 때문에 모든 데이터가 left에 영향을 준다. → 최적 모델과 단순 모델의 비교

    m1<-glm(left~dissatisfaction + salary + time_spend_company, family="binomial",data=HR)
    m2<-glm(left~dissatisfaction, family="binomial",data=HR)
    library(lmtest)
    필요한 패키지를 로딩중입니다: zoo

    다음의 패키지를 부착합니다: ‘zoo’

    The following objects are masked from ‘package:base’:

    as.Date, as.Date.numeric
    lrtest(m1,m2)
    Likelihood ratio test

    Model 1: left ~ dissatisfaction + salary + time_spend_company
    Model 2: left ~ dissatisfaction
    #Df LogLik Df Chisq Pr(>Chisq)
    1 5 -6798.7
    2 2 -7098.9 -3 600.43 < 2.2e-16 ***

    Signif. codes: 0 ‘*’ 0.001 ‘’ 0.01 ‘*’ 0.05 ‘.’ 0.1

    summary(m2)

    Call:
    glm(formula = left ~ dissatisfaction, family = "binomial", data = HR)

    Coefficients:
    Estimate Std. Error z value Pr(>|z|)
    (Intercept) -2.85860 0.04735 -60.38 <2e-16
    dissatisfaction 3.83248 0.08720 43.95 <2e-16

    Signif. codes: 0 ‘*’ 0.001 ‘’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

    (Dispersion parameter for binomial family taken to be 1)

    Null deviance: 16465 on 14998 degrees of freedom

    Residual deviance: 14198 on 14997 degrees of freedom
    AIC: 14202

    Number of Fisher Scoring iterations: 4

    💡

    Likelihood Ratio Test (LR Test)

    1. 모형 생성

      m1 <- glm(left ~ dissatisfaction + salary + time_spend_company, family = "binomial", data = HR)
      m2 <- glm(left ~ dissatisfaction, family = "binomial", data = HR)
    2. LR Test 수행

      library(lmtest)
      lrtest(m1, m2)
    3. LR Test 결과

      Likelihood ratio test
      Model 1: left ~ dissatisfaction + salary + time_spend_company
      Model 2: left ~ dissatisfaction
      #Df LogLik  Df Chisq  Pr(>Chisq)
      1   5  -6798.7
      2   2  -7098.9 -3  600.43  < 2.2e-16 ***
    4. 해석
      - LR Test두 모델의 유의한 차이가 있는지를 검정합니다.
      - Chisq = 600.43, p < 2.2e-16로, 모형 1이 모형 2에 비해 유의미하게 더 적합하다고 판단할 수 있습니다.

    회귀분석의 해석

    • 절편(Intercept): 기준 그룹의 이직할 오즈를 해석합니다.
    • 카테고리형 변수의 해석: 더미 변수로 처리되며, 기준 그룹과 다른 수준 간의 오즈 비율을 해석합니다.
    • p-value: p-value < 0.05이면 독립변수가 종속변수에 유의미한 영향을 미친다고 해석합니다.
    • 오즈 비율 (Odds Ratio, OR): 회귀계수를 exp()로 변환하여 해석하며, 1보다 크면 증가, 1보다 작으면 감소로 해석합니다.

    0개의 댓글