본문 바로가기

데이터 기본

데이터 샘플링: 통계적 및 비통계적 샘플링 방법

출처: Unsplash

 

데이터 샘플링(표본추출)은 많은 양의 데이터를 대상으로 분석 작업 수행 시, 전체 데이터가 아닌 일부를 ‘샘플(표본)’로 선택하여 전체 데이터를 대표하게 하는 작업이다. 이 샘플링은 처리할 데이터의 양이 많을 때 반드시 필요한 중요한 단계이다.

 샘플링은 통계에서 나온 개념이다. 사실 통계가 나온 중학교 2학년 때부터 수학이 싫어졌던 경험이 있는 사람으로서, 자세한 내용은 별로 관심이 없다. 하지만 자세한 내용을 모른다고 분석 업무를 못하는 건 아니니, 이런 게 있다고 아는 정도로 이해하고 넘어가자.

데이터 샘플링 방법은 크게 통계적 기법을 기반으로 한 샘플링과, 비통계적 기법을 기반으로 한 샘플링이 있다.

 

샘플링 종류 방법 장점 단점 데이터 분석에서의 사용빈도
통계적 단순 랜덤 모집단에서 무작위 추출 편향이 없는 샘플 모집단 데이터의 전체 리스트가 필요함
계통 특정 간격으로 추출 모집단과 동등한 대표성 제공 모집단 데이터의 전체 리스트가 필요하며, 데이터에 주기성이 있는 경우 편향된 결과 초래
유층 동일한 특성을 가진 하위 그룹(strata)으로 나눈 후에 추출 단순 랜덤에 비해 모집단의 대표성을 더 정확하게 반영 모집단에 대한 기본적 이해가 선행되어야 하며, 시간이 많이 소요됨
클러스터 주로 지리적 특성 등으로 클러스터를 구분한 후에 추출 추출된 샘플의 에러가 적고, 클러스터들에 대한 대표성이 높음 높은 분산도 및 편향 발생 가능
다단계 여러 방법들을 조합하여 더 세분화 한후 추출 다른 방법에 비해 비용과 시간 절약 가능 높은 분산도 및 편향이 발생 가능하며, 기획하는데 많은 시간 소요
비통계적 편의 선택하기 쉬운 샘플 추출 쉽고, 빠르고 저렴함 편향과 낮은 대표성 초래
할당 모집단 내 특성별 비율에 따라 샘플을 맞춰서 추출 편의법 보다는 대표성이 높을 수 있음 여전히 대표성이 낮고 편향되어 있을 가능성
스노우볼 최초 샘플로부터 연관성 또는 소개를 통해 다음 샘플로 확장 샘플 접근 자체가 어려운 전문 분야에 유용 최초 샘플 선택에 따라 편향 및 대표성이 좌지우지됨

 

1. 통계적 샘플링 방법

통계적 샘플링에서는 모집단에 있는 모든 데이터들을 0이 아닌 특정한 확률을 가지고 무작위로 선택한다. 즉, 특정한 확률을 사용해서 샘플을 뽑아낸다는 말이다. 통계적 샘플링에는 다음과 같은 방법들이 있다.

  • 단순 랜덤(단순임의, 단순무선, 단순 무작위) 샘플링 (Simple Random Sampling)
  • 계통 샘플링 (Systematic Sampling)
  • 유층(층별/계층/층화) 샘플링 (Stratified Sampling)
  • 클러스터(군집) 샘플링 (Cluster Sampling)
  • 다단계 샘플링 (Multistage Sampling)

1.1 단순 랜덤 샘플링 (Simple Random Sampling)

단순 랜덤 샘플링은 모집단의 크기를 N이라고 할 때, 크기가 n인 모든 가능한 샘플을 동일한 가능성을 갖고 추출하는 방법이다. 말이 어렵지만, 그냥 10개짜리 데이터가 존재하는 모집단에서 3개를 고른다고 하면, 그냥 임의로 3개를 골라 샘플로 삼겠다는 말이다.

보통 프로그래밍 언어별로 주어진 간단한 함수를 통해 n개의 난수를 랜덤으로 고르는 방식이며, 데이터를 빠르고 직접적으로 표현하려는 경우에 유용하게 사용된다. 가장 원시적인 샘플링 방법이기도 하다.

R

# 단순 랜덤 샘플링 예시
#install.packages("tidyverse")
library(tidyverse)
store_data <- read.csv("stores.csv")

# store_data에서 임의로 100개의 샘플을 추출
simple_random_sample <- store_data %>%
  sample_n(100)

Python

# 단순 랜덤 샘플링 예시
import pandas as pd
import numpy as np

store_data = pd.read_csv("stores.csv")

# store_data에서 임의로 100개의 샘플을 추출
simple_random_sample = store_data.sample(n=100)

 

1.2 계통 샘플링 (Systematic Sampling)

계통 샘플링은 계통 추출법, 체계적 표집 등으로도 불리운다. 단순 랜덤 샘플링처럼 임의로 추출하긴 하나, 한 가지 조건이 추가된다. 즉, 처음 하나의 샘플을 임의로 고르고 난 다음에 일정한 간격으로 다음 샘플들을 고른다. 따라서 계통 샘플링을 할 때는 간격(Interval)을 반드시 지정해 줘야 한다. 단, 데이터가 일정한 주기성을 가지고 있는 경우에는 주기를 고려하여 샘플링 간격을 설정해 줘야 하는데, 그렇지 않으면 왜곡(bias)된 샘플을 얻게 될 수도 있다.

R

# 계통 샘플링 예시 (R)
#install.packages("tidyverse")
library(tidyverse)
student_data <- read.csv("student_data.csv")

# 첫번째 학생부터 매 10번째 학생들을 샘플로 선택
systematic_sample <- student_data %>%
  slice(seq(1, nrow(student_data), by = 10))

Python

# 계통 샘플링 예시 (Python)
import pandas as pd

student_data = pd.read_csv("student_data.csv")

# 첫번째 학생부터 매 10번째 학생들을 샘플로 선택
systematic_sample = student_data.iloc[::10, :]

 

1.3 유층 샘플링 (Stratified Sampling)

유층, 계층, 계층화, 층별 샘플링이라고도 한다. 모집단 안에 유사한 속성을 갖는 그룹들 (하위 집단)이 있다고 가정할 때, 모집단을 속성에 따라 계층으로 구분하고 각 계층(Strata)에서 단순 랜던 샘플링을 하는 방법이다. 즉, 하위 집단이 있다는 차이를 제외하고는 단순 랜덤 샘플링과 기본적으로는 같다.

유층 샘플링을 위한 하위 그룹은 특정한 특성을 고려하여 이루어지는데, 연령별 계층을 나누는 것(10대, 20대, 30대, 40대 등), 성별, 수입(연 소득 3천만원 이하, 3~4천만원, 4~5천만원, 5~6천만원, 6천만원 이상 등) 등이 그 예이다. 샘플링은 보통 실질적인 분석이 이루어지기 전에 이루어지므로, 모집단이 어떤 특성으로 구분되어야 의미가 있는지에 대한 해당 분야의 지식(Domain Knowledge)이 있어야 한다.

R

# 유층 샘플링 예시(R)
#install.packages("dplyr")
library(dplyr)

# 예시를 위한 데이터 세트 생성
set.seed(123)
dataset <- data.frame(age = sample(18:70, 100, replace = T), 
                      salary = sample(35000:180000, 100, replace = T), 
                      group = sample(c("A", "B", "C"), 100, replace = T, prob = c(0.3, 0.4, 0.3)))

# 'sample_frac()' 함수를 사용한 그룹별 유층 샘플링
strata_sample <- dataset %>% 
  group_by(group) %>% 
  sample_frac(size = 0.5) %>% 
  ungroup()

# 샘플의 분포 확인
table(strata_sample$group)

Python

# 유층 샘플링 예시(python)
import numpy as np
import pandas as pd
from sklearn.model_selection import StratifiedShuffleSplit

# 데이터 세트 입력
df = pd.read_csv('population.csv')

# y를 target variable로, x를 feature로 지정
y = df['target']
X = df.drop('target', axis=1)

# 'StratifiedShuffleSplit'를 생성하여 Training과 testing set을 구분하기 위한 준비
sss = StratifiedShuffleSplit(n_splits=1, test_size=0.2, random_state=0)

# 'sss'를 사용하여 training 과 testing set으로 나눠 줌
for train_index, test_index in sss.split(X, y):
    X_train, X_test = X.iloc[train_index], X.iloc[test_index]
    y_train, y_test = y.iloc[train_index], y.iloc[test_index]

 

1.4 클러스터(군집) 샘플링 (Cluster Sampling)

클러스터(군집) 샘플은 전체 모집단을 여러 클러스터(군집)으로 나눈 다음 일부 군집을 무작위로 선택하고, 그 군집에서 다시 일부를 무작위로 선택하는 방법이다. 이 샘플링 방법은 시간이 너무 많이 소요되거나 비용이 많이 들거나 전체 모집단을 연구하기 어려울 때 유용하게 사용될 수 있다.

앞서 본 유층 샘플링도 하위그룹을 만들고, 그 하위그룹에서 무작위로 샘플을 추출한다는 점에 대해서는 클러스터 샘플링과 비슷하다. 하지만 보통 클러스터 샘플링은 지정학적 특성을 사용하여 하위 그룹을 나눈다. 예를 들어 도시, 학군 등이다.

R

#클러스터 샘플링 예시
#install.packages("sampling")
library(sampling)

# 모집단 'pop' 생성
pop <- c(1:100)

# 모집단을 5개의 클러스터로 나눔
clusters <- cutree(hclust(dist(pop)), k = 5)

# 클러스터 중 일부를 선택
sample_clusters <- sample(unique(clusters), size = 3, replace = FALSE)

# 선택된 클러스터에 대해서 무작위로 샘플을 추출
sample_indices <- which(clusters %in% sample_clusters)
sample <- pop[sample_indices]

 

Python

# 클러스터 샘플링 예시
import random
import numpy as np

# 모집단 'pop'생성
pop = np.arange(1,101)

# 모집단을 5개의 클러스터로 나눔
clusters = np.array_split(pop, 5)

# 클러스터 중 일부를 선택
sample_clusters = random.sample(clusters, 3)

# 선택된 클러스터에 대해서 무작위로 샘플을 추출
sample = np.concatenate(sample_clusters)

 

1.5 다단계 샘플링 (Multistage Sampling)

다단계 샘플링은 원하는 샘플의 크기에 도달할 때까지 여러 단계의 샘플링 과정을 수행하는 방법이다. 이 방법은 클러스터 샘플링과 유사하나, 클러스터 샘플링이 한 번의 클러스터링을 거치는 반면, 다단계 샘플링은 2번 이상의 클러스터링을 거치는 차이가 있다. 즉, 더 여러 번 군집화를 시켜서 샘플의 크기가 충분히 작아질 때까지 반복적으로 클러스터링과 샘플링을 하는 것이다. 때에 따라 유층 샘플링 및 클러스터 샘플링이 같이 사용되기도 한다.

아래 예시 코딩이 다소 길지만, 참고용으로만 봐주길 바란다.

R

# 클러스터 샘플링과 유층 샘플링을 포함한 다단계 샘플링 예시
# 랜덤으로 데이터를 생성
set.seed(123)
population <- data.frame(
  id = 1:1000,
  cluster = sample(1:20, 1000, replace = TRUE),
  strata = sample(1:4, 1000, replace = TRUE),
  variable = rnorm(1000)
)

# 임의로 3개의 계층(strata)를 선택
strata_sample <- sample(unique(population$strata), 3, replace = FALSE)
strata_population <- population[population$strata %in% strata_sample, ]

# 선택된 계층 중에서 임의로 2개의 클러스터를 선택
cluster_sample <- lapply(strata_sample, function(str) {
  sample(unique(strata_population[strata_population$strata == str, "cluster"]), 2, replace = FALSE)
})
cluster_sample <- unlist(cluster_sample)

# 각 클러스터에서 임의로 5개의 데이터(Observation)를 선택
final_sample <- strata_population[strata_population$cluster %in% cluster_sample, ]
final_sample <- by(final_sample, final_sample$cluster, function(x) x[sample(nrow(x), 5, replace = FALSE),])
final_sample <- do.call(rbind, final_sample)

# 추출된 최종 샘플 확인
final_sample

Python

# 클러스터 샘플링과 유층 샘플링을 포함한 다단계 샘플링 예시
import pandas as pd
import numpy as np

# 랜덤으로 데이터를 생성
np.random.seed(123)
population = pd.DataFrame({
    'id': range(1, 1001),
    'cluster': np.random.choice(range(1, 21), 1000),
    'strata': np.random.choice(range(1, 5), 1000),
    'variable': np.random.normal(size=1000)
})

# 임의로 3개의 계층(strata)를 선택
strata_sample = np.random.choice(np.unique(population['strata']), 3, replace=False)
strata_population = population[population['strata'].isin(strata_sample)]

# 선택된 계층 중에서 임의로 2개의 클러스터를 선택
cluster_sample = []
for stratum in strata_sample:
    clusters = strata_population.loc[strata_population['strata'] == stratum, 'cluster'].unique()
    selected_clusters = np.random.choice(clusters, 2, replace=False)
    cluster_sample.append(selected_clusters)
cluster_sample = np.concatenate(cluster_sample)

# 각 클러스터에서 임의로 5개의 데이터(Observation)를 선택
final_sample = pd.concat([
    strata_population.loc[strata_population['cluster'].isin(cluster_sample)]
    .groupby('cluster')
    .apply(lambda x: x.sample(5))
])

# 추출된 최종 샘플 확인
print(final_sample)

 

2. 비통계적 샘플링 방법

앞서 알아본 통계적 샘플링 방법과는 달리, 비통계적 방법은 샘플의 크기와 선택 과정을 결정하기 위해 수학적 확률 이론에 근거하지 않는다. 대신 샘플링하는 사람의 판단에 의존한다. 비통계적 샘플링 방법으로는 다음과 같은 방법들이 있다:

  • 편의 샘플링(Convenience Sampling)
  • 할당 샘플링 / 추출단위 선정 할당법(Quota Sampling)
  • 스노우볼 샘플링 (Snowball Sampling)

2.1 편의 샘플링 (Convenience Sampling)

편의 샘플링은 말 그대로 ‘편한 대로’ 표본을 찾아 샘플링한다. 즉, 샘플 뽑아내기 쉬운 상황에서 쉬운 샘플만 뽑는 것이다. 예를 들어, 어떤 쇼핑몰에 대한 고객의 의견이 필요한 상황에서 무작위로 샘플을 추출해서 설문을 하는 것이 아니라, 설문조사 시점에 해당 쇼핑몰 안에 있는 고객만을 대상으로 설문하는 것이다. 뭔가 이상하는 생각이 드는 게 당연하다. 이러한 방법으로 샘플을 뽑아내면, 추출된 샘플이 모집단을 대표하지 않고, 편향되어 있을 가능성이 크다.

이런 한계에도 불구하고 편의 샘플링 방법이 종종 쓰이는 이유는 그만큼 ‘편의성’이 좋기 때문이다. 따라서 탐구적 자료분석(EDA, Exploratory data analysis)을 할 때나, 시간과 자원이 너무 없을 때 가볍게 사용된다. 따라서 초기 가설을 수립하거나 인사이트의 실마리를 찾는 용도 정도로만 사용하자.

2.2 할당 샘플링(Quota Sampling)

모집단 내의 계층이 확인되면 각 계층에 있는 데이터 크기에 비례해서 샘플을 추출하는 방법이다. 예를들어, 모집단에 여성이 60%, 남성이 40%가 있으면 샘플도 무작위로 선택하지 않고 동일한 비율의 성별로 선택한다. 모집단의 특성을 미리 인지하고 있어야 가능한 방법이나, 그 특성에 대해 완벽한 이해가 없어 잘못된 샘플 구성을 기획할 수 있다. 또한 선택된 샘플이 모집단을 정확하게 대표하지 않고 편향되어 있을 가능성이 여전히 있다.

3.3 스노우볼 샘플링(Snowball Sampling)

스노우볼 또는 눈덩이 샘플링은 말 그대로 작은 눈덩이 같은 소규모 샘플로 시작해서 비슷한 속성을 가진 다른 데이터들을 추가로 연결시켜 점점 더 큰 눈덩이처럼 샘플을 늘려나가는 방법이다. 보통은 전문적인 설문 조사 시에 샘플에 대한 접근 자체가 어려운 심층조사를 위해 많이 이루어진다. 이 방법은 매우 특이한 모집단에 접근하는 데는 유용할 수 있지만, 처음 시작이 잘못될 경우 편향이 쉽게 일어나는 단점이 있다.