본문 바로가기

■ 프로그래밍/R

[R] One Sample Test (단일 표본 검정)

[ R : One Sample Test (단일 표본 검정) ]


패키지 설치 및 로딩하기

install.packages("readxl")
library(readxl)


사용 데이터:  body.xlsx


One Sample Test란?

  • one sample test는 언제 하는가?
    A. 하나의 모집단의 평균이 이전보다 커졌는지/작아졌는지/달라졌는지를 통계적으로 분석할 때 사용

  • 자료: 양적 자료 1개

our.body <- readxl::read_excel(path      = "body.xlsx",
                               sheet     = 1,
                               col_names = TRUE)
head(our.body)
## # A tibble: 6 x 4
##      id height weight    iq
##   <dbl>  <dbl>  <dbl> <dbl>
## 1     1    174     73   120
## 2     2    165     50   140
## 3     3    168     50   150
## 4     4    169     50   140
## 5     5    180     70   180
## 6     6    160     48   136

방법

  1. One sample t-test
  • Parametric Method(모수적 방법)
  • 일표본 t검정
  • 모집단의 분포가 정규분포라는 가정이 될 때

  1. Willcoxon’s signed rank test
  • Non-parametric Method(비모수적 방법)
  • 윌콕슨의 부호 순위 검정
  • 모집단의 분포가 정규분포라는 가정이 안 될 때


정규성 검정(정규분포 가정)이 왜 필요한가?
일반적으로 모집단은 데이터의 양이 많기 때문에 골고루 분포된 데이터(정규분포)를 띄운다.
따라서, 이러한 모집단에서 추출한 (표본)데이터가 30개 이상인 경우 중심극한정리에 의해 정규성이 만족 된다는 하에 진행된다.
즉, 데이터가 골고루 추출되어 집단 간의 차이를 밝혀낼 수 있다는 뜻이다.


그러나, 표본 데이터가 30 이하인 경우 먼저 ’정규성 검정’을 수행해야 한다.
왜냐하면 데이터가 어느 한 쪽으로 치우쳐져 있을 수 있기 때문이다.
이 외에도, ’모집단에 대해 아예 모를 경우’에도 정규성 검정을 통해 올바른 가설검정 방법을 채택해야 한다.


가설검정

  • 귀무가설: 성인들의 평균 키는 168cm이다.
  • 대립가설: 성인들의 평균 키는 168cm보다 크다.


보통 귀무가설은 증명하기 힘든 것을 쓴다. 예로, “비둘기는 모두 회색이다.”를 증명하기 위해서는 세상의 모든 비둘기를 다 하나하나 찾아봐야 한다.
반면, “비둘기는 모두 회색이 아니다.”를 증명하려면 회색이 아닌 비둘기 한 마리만 찾아도 된다. 따라서, 증명하기 더 쉬운 것을 보통 대립가설에 두는 편이다.


1단계: 정규성 검정(Normality test)
- 귀무가설: 성인들의 키는 정규분포를 따른다.
- 대립가설: 성인들의 키는 정규분포를 따르지 않는다.

  • Shapiro-Wilk’s 정규성 검정: 데이터가 5,000개 미만일 때 사용
shapiro.test(our.body$height)
## 
##  Shapiro-Wilk normality test
## 
## data:  our.body$height
## W = 0.92802, p-value = 0.1415

결론: 유의확률이 0.142로, 유의수준 0.05에서 귀무가설을 채택한다. 즉 정규성 가정을 만족.


2단계: 일표본 t검정(One sample t-test)

t.test(our.body$height,
       mu          = 168,        # 귀무가설이 참일 때의 모평균
       alternative = "greater")  # 대립가설보다 greater(크다), less(작다), two.sided(같지 않다)
## 
##  One Sample t-test
## 
## data:  our.body$height
## t = 1.2498, df = 19, p-value = 0.1133
## alternative hypothesis: true mean is greater than 168
## 95 percent confidence interval:
##  166.9262      Inf
## sample estimates:
## mean of x 
##     170.8
sd(our.body$height) #표본의 표준편차
## [1] 10.01893

결론: 유의확률이 0.113으로, 유의수준 0.05에서 귀무가설을 채택한다. 즉, 성인들의 평균 키는 168cm이다.


2단계: (만약에 1단계의 정규성 가정이 깨졌다면,) 윌콕슨의 부호 순위 검정(Wilcoxon’s signed rank test)

wilcox.test(our.body$height,
            mu          = 168,        # 귀무가설이 참일 때의 모평균
            alternative = "greater")  # 대립가설보다 greater(크다), less(작다), two.sided(같지 않다)


실습
첨부 된 ’body.xlsx’로 “[가설 2] weight의 평균이 65보다 적다”와 “[가설 3] IQ의 평균은 100이 아니다”를 혼자 연습해보자.



한 번에 가설검정 코드 만들기

단계별 코드 이해

  • 1단계(정규성 검정) 저장하기
height.normal <- shapiro.test(our.body$height)  # List형태로 나타남
height.normal$statistic # W 검정통계량 ## 0.9280244
height.normal$p.value   # 유의확률     ## 0.1414645
  • 1단계의 p값에 따라, 2단계 자동 실행
if(height.normal$p.value >= 0.05){
  t.test(our.body$height,
         mu = 168,
         alternative = "greater")
}else{
  wilcox.test(our.bocy$height,
              mu = 168,
              alternative = "greater")
}
## 
##  One Sample t-test
## 
## data:  our.body$height
## t = 1.2498, df = 19, p-value = 0.1133
## alternative hypothesis: true mean is greater than 168
## 95 percent confidence interval:
##  166.9262      Inf
## sample estimates:
## mean of x 
##     170.8

결과가 1단계에서 정규성 검정이 만족(유의확률이 0.14)되어 자동으로 One Sample T-test가 채택된 것을 볼 수 있다.


한 번에 1단계, 2단계 수행

height.normal <- shapiro.test(our.body$height)
Test.Statistics <- c()           # if문 안의 내용을 저장하게 위해 빈 vector 생성
PValue <- c()                    # Test.Statistic에는 1단계 test의 결과 값, PValue는 유의확률 저장

if(height.normal$p.value >= 0.05){
  print("# One Sample t-test #")
  result <- t.test(our.body$height,
         mu = 168,
         alternative = "greater")
  Test.Statistics <- result$statistic
  PValue <- result$p.value
}else{
  print("# Wilcoxon's signed rank test #")
  result <- wilcox.test(our.bocy$height,
              mu = 168,
              alternative = "greater")
  Test.Statistics <- result$statistic
  PValue <- result$p.value
}



실습
첨부 된 ’body.xlsx’로 “[가설 2] weight의 평균이 65보다 적다”와 “[가설 3] IQ의 평균은 100이 아니다”로 각각 코드 연습을 해보자.


[가설 1, 2, 3] 한 번에 실행하고 pdf로 저장하기

직접 실습해 보기를 권장한다.

T.method      <- c() #비어 있는 벡터 만들기, 만약 for문 안에 바로 저장하면 제일 마지막 결과만 추출
T.statistic   <- c()
T.pvalue      <- c()
T.mu          <- c(168, 65, 100)
T.alternative <- c("greater", "less", "two.sided")

for(i in 2:4){
  norm.test <- shapiro.test(unlist(our.body[ , i])) 
  # data.frame이라 행렬구조로 인식하기 때문에 unlist로 벡터화 시켜 인덱스 가능하게 만듦
  
  if(norm.test$p.value >= 0.05){
    t.test.result <- t.test(unlist(our.body[ , i]),
                            mu = T.mu[i-1], # i가 2부터 시작하니까 i-1해줘야 1부터 시작
                            alternative = T.alternative[i-1])
    T.method    <- c(T.method, t.test.result$method)        # 어떤 방법을 취했는지
    T.statistic <- c(T.statistic, t.test.result$statistic)
    T.pvalue    <- c(T.pvalue, t.test.result$p.value)
  }else{
    wilcox.test.result <- wilcox.test(unlist(our.body[ , i]),
                                      mu = T.mu[i-1],
                                      alternative = T.alternative[i-1])
    T.method    <- c(T.method, wilcox.test.result$method)
    T.statistic <- c(T.statistic, wilcox.test.result$statistic)
    T.pvalue    <- c(T.pvalue, wilcox.test.result$p.value)
  }
}

resultDF <- data.frame(Variable  = colnames(our.body)[2:4],  # 변수명
                       Method    = T.method,
                       Statistic = T.statistic,
                       PValue    = T.pvalue)

writexl::write_xlsx(resultDF,
                    path = "OneSampleTest.xlsx")


윌콕슨의 tie warning 해결 - exactRankTests::wilcox.exact(data$variable)

exactRankTests::wilcox.exact(our.body$weight, 
                             mu = 65,
                             alternative = "less")