
같은 숫자로 분산을 구했는데 NumPy는 4.5, pandas는 6.0을 반환할 수 있습니다. 먼저 계산 오류보다 분모를 확인하세요. np.var의 기본값은 ddof=0, Series.var의 기본값은 ddof=1입니다. 무엇으로 나누었는지와 어떤 값을 계산에 포함했는지를 맞추면 차이를 설명할 수 있습니다.
1. 네 값의 분산을 먼저 손으로 계산합니다
가상 자료 [4, 7, 7, 10]의 평균은 7입니다. 평균에서 얼마나 떨어졌는지를 제곱해 더하면 다음과 같습니다.
평균 = (4 + 7 + 7 + 10) / 4 = 7
편차 = [-3, 0, 0, 3]
편차 제곱합 = 9 + 0 + 0 + 9 = 18
네 값을 전체 대상으로 보고 산포를 기술하면 18을 4로 나누어 4.5를 얻습니다. 이 값들로 모집단의 분산을 추정할 때 사용하는 불편 표본분산은 18을 3으로 나누어 6.0을 얻습니다.
여기서는 제곱합이 바뀐 것이 아닙니다. 평균을 구한 자료도 같습니다. 마지막 분모만 달라졌습니다. 6.0이 더 크다는 이유로 무조건 더 정확한 계산이라고 판단할 수는 없습니다.
ddof는 분모에서 빼는 자유도 조정값입니다. 이 예제에서 계산에 들어간 값의 개수를 n이라고 하면 분모는 n - ddof입니다.
ddof=0: 18 / (4 - 0) = 4.5
ddof=1: 18 / (4 - 1) = 6.0
2. 기본값 대신 비교 기준을 명시합니다
다음 코드는 NumPy와 pandas를 사용할 수 있는 Python 환경에서 실행합니다. 1차원 실수 배열과 같은 값의 Series를 만들며, 파일이나 외부 데이터는 필요하지 않습니다.
import numpy as np
import pandas as pd
values = np.array([4., 7., 7., 10.])
series = pd.Series(values)
print(np.var(values))
print(series.var())
print(np.var(values, ddof=1))
print(series.var(ddof=0))
assert np.isclose(np.var(values), 4.5)
assert np.isclose(series.var(), 6.0)
assert np.isclose(np.var(values, ddof=1), series.var())
assert np.isclose(series.var(ddof=0), np.var(values))
출력은 차례로 다음과 같습니다.
4.5
6.0
6.0
4.5
첫째와 둘째 줄은 각 라이브러리의 기본 동작입니다. 셋째 줄에서는 NumPy의 ddof를 1로 바꾸어 pandas 기본값에 맞췄고, 넷째 줄에서는 pandas의 ddof를 0으로 바꾸어 NumPy 기본값에 맞췄습니다.
분모가 n인 값을 비교하려면 양쪽 모두 ddof=0을, 분모가 n-1인 값을 비교하려면 양쪽 모두 ddof=1을 명시하세요. 함수 이름이 같다는 사실만으로 기본 정의까지 같다고 가정하면 안 됩니다.
검사문은 화면에 표시된 소수 자릿수가 아니라 실제 계산값을 비교합니다. 다른 자료에서는 부동소수점 연산의 작은 차이가 남을 수 있으므로, 결과가 다르다는 이유만으로 분모 문제라고 단정하지도 않습니다.
3. n-1은 모든 표본을 정답으로 만드는 장치가 아닙니다
같은 분포에서 독립적으로 뽑은 표본이고 모집단의 분산이 유한하다는 조건에서, 표본평균을 이용한 편차 제곱합을 n-1로 나누면 모집단 분산의 불편추정량이 됩니다. 여기서 불편하다는 말은 표본을 반복해서 뽑았을 때 추정값의 평균이 추정 대상과 같다는 뜻입니다.
작은 경우를 모두 나열해 보겠습니다. 0과 2가 각각 같은 확률로 나오는 모집단의 평균은 1, 분산은 1입니다. 여기서 독립적으로 두 번 뽑으면 다음 네 순서쌍이 같은 확률로 나옵니다.
[0, 0]: 편차 제곱합 0 → n-1로 나눈 분산 0
[0, 2]: 편차 제곱합 2 → n-1로 나눈 분산 2
[2, 0]: 편차 제곱합 2 → n-1로 나눈 분산 2
[2, 2]: 편차 제곱합 0 → n-1로 나눈 분산 0
네 추정값의 평균은 (0 + 2 + 2 + 0) / 4 = 1입니다. 반대로 n으로 나누면 추정값은 0, 1, 1, 0이 되어 평균이 0.5입니다.
그렇다고 n-1로 나눈 개별 표본의 결과가 항상 1인 것은 아닙니다. 위에서는 오히려 0 또는 2가 나옵니다. 불편성과 개별 추정값의 정확도는 구분해야 합니다. 불편 분산의 제곱근을 취했다고 표준편차 추정량까지 자동으로 불편해지는 것도 아닙니다.
문제에서 요구하는 통계량의 정의와 표본 추출 조건을 먼저 읽으세요. ‘표본’이라는 단어 하나나 함수의 기본값만 보고 어떤 분모든 항상 정답이라고 외우는 방식은 피하는 편이 좋습니다.
4. NaN이 있으면 분모뿐 아니라 포함 대상을 맞춥니다
이번에는 [4, 7, NaN, 7, 10]으로 바꿉니다. np.var는 이 NaN을 자동으로 제외하지 않습니다. 반면 np.nanvar는 NaN을 제외하며, Series.var도 기본 skipna=True에서 결측값을 제외합니다.
import numpy as np
import pandas as pd
values = np.array([4., 7., np.nan, 7., 10.])
series = pd.Series(values)
print(np.var(values))
print(np.nanvar(values, ddof=1))
print(series.var(ddof=1))
print(series.var(ddof=1, skipna=False))
assert np.isnan(np.var(values))
assert np.isclose(np.nanvar(values, ddof=1), 6.0)
assert np.isclose(series.var(ddof=1), 6.0)
assert np.isnan(series.var(ddof=1, skipna=False))
출력은 다음과 같습니다.
nan
6.0
6.0
nan
NaN을 제외한 값은 [4, 7, 7, 10]이므로 유효한 값은 네 개입니다. ddof=1일 때 분모는 전체 배열 길이 5에서 1을 뺀 4가 아니라, 유효한 값 4에서 1을 뺀 3입니다.
ddof만 같게 두고 한쪽은 NaN을 포함하고 다른 쪽은 제외하면 비교 조건이 여전히 다릅니다. 두 함수의 분모와 결측값 처리 정책을 함께 확인해야 합니다.
NaN을 제외하는 것은 0으로 바꾸는 일과도 다릅니다. 또한 제외 후 계산이 된다는 사실이 결측값을 버려도 통계적으로 문제가 없다는 뜻은 아닙니다. 여기서는 같은 관측값으로 같은 정의의 분산을 계산하는지에만 범위를 둡니다.
5. 유효한 값이 하나라면 0과 NaN을 구분합니다
[8]의 편차 제곱합은 0입니다. ddof=0이면 0/1이므로 분산은 0입니다. 이는 주어진 한 값 자체의 산포가 없다는 설명이지, 더 넓은 모집단의 분산도 0이라는 증거는 아닙니다.
ddof=1이면 분모가 0이 되어 불편 표본분산을 계산할 수 없습니다. NumPy의 해당 연산은 NaN과 경고를 반환할 수 있고, pandas Series.var도 이 조건에서는 NaN을 반환합니다. NaN을 단순히 0으로 바꾸면 ‘산포가 없음’과 ‘계산에 필요한 값이 부족함’을 섞게 됩니다.
이 글의 코드는 1차원 실수 자료를 비교합니다. 2차원 배열이나 DataFrame으로 넓히면 어떤 축을 따라 계산했는지도 맞춰야 합니다. 분산과 표준편차를 섞어 비교하거나, 무한대·자료형·수치 정밀도 차이를 놓치지 않는지도 따로 살펴야 합니다.
핵심 요약
같은 값으로 결과가 다르면 먼저 ddof를 확인하세요. [4, 7, 7, 10]은 ddof=0에서 4.5, ddof=1에서 6.0이며 제곱합은 같습니다.
결측값이 있으면 유효한 값의 개수와 제외 정책도 맞춰야 합니다. np.var, np.nanvar, Series.var는 이름이 비슷해도 기본 동작이 모두 같지는 않습니다.
n-1 보정은 표본 추출 조건 아래에서 분산 추정의 편향을 다루는 규칙입니다. 개별 결과의 정확도나 부족한 관측값까지 해결해 주는 규칙은 아닙니다.
'자격증 > 빅데이터 분석 기사' 카테고리의 다른 글
| pandas groupby에서 행이 사라질 때: dropna=False와 size·count 구분 (0) | 2026.10.04 |
|---|---|
| pandas read_csv: 앞자리 0과 문자열 NA를 보존하는 방법 (0) | 2026.10.03 |
| 빅데이터분석기사 전처리 누수 실습: 평균 대체와 Pipeline 적용 순서 (0) | 2026.10.01 |
| 빅데이터분석기사 필기 혼동행렬 계산 실습: 정밀도·재현율·F1과 지표 선택 (0) | 2026.09.29 |
| 빅분기 실기 연습 모음집: 1·2·3유형 문제와 CSV·노트북 (0) | 2026.09.15 |
댓글