통계 (Statistics)
정의
통계 (Statistics) 는 데이터를 수집, 정리, 분석하는 학문. PS 에서는 주로 기술 통계 (Descriptive Statistics) 의 기본값들인 평균 (Mean), 중앙값 (Median), 분산 (Variance), 표준편차 (Standard Deviation) 와 스트리밍 통계 (Streaming / Online Statistics) 를 다룬다.
핵심 질문: “대량의 데이터(또는 무한 스트림)에서 평균과 분산을 얼마나 효율적으로 계산할 수 있는가?”
문제 상황과 동기
“N 개의 원소로 이루어진 집합에서 통계량을 계산” 또는 “데이터가 하나씩 들어올 때마다 통계량을 갱신”.
- Naive: 전체 데이터를 배열에 저장. 평균 O(N), 분산 O(N) (두 번 순회). 메모리 O(N).
- Online (Welford): 데이터가 한 개 올 때마다 O(1) 갱신. 메모리 O(1). 한 번만 순회.
- 중앙값: naive 는 매번 정렬 O(N log N). 힙으로 O(log N) 갱신.
핵심 통찰: 통계량을 점화식(재귀 관계)으로 표현하면 이전 값 + 새 값만으로 갱신 가능.
시각화
핵심 아이디어
평균 (Mean)
μ_n = (Σ x_i) / n
Online: μ_n = μ_{n-1} + (x_n - μ_{n-1}) / n
분산 (Variance)
모분산: σ²_n = Σ (x_i - μ)² / n
Welford’s online algorithm (1-pass, numerically stable):
δ = x_n - μ_{n-1}
μ_n = μ_{n-1} + δ / n
M2_n = M2_{n-1} + δ * (x_n - μ_n) # sum of squared differences
σ²_n = M2_n / n # population variance
표본 분산: s²_n = M2_n / (n-1).
중앙값 (Median)
- 정렬 상태 유지: O(N log N) 초기 비용 + O(N) 삽입 (shift).
- Two-heap (max-heap + min-heap): O(log N) 삽입, O(1) median 조회.
알고리즘
# 평균 / 분산 (online streaming)
welford_update(μ, M2, n, x):
n' = n + 1
δ = x - μ
μ' = μ + δ / n'
M2' = M2 + δ * (x - μ')
return μ', M2', n'
# 중앙값 (two-heap)
median_add(low_maxheap, high_minheap, x):
if low is empty or x <= low.top():
low.push(x)
else:
high.push(x)
rebalance(low, high) # ensure |low| == |high| or |low| == |high| + 1
median(low, high):
return low.top() # low has one more or equal
구현
// Welford online variance + two-heap median
#include <bits/stdc++.h>
using namespace std;
int main() {
vector<double> data = {5, 8, 3, 9, 2, 7};
// Welford online
double mu = 0, M2 = 0;
int n = 0;
for (double x : data) {
n++;
double delta = x - mu;
mu += delta / n;
M2 += delta * (x - mu);
}
double variance = M2 / n;
// Two-heap median
priority_queue<double> low;
priority_queue<double, vector<double>, greater<>> high;
for (double x : data) {
if (low.empty() || x <= low.top()) low.push(x);
else high.push(x);
if (low.size() < high.size()) {
low.push(high.top());
high.pop();
} else if (low.size() > high.size() + 1) {
high.push(low.top());
low.pop();
}
}
double median = low.top();
cout << fixed << setprecision(4);
cout << "Mean: " << mu << "\n";
cout << "Variance: " << variance << "\n";
cout << "Median: " << median << "\n";
}Mean: 5.6667
Variance: 5.8889
Median: 5.5000복잡도
| 항목 | 값 |
|---|---|
| 평균 (online) | O(1) 갱신, O(1) 조회, O(1) 공간 |
| 분산 (Welford online) | O(1) 갱신, O(1) 조회, O(1) 공간, 안정적 |
| 중앙값 (two-heap) | O(log N) 삽입, O(1) 조회, O(N) 공간 |
| 중앙값 (정렬 naive) | O(N log N) 초기, O(N) 삽입, O(N) 공간 |
| 표준편차 | sqrt(분산), O(1) |
변형 / 활용
| 변형 | 설명 |
|---|---|
| 표본 분산 | M2 / (n-1) (Bessel’s correction), 표본 추정 편향 보정 |
| Weighted mean | μ_w = Σ w_i x_i / Σ w_i, 각 항목 가중치 |
| Min / Max / Range | Online min/max 는 O(1) 갱신, range = max - min |
| 사분위수 | median 의 확장, Q1 / Q3 별도 힙 또는 order statistic tree 필요 |
| 히스토그램 | 구간별 빈도수, 등간격 buckets, O(1) 갱신 |
| Exponential moving average | EMA = α · x + (1-α) · EMA_prev, 시계열 평활 |
함정
1. Naive 분산 (two-pass) 의 수치적 불안정
σ² = (Σ x²_i)/n - μ² 는 같은 부호 큰 수 끼리의 소거로 precision loss. 항상 Welford 권장.
2. 중앙값 two-heap rebalance
low 가 항상 high 보다 1 많거나 같도록 유지. 삽입마다 크기 비교 후 pop/push 교환.
3. Variance / std vs sample variance
σ² = M2 / n (population) vs s² = M2 / (n-1) (sample). PS 에서는 population 기준이 일반적.
4. 정수 데이터 분산
정수 평균이 실수면 정수 분산 공식 부정확. Σ (x_i - μ)² 를 double 로 계산.
5. 빈 배열 / 단일 원소
n = 0 이면 분산 undefined. n = 1 이면 분산 = 0 (population) 또는 undefined (sample). 경계 분기.
BOJ 연습 문제
| 번호 | 제목 | 정답률 | 링크 |
|---|---|---|---|
| BOJ 2108 | 통계학 | - | kokoa-lab |
| BOJ 18110 | solved.ac | - | kokoa-lab |
| BOJ 1572 | 중앙값 | - | kokoa-lab |
| BOJ 11004 | K번째 수 | - | kokoa-lab |
참고
이 글의 용어 (3개)
- 정렬 알고리즘algorithm
- 정의 정렬 (sort) 은 원소들의 컬렉션을 어떤 전순서 (total order) 기준으로 재배열하는 것. 알고리즘 입문의 정석 주제이자, 데이터베이스·검색·통계 등 모든 시스템…
- 확률 (Probability)algorithm
- 정의 확률 (Probability) 은 사건이 발생할 가능성을 수치화한 값. 표본 공간 Ω 에 대해 P(A) = |A| / |Ω| (동일 확률), 또는 더 일반적으로는 σ-alg…
- Priority Queue / Heap: 우선순위 큐algorithm
- 정의 Priority Queue 는 우선순위가 가장 높은 원소를 O(log N) 에 pop 할 수 있는 자료구조입니다. Binary Heap 이 표준 구현. Max-heap: 부…
💬 댓글