HOWTO · Pandas
Pandas에서 층화 샘플링을 수행하는 방법
Pandas DataFrame에서 그룹별 동일한 크기 또는 모집단 비율에 따른 층화 표본을 추출하는 방법을 알아보세요.
이 페이지의 내용
Pandas에서는 층화 기준 열로 정한 그룹 안에서 표본을 추출할 수 있습니다. 그룹 간 비교가 중요하면 각 그룹에서 같은 수의 행을 선택하고, 표본이 모집단의 구성을 반영해야 하면 그룹 크기에 비례해 정해진 총수를 배분하세요. 예시 표본 추출에 고정 난수 시드를 사용하면 결과를 재현할 수 있습니다.
통계에서의 층화 표본추출
층화 표본추출에서는 모집단을 서로 겹치지 않는 여러 그룹, 즉 층으로 나눈 다음 각 층에서 관측값을 선택합니다. 층은 학년, 지역, 연령대처럼 분석 질문과 관련된 특성으로 정할 수 있습니다. 각 그룹에서 표본을 추출하면 중요한 그룹이 표본에 포함되도록 할 수 있지만, 그것만으로 선택 편향이 없어지거나 표본이 모집단을 대표한다고 보장되지는 않습니다. 표본 추출 대상과 관측값을 선택하는 방식도 여전히 중요합니다.
연구자는 그룹별 차이가 추정 결과에 영향을 줄 때 층화 표본추출을 사용합니다. 데이터 실무자는 각 범주가 학습 세트와 테스트 세트에 모두 포함되도록 데이터를 나눌 때도 이를 활용할 수 있습니다. 먼저 어느 열을 층화 기준으로 삼을지, 그리고 각 그룹에서 같은 수를 뽑을지 모집단 크기에 따른 비율로 뽑을지 정하세요. 두 방식은 서로 다른 질문에 답합니다. 같은 수를 뽑으면 그룹 간 비교에 초점을 두고, 비례해서 뽑으면 그룹별 상대적 크기를 유지합니다.
Pandas에서 층화 표본추출 수행하기
아래 예제에서는 세 학년 그룹에 속한 학생 10명으로 DataFrame을 만듭니다. 각 학년에서 학생 2명씩 뽑아 그룹별 표본 크기를 같게 만든 다음, 전체 6명을 그룹 크기에 비례해 배분합니다. 비례 배분에는 최대 나머지 방법을 사용합니다. 각 그룹의 정확한 할당량에서 소수 부분을 버린 뒤, 남은 자리를 소수 나머지가 큰 그룹부터 배정합니다. 이 예제의 그룹 크기는 5, 3, 2이므로 6개 행은 각각 3, 2, 1개로 배분됩니다.
import pandas as pd
students = {
"Name": [
"sanay", "shivesh", "rutwik", "preet", "yash",
"mann", "pritesh", "hritesh", "raj", "tarun",
],
"ID": ["001", "002", "003", "004", "005", "006", "007", "008", "009", "010"],
"Grade": ["A", "A", "C", "B", "B", "B", "C", "A", "A", "A"],
"Category": [2, 3, 1, 3, 2, 3, 3, 1, 2, 1],
}
df = pd.DataFrame(students)
# Take the same number from each grade.
equal_sample = df.groupby("Grade", group_keys=False).sample(n=2, random_state=7)
print("Equal-sized counts:")
print(equal_sample["Grade"].value_counts().sort_index().to_dict())
# Allocate a fixed total in proportion to each grade's population size.
target = 6
group_sizes = df["Grade"].value_counts().sort_index()
quotas = group_sizes / len(df) * target
allocation = quotas.astype(int)
places_left = target - int(allocation.sum())
remainders = (quotas - allocation).sort_values(ascending=False)
for grade in remainders.index[:places_left]:
allocation.loc[grade] += 1
proportional_sample = pd.concat(
[
group.sample(n=int(allocation.loc[grade]), random_state=7)
for grade, group in df.groupby("Grade", sort=True)
],
ignore_index=True,
)
print("Proportional counts:")
print(proportional_sample["Grade"].value_counts().sort_index().to_dict())
DataFrame.groupby()는 표본 추출에 사용할 그룹을 만듭니다. 자세한 내용은 한국어 Pandas groupby() 참조 문서를 확인하세요.
그룹별 표본 크기를 같게 하려면 sample(n=2)로 각 학년에서 행 2개를 요청합니다. 따라서 가장 작은 그룹에도 행이 2개 이상 있어야 합니다. 그렇지 않다면 그룹별 추출 수를 줄이거나 층을 다시 정하세요. 비례 표본에서는 target이 요청한 전체 행 수이며, 배분 단계에서 반올림을 처리해 그룹별 수의 합이 그 값과 일치하도록 합니다. 소수 나머지가 같으면 반올림 규칙에 따라 남은 자리를 서로 다른 그룹에 배정할 수 있으므로, 분석을 반복할 때는 규칙을 문서화하세요.
두 호출 모두 random_state=7을 사용하므로 입력과 Pandas 환경이 같으면 표본 추출 결과를 재현할 수 있습니다. 다른 무작위 표본을 원하면 시드를 바꾸세요. 층화 표본추출은 각 그룹에서 추출하는 관측값 수를 조절하지만, 원본 데이터나 추출 과정에 편향이 있다면 그룹 안의 관측값까지 무작위가 되게 하지는 않습니다. 표본을 재현해야 한다면 층화 기준 열, 배분 규칙, 목표 표본 크기, 시드를 함께 기록하세요.