AI/기초통계

[기초통계] 정규확률그림이란? 정규확률그림 그리는 방법/원리 (qqplot in R)

슈퍼짱짱 2019. 10. 8. 08:00
반응형

정규확률그림이란? What is Q-Q plot?


많은 경우에 통계적인 절차나 분석 등에서 모집단의 분포가 정규분포를 따른 다는 가정을 하고 있다. 그렇다면 표본을 추출했을 때 이러한 정규모집단의 가정을 조사하는 방법은 어떤 것이 있을까?


그 방법 중 하나가 바로 정규확률그림으로 확인하는 것이다.

정규점수그림(normal scores plot) 또는 정규확률그림(normal probability plot)이라 하는데 정규확률그림이라는 용어를 더 많이 쓴다. 

이 때, 정규점수(normal scores)란 표준정규분포(mean=0,sd=1)에서의 이상적인 표본을 말한다. 즉, 표준정규분포의 확률밀도함수를 등확률 구간으로 나누어 주는 경계값(z값)을 의미한다. 분위수를 생각해보면 쉽다. n분위수에 해당하는 z값을 구해주면 된다.

예를 들어, n=4일 때 각 점의 정규점수는 -0.84, -0.25, 0.25, 0.84 이다.


1
2
3
4
<- seq(-33, length=200)
plot(x, dnorm(x, mean=0, sd=1), type='l', xlab="", ylab="",xaxt="n",yaxt="n"
abline(v=qnorm(q,0,1), col="green")
axis(side=1,at=qnorm(q,0,1), labels=round(qnorm(q,0,1),2))
cs


> q <- (1:4)/5

> qnorm(q,0,1)

[1] -0.8416212 -0.2533471  0.2533471  0.8416212



분포를 알고자 하는 값들과 이 정규점수로 x축, y축으로 그려보았을 때, 그 값들이 정규분포를 따른다면 그림은 우상향하는 일직선의 형태를 띄게 된다.

즉, 정규분포인지 알고자 하는 값들이 정규분포를 따른다면, 이 값들을 정규분포로 근사했을 때 값들과 비슷한 양상을 띌 것이다.

이를 R에서 그려보면 다음과 같다.




R에서 정규확률 그림 그리는 방법 qqplot in R


R에서 정규확률그림은 qqnorm(), qqline(), qqplot() 으로 확인할 수 있다.

uniform 분포에서 임의로 x를 추출한 다음, 이 값들이 정규분포를 따르는지 확인해보겠다.

애초에 정규분포가 아닌 uniform 분포로 추출했기 때문에 결과는 당연히 따르지 않는다.


qqnorm(x)는 x의 정규점수를 return하며, 정규점수와 x값의 plot을 그려준다.

qqline(x)는 정규분포의 25%, 75% 점과, input x의 25%, 75%를 지나는 선을 그려준다. 즉, qqnorm(x)의 결과가 qqline(x)의 직선위에 있으면 정규분포를 따른다고 볼 수 있다.


1
2
3
x <- runif(20,min=0,max=100)
qqnorm(x)
qqline(x, col="green")
cs


> x

 [1]  1.347189 57.828226 94.062955 45.647394 59.228052 77.694957  7.988212 52.335207 47.435456

[10] 36.048707 95.276243 67.756599 44.205048 95.576409 94.002653 74.910064 29.497777 32.778766

[19]  7.526885 17.500935


> sort(x)

 [1]  1.347189  7.526885  7.988212 17.500935 29.497777 32.778766 36.048707 44.205048 45.647394

[10] 47.435456 52.335207 57.828226 59.228052 67.756599 74.910064 77.694957 94.002653 94.062955

[19] 95.276243 95.576409


> q <- qqnorm(x)

> q

$x

 [1] -1.95996398  0.18911843  1.15034938 -0.18911843  0.31863936  0.75541503 -1.15034938

 [8]  0.06270678 -0.06270678 -0.45376219  1.43953147  0.45376219 -0.31863936  1.95996398

[15]  0.93458929  0.59776013 -0.75541503 -0.59776013 -1.43953147 -0.93458929


$y

 [1]  1.347189 57.828226 94.062955 45.647394 59.228052 77.694957  7.988212 52.335207 47.435456

[10] 36.048707 95.276243 67.756599 44.205048 95.576409 94.002653 74.910064 29.497777 32.778766

[19]  7.526885 17.500935




R에서 qqnorm() qqline() 구현하기


정규확률그림을 그리는 순서는 다음과 같다.


* 정규확률그림 그리는 순서


1. 자료를 작은 것부터 크기순으로 나열한다.

2. 각 자료에 해당하는 점수를 계산한다.

3. i번째 순서의 자료와 i번째 순서의 정규점수를 하나의 쌍으로 2차원 공간 상에 나타낸다.


이에 따라, 위에 function들을 직접 구현해보면 다음과 같다.


1. qqnorm() 구현


1
2
3
4
5
6
7
8
qqnorm_fun <- function(x){
  x <- sort(x)
  # q <- qnorm((1:length(x))/length(x))
  q <- qnorm(((1:length(x))-(3/8))/(length(x)+(1/4)))
  plot(x=q,y=x, main = "정규확률그림")
  
  return(q)
}
cs


input으로 들어가는 x를 순서대로 sorting해주고, input 개수에 맞추어 정규점수를 계산한다. 

이 때, 주의할 점은 Z의 범위는 -inf ~ inf 이기 때문에 qnorm((1:length(x))/length(x)) 로 계산하면 Inf값이 return 된다.


> qnorm((1:length(x))/length(x))

 [1] -1.6448536 -1.2815516 -1.0364334 -0.8416212 -0.6744898 -0.5244005 -0.3853205 -0.2533471

 [9] -0.1256613  0.0000000  0.1256613  0.2533471  0.3853205  0.5244005  0.6744898  0.8416212

[17]  1.0364334  1.2815516  1.6448536        Inf


따라서 식을 약간 변경해주는데, 일반적으로 (x-(3/8))/(n+(1/4)) 로 변경해준다. 이 식은 조금씩 다를 수 있다.


> qnorm(((1:length(x))-(3/8))/(length(x)+(1/4)))

 [1] -1.86824165 -1.40341264 -1.12814365 -0.91913552 -0.74414274 -0.58945580 -0.44776752

 [8] -0.31457229 -0.18675612 -0.06193162  0.06193162  0.18675612  0.31457229  0.44776752

[15]  0.58945580  0.74414274  0.91913552  1.12814365  1.40341264  1.86824165



2. qqline() 구현


qqline(x)는 Q-Q plot의 Q1, Q3 을 이어주는 직선이다. 이를 구현하면 다음과 같다.


>> 사분위수란? 바로가기


1
2
3
4
5
6
7
8
9
qqline_fun <- function(x){
  x <- quantile(x, probs=c(0.25,0.75), names = FALSE,na.rm = TRUE)
  y <- qnorm(c(0.25,0.75))
  
  slope <- diff(x)/diff(y)
  int <- x[1L] - slope * y[1L]
  
  abline(int, slope, col="green")
}
cs




직접 구현한 그림과, 기존의 function으로 그린 그림을 비교하면 다음과 같다.


1
2
3
4
5
6
7
8
x <- runif(20,min=0,max=100)
par(mfrow=c(1,2))
 
qqnorm_fun(x)
qqline_fun(x)
 
qqnorm(x)
qqline(x, col="green")
cs



거의 비슷하다. 살짝 다른 이유는 정규점수 계산 식을 변경할 때 생기는 차이 때문인 것 같다.


위 그림은 포인트 수가 적어서 마치 정규분포인 것 처럼 보이지만, sampling 개수를 1000개로 하면 다음과 같이 정규분포를 따르지 않는 다는 것이 명확히 보인다.



반응형