본문 바로가기

R/R을 이용한 데이터 처리&분석 실무

표본 추출

반응형

현대의 데이터는 기하급수적으로 증가하고 있다. 예를 들어, 구글에서 사용자들이 검색하는 질의를 분석하는 경우를 생각해보자. 특정 알고리즘이 검색을 개선하는지를 알아보기 위해 사용자들이 입력한 모든 질의를 분석하는 것은 아무리 분산 컴퓨터 능력이 받쳐준다 할지라도 낭비에 가깝다. 그보다는 특정 기간에 있었던 질의만 분석한다거나, 특정 조건을 만족하는 질의만 분석하는 것이 효율적일 것이다. 이처럼 전체 데이터(모집단,Population) 중 일부를 표본(샘플, Sample)으로 추출하는 작업은 데이터 분석에서 필수다.

 

표본 추출(샘플링,Sampling)은 훈련 데이터(Training Data)와 테스트 데이터(Test Data)의 분리에서도 중요하다. 전체 데이터 중 80%를 훈련 데이터, 20%를 테스트 데이터로 분리한 뒤 데이터에 대한 모델링은 훈련 데이터로만 수행하고, 모델의 성능은 테스트 데이터로 평가하면 모델의 성능을 가장 적절히 평가할 수 있다. 데이터를 분리하지 않고 전체 데이터를 모델링과 모델 평가에 사용하게 되면 데이터에 내재하는 실제적 특징(Signal)외에 데이터에 우연히 포함된 노이즈(Noise)까지 반영한 모델을 만들게 될 위험이 있다. 이를 과적합이라고 하며, 과적합된 모델은 예측력이 떨어지므로 반드시 경제해야 할 대상이다.

 

이 절에서는 전체 데이터로부터 표본을 추출하는 방법으로 단순 임의 추출, 층화 임의 추출, 계통 추출에 대해 알아본다.

 

 

단순 임의 추출

단순 임의 추출(단순 무작위 추출, Simple Random Sampling)은 전체 데이터에서 각 데이터를 추출할 확률을 동일하게 하여 표본을 추출하는 방법이다. 예를 들어, 항아리에 빨간색 공 30개와 파란색 공 70개를 섞어놓은 뒤 항아리를 보지 않으면서 공 10개를 꺼내는 경우를 생각해 볼 수 있다. 이렇게 공을 꺼내면 각 공이 뽑힐 확률이 동일하므로 단순 입의 추출에 해당한다.

 

데이터를 추출하는 방법에는 복원 추출(Sampling with Replacement)과 비복원 추출(Sampling without Replacement)이 있다. 복원 추출은 복원 추출은 한 번 추출된 표본을 다시 선택하는 것이 가능한 경우를 뜻하며, 비복원 추출은 한 번 추출한 표본은 다시 선택할 수 없는 경우를 말한다. 항아리에서 공을 뽑을 때, 공을 하나 뽑아 그 색깔을 확인한 뒤 다시 항아리에 넣은 다음 공을 뽑는 것을 반복하는 경우가 복원 추출이다. 반면 공을 하나 뽑아 색깔을 확인한 뒤 그 공은 꺼내둔 채로 다른 공들을 항아리에서 계속 뽑는 경우가 비복원 추출이다.

 

단순 임의 추출은 sample()함수를 사용한다.

 

-sample : 표본 추출을 수행한다.

sample(

   x,        #표본을 뽑을 데이터 벡터. 만약 길이 1인 숫자 n이 지정되면 1:n에서 표본이 선택된다.

   size,    #표본의 크기

   replace=FALSE,    # 복원 추출 여부

   #데이터가 뽑힐 가중치. 예를 들어, x=c(1,2,3)에서 2개의 표본을 뽑되 각 표본이 뽑힐 확률을

   #50%, 20%, 30%로 하고자 한다면 size=2, prob=c(5,2,3)을 지정한다.

   #prob에 지정한 값의 합이 1일 필요는 없다.

   prob=NULL

)

 

1에서 10까지의 수에서 5개를 비복원 추출로 뽑아보자.

>sample(1:10,5)
[1] 4 5 6 10 9

 

1에서 10까지의 수에서 복원 추출로 5개의 표본을 뽑아보자. 복원 추출이므로 같은 값이 여러번 뽑힐 수 있다. 한 가지 예로 다음 결과를 보면 3이 두 번 뽑힌 것을 볼 수 있다.

>sample(1:10,5,replace=TRUE)
[1] 3 4 3 10 7

 

가중치를 고려한 표본 추출

각 데이터의 중요도나 발생 빈도가 다르다면 이를 고려하여 표본을 추출해야 한다. 예를 들어, 인터넷 쇼핑몰에서 제품과 제품별 판매량이 다음 표와 같이 정리되어 있다고 가정해보자.

제품명 팬매량
A 23,428
B 104
C 3,392,201
D 1,392,485
... ...
Y 3,007
Z 32,037

 

그리고 이들 중 5개 제품을 선택해서 판매 데이터를 분석하기를 원한다고 가정해보자. 어떤 제품들을 분석해야 할까?

 

이 문제에 단순 임의 추출을 적용하면 알파벳 A ~ Z 중 5개가 모두 같은 확률로 선택될 것이다. 그러나 이렇게 표본을 추출하면 우연히 판매량이 적은 데이터만 선택될 가능성이 있다. 또, 인터넷 쇼핑몰 운영자 입장에서도 판매량이 많은 제품에 가중치를 두어 분석해보고 싶을 것이다. 따라서 이런 경우에는 제품 5개를 선택할 때 판매량에 비례하여 표본을 추출해야 한다.

 

sample()에는 이런 경우를 위해 각 데이터가 뽑힐 가중치를 지정하는 prob 파라미터가 있다. prob라는 이름은 확률을 의미하지만 실제로 이 인자에 확률을 지정할 필요는 없다. 다만 가중치에 비례하는 음이 아닌 값을 지정하면 된다.

예를 들어, 1에서 10까지의 수에 각각 1에서 10까지 가중치를 주어 복원 추출을 해보자. 다음 코드를 보면 가중치가 큰 표본이 더 많이 뽑히는 경향을 쉽게 확인할 수 있다.

 

>sample(1:10, 5, replace=TRUE, prob=1:10)
[1]10 9 6 7 7

 

층화 임의 추출

데이터가 중첩 없이 분할될 수 있는 경우(즉, 서로 교집합이 없는 집합들로 나뉠 수 있는 경우) 그리고 각 분할의 성격이 명확히 다른 경우 층화 임의 추출(Stratified Random Sampling)을 수행하여 더 정확한 분석 결과를 얻을 수 있다.

 

예를 들어, 남성 20%, 여성 80%로 구성된 집단이 있을 때 이 집단의 일부를 표본으로 뽑아 키를 측정한 뒤 전체 집단의 평균 키를 예상한다고 가정해보자. 성별에 따라 키의 차이가 존재할 것이므로, 성별을 고려하여 표본을 추출하는 것이 중요할 것이다. 그런데 단순 임의 추출을 이 데이터에 적용하게 되면 전체 데이터로부터 각 데이터를 같은 확률로 뽑는다. 그 결과 남성이 우엲히 20%보다 많이 추출되거나 적게 추출될 수 있다. 이렇게 뽑힌 표본에서 평균 키를 계산하게 되면 평균 키가 집단의 실제 평균보다 우연히 작거나 크게 추정될 위험이 있다.

 

이 데이터의 경우 남성 데이터와 여성 데이터를 떼놓고 각각으로부터 표본을  추출함으로써 남성과 여성의 표본 비율을 20%:80%로 유지할 수 있다. 이를 층화 임의 추출이라 하며 데이터를 남성, 여성으로 분할한 것을 '층'이라고 부른다.

 

층화 임의 추출을 하게 되면 뽑힌 남성의 표본을 사용해 남성 키의 평균을 추정할 수 있고, 여성 표본을 사용해 여성 키의 평균을 추정할 수있다는 장점이 있다. 다시 말해 전체 평균뿐만 아니라 층별(성별) 평균 키의 추정이 가능해진다. 더 자세한 설명은 참고자료 [4]를 참고하기 바란다.

 

층화 임의 추출은 sampling::strata() 함수를 사용한다.

 

-sampling::strata : 주어진 데이터에 대해 층화 임의 추출을 수행한다.

sampling::strata(

   data,                               #데이터 프레임 또는 행렬

   stratanames=NULL,            #층화 추출에 사용할 변수들

   size,                               #각 층의 크기

   #method는 데이터를 추출하는 방법으로, 다음 4가지 중 하나로 지정한다.

   # - srswor : 비복원 단순 임의 추출

   # - srswr  :  복원 단순 임의 추출

   # - poisson : 포아송 추출

   # - systematic : 계통 추출

   method=c("srswor",

                 "srswr",

                 "poisson",

                 "systematic"),

   pik,                #각 데이터를 표본에 포함할 확률

   description=FALSE  # TRUE면 표본의 크기와 모집단의 크기를 출력한다.

)

 

-sampling::getdata : 표본 추출을 수행한 뒤 데이터 프레임으로부터 값을 추출한다.

sampling::getdata(

   data,

   m      #선택된 유닛에 대한 벡터 또는 표본 데이터 프레임

)

 

다음은 iris 데이터로부터 비복원 단순 임의 추출을 사용해 각 종별로 3개씩 표본을 추출하는 예다.

>install.packages("sampling")
>library(sampling)
>(x<-strata(c("Species"), size=c(3, 3, 3), method="srswor", data=iris))
       Species     ID_unit    Prob    Stratum
4       setosa       4          0.06       1
15      setosa      15         0.06       1
36      setosa      36         0.06       1
73  versicolor      73         0.06       2
78  versicolor      78         0.06       2
85  versicolor      85         0.06       2
104  virginica     104        0.06       3
138  virginica     138        0.06       3
141  virginica     141        0.06       3

>getdata(iris, x)
    Sepal.Length Sepal.Width Petal.Length Petal.Width    Species    ID_unit Prob Stratum
4           4.6          3.1          1.5                 0.2          setosa       4     0.06       1
15          5.8          4.0          1.2                0.2          setosa      15     0.06       1
36          5.0          3.2          1.2                0.2          setosa      36     0.06       1
73          6.3          2.5          4.9                1.5      versicolor      73     0.06       2
78          6.7          3.0          5.0                1.7      versicolor      78     0.06       2
85          5.4          3.0          4.5                1.5      versicolor      85     0.06       2
104         6.3          2.9          5.6               1.8       virginica     104     0.06       3
138         6.4          3.1          5.5               1.8       virginica     138     0.06       3
141         6.7          3.1          5.6               2.4       virginica     141     0.06       3

 

strata() 함수가 편리한 점은 층별로 다른 수의 표본을 추출할 수 있다는 점이다. 다음 예에서는 setosa 종에서 3개의 표본을 추출하고, 나머지 종에서는 1개씩 표본을 추출한다.

>strata(c("Species"), size=c(3, 1, 1), method="srswr", data=iris)
       Species      ID_unit   Prob   Stratum
5       setosa         5        0.06       1
38      setosa        38       0.06       1
46      setosa        46       0.06       1
89  versicolor        89       0.02       2
116  virginica       116      0.02       3

 

또, strata()는 다수의 층을 기준으로 데이터를 추출할 수 있다. 다음은 iris에 Species2라는 이름으로 또 다른 층을 만들고, (Species, Species2)의 각 층마다 1개씩 표본을 추출하는 예다.

>iris$Species2 <- rep(1:2, 75)               # 1, 2, 1, 2, ..., 1, 2
>strata(c("Species", "Species2"), size=c(1, 1, 1, 1, 1, 1), method="srswr", data=iris)
       Species    Species2 ID_unit    Prob   Stratum
49      setosa        1      49         0.04       1
26      setosa        2      26         0.04       2
59  versicolor        1      59         0.04       3
60  versicolor        2      60         0.04       4
127  virginica        1     127         0.04       5
114  virginica        2     114         0.04       6

 

각 층마다 동일한 개수의 표본을 추출하고자 한다면 doBy::sampleBy()를 사용할 수 있다. 이 함수는 책의 "sampleBy()" 절에서 설명했다.

 

 

계통 추출

아침부터 밤까지 특정한 지역을 지나간 차량의 번호를 모두 조사한 뒤 이들로부터 조사 대상을 뽑는 경우를 가정해보자. 가장 간단한 단순 임의 추출을 적용하여 차량 번호를 뽑는다면 우연히 아침 시간에 지나간 차량을 더 많이 뽑거나, 저녁 시간에 지나간 차량을 더 많이 뽑는 편향bias이 발생할 수 있다. 계통 추출(Systematic Sampling)은 이런 상황에서 해결책이 될 수 있다.

 

계통 추출은 모집단의 임의 위치에서 시작해 매 k번째 항목을 표본으로 추출하는 방법이다. 예를 들어, 1, 2, 3, …, 10의 수에서 3개의 표본을 뽑는다고 가정해보자. 10 / 3 = 3.33333…이므로 k = 3으로 놓는다. 표본 추출 시작 위치를 잡기 위해 1 ~ k 사이의 수 하나를 뽑는다. 이 수가 2라 하자. 나머지 두 수를 뽑기 위해 2 + k에 해당하는 5를 뽑는다. 다음, 5 + k에 해당하는 8을 뽑는다. 그러면 최종적으로 표본 2, 5, 8을 얻는다.

매우 단순한 방법이지만 데이터가 임의로 분포된 경우에는 단순 임의 추출 방법과 동일한 효과를 보이고, 데이터가 순서대로 나열된 순서 모집단Ordered Population(예를 들면, 1, 2, 3, …, 10과 같이 순서대로 나열된 모집단)의 경우 단순 임의 추출보다 좋은 표본을 추출한다. 5 하지만 데이터에 일종의 주기성이 존재한다면(예를 들면, 데이터가 1, 2, 3, 1, 2, 3, …과 같이 주기적으로 반복되는 경우) 편향된 추정값6 을 얻게 된다. 이에 대한 자세한 분석은 참고자료 [4]를 보기 바란다.

 

계통 추출은 doBy 패키지의 sampleBy(formula, frac=0.1, replace=FALSE, data=parent.frame(), systematic=FALSE) 함수를 사용하여 수행할 수 있다(‘4.5.3 sampleBy( )’ 절 참고). 계통 추출을 하려면 systematic 인자에 TRUE를 지정한다.

다음 예는 1:10을 저장한 데이터 프레임에서 3개의 표본을 계통 추출로 뽑는 예다. 코드에서 sampleBy()의 첫 번째 인자는 ‘~ 1’이다. 그 이유는 첫 번째 인자가 표본을 추출할 그룹을 지정하는 포뮬러기 때문이다. 만약 그룹별로 데이터를 뽑는 층화 임의 추출이라면 그룹을 뜻하는 표현을 적어야 하지만, 여기서는 그룹의 구분이 없으므로 상수 1을 사용했다. 실행 결과 ‘1, 4, 7’ 3개의 표본이 뽑혔다.

 

>(x<-data.frame(x=1:10))
    x
1   1
2   2
3   3
4   4
5   5
6   6
7   7
8   8
9   9
10 10

>sampleBy(~1, frac=.3, data=x, systematic=TRUE)
    [,1]  [,2]  [,3]
1    1    4    7

 

 

R을 이용한 데이터 처리&분석 실무 中

반응형

'R > R을 이용한 데이터 처리&분석 실무' 카테고리의 다른 글

상관 분석  (0) 2020.02.06
분할표  (0) 2020.02.05
기초 통계량  (0) 2020.02.04
난수 생성 및 분포 함수  (0) 2020.02.04
코드 수행 시간 측정  (0) 2020.02.03