통계학 입문 및 기본 개념
1. 통계학이란?
- 정의: 통계학은 자료를 **수집·정리·분석**하여 의미 있는 결론을 얻는 학문입니다.
- 이유: 현실에서 모든 것을 다 조사(전수조사)하기는 어렵기 때문에, 일부를 뽑아 조사(표본조사)한 뒤 이를 바탕으로 전체(모집단)를 추론하는 방법을 사용합니다. 이를 **추론통계**라고 부릅니다.
👉 즉, 통계는 **현실을 이해하고 의사결정을 돕는 도구**입니다.
2. 왜 통계학을 공부해야 할까?
- 학문적 활용: 경영, 경제, 사회, 의학, 공학 등 거의 모든 분야에서 사용됩니다.
- 일상적 활용: 신문 기사, 선거 여론조사, 제품 리뷰 등 우리가 접하는 많은 정보가 통계로 만들어집니다.
- 실무적 활용: 기업의 품질관리, 마케팅 전략, 고객 만족도 조사 등에 직접적으로 활용됩니다.
3. 통계학의 기본 용어
- 모집단 (Population): 조사 대상 전체 집단. (예: 우리 학교 전체 학생)
- 표본 (Sample): 모집단에서 뽑은 일부 집단. (예: 무작위로 뽑은 100명의 학생)
- 모수 (Parameter): 모집단의 특성을 나타내는 수치.
- 통계량 (Statistic): 표본의 특성을 나타내는 수치.
👉 표본으로부터 통계량을 구하고, 이를 근거로 모집단의 모수를 추정합니다.
4. 자료의 종류
- 횡단 자료 (Cross-section data): 한 시점에서 여러 대상을 조사. (예: 2025년 1학년 학생들의 수학 성적 조사)
- 종단 자료 (Longitudinal data): 같은 대상을 시간의 흐름에 따라 반복 조사. (예: 한 학생의 1학년~3학년 성적 변화 추적)
- 시계열 자료: 특정 기간 동안 계속 기록 (예: 주식 가격, 기온 변화)
- 패널 자료: 여러 대상을 장기간 추적 (예: 가구별 소비 패턴)
- 코호트 자료: 동일 조건을 가진 집단을 장기적으로 관찰 (예: 2005년생 건강 조사)
5. 변수와 척도
- 변수 (Variable): 연구 대상이 가지는 특성. (예: 키, 성별, 성적)
- 척도 (Scale): 변수를 측정하는 방법.
(1) 질적 자료
- 명목 변수 (Nominal): 단순 구분용 (예: 성별, 혈액형)
- 서열 변수 (Ordinal): 순위 의미 있음 (예: 성적 등수, 만족도 설문: 매우 만족~불만족)
(2) 양적 자료
- 등간 변수 (Interval): 간격 의미 있음, 비율 의미 없음 (예: 섭씨 온도, IQ)
- 비율 변수 (Ratio): 간격+비율 의미 있음, 0이 절대적 의미 (예: 몸무게, 소득)
- 이산 변수 (Discrete): 셀 수 있는 값 (예: 학생 수, 책 권수)
- 연속 변수 (Continuous): 셀 수 없는 무한한 값 (예: 키, 몸무게, 시간)
자료의 정리 및 시각화
1. 질적 자료의 정리
(1) 도수분포표
- 정의: 같은 범주(분류)에 속하는 값들을 모아 **빈도(횟수)와 비율**로 정리한 표
- 활용: 한눈에 "어떤 선택이 많은지" 비교 가능
📌 **예시:**
반 학생들의 진로 희망을 조사한 결과 → "취업 11명, 군입대 4명, 대학원 3명, 해외유학 2명"
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib as mpl
# 한글 폰트 설정
mpl.rcParams['font.family'] = 'Malgun Gothic'
mpl.rcParams['axes.unicode_minus'] = False
# 예제 데이터
data = {'진로희망': ['취업','취업','대학원진학','군입대','취업',
'취업','군입대','해외유학','취업','취업',
'취업','대학원진학','해외유학','취업','취업',
'군입대','취업','대학원진학','군입대','취업']}
df = pd.DataFrame(data)
# 도수분포표 생성
freq_table = df['진로희망'].value_counts().reset_index()
freq_table.columns = ['진로희망', '빈도(명)']
freq_table['비율(%)'] = freq_table['빈도(명)'] / len(df) * 100
print(freq_table)
(2) 막대그래프 & 파이 차트
- 막대그래프: 각 범주를 막대의 높이로 표현 (비교에 유리)
- 파이 차트: 전체를 100%로 놓고 각 범주의 비율을 파이 조각으로 표현 (비율 직관적)
import seaborn as sns
# 막대그래프
plt.figure(figsize=(8,6))
sns.countplot(x='진로희망', data=df, order=df['진로희망'].value_counts().index)
plt.title('진로희망별 빈도 (막대그래프)')
plt.show()
# 파이 차트
plt.figure(figsize=(8,8))
plt.pie(freq_table['비율(%)'], labels=freq_table['진로희망'], autopct='%1.1f%%')
plt.title('진로희망별 비율 (파이 차트)')
plt.show()
👉 **정리:** 질적 자료(성별, 혈액형, 진로 등)는 **도수분포표 → 막대그래프/파이차트**로 표현합니다.
2. 양적 자료의 정리
(1) 히스토그램 (Histogram)
- 정의: 수치형 자료를 구간으로 나누어 빈도를 나타낸 그래프
- 특징: 값이 어떻게 분포했는지, 정규분포(종 모양)인지 등을 한눈에 확인
📌 **예시:**
학생들의 키(단위: cm)를 5cm 간격으로 구간 나눠서 몇 명씩 있는지 표시
import numpy as np
# 키 예시 데이터
height = np.random.normal(170, 5, 100) # 평균 170, 표준편차 5, 100명
plt.hist(height, bins=10, edgecolor='black')
plt.title("학생 키 분포 (히스토그램)")
plt.xlabel("키(cm)")
plt.ylabel("빈도(명)")
plt.show()
(2) 줄기-잎 그림 (Stem-and-Leaf Plot)
- 정의: 자료의 실제 값을 보존하면서 분포를 보여주는 방법
- 장점: 숫자 값 자체를 그대로 유지
📌 **예시:**
시험 점수: 72, 75, 81, 84 → "줄기=10단위, 잎=1의 자리"로 표현
# 간단한 줄기-잎 그림 (텍스트 방식)
scores = [72, 75, 81, 84, 85, 89, 90, 91, 92]
stem_leaf = {}
for s in scores:
stem, leaf = divmod(s, 10)
stem_leaf.setdefault(stem, []).append(leaf)
for stem, leaves in stem_leaf.items():
print(f"{stem} | {' '.join(map(str, sorted(leaves)))}")
📐 기술통계량
1. 중심 위치 측정 (자료의 “대표값”)
- 평균 (Mean): 모든 값을 더해 개수로 나눈 값
import numpy as np data = [6, 9, 4, 10, 14] print(np.mean(data)) # 8.6 - 중앙값 (Median): 자료를 크기 순으로 정렬했을 때 “가운데 값”
data = [4, 6, 9, 10, 15] print(np.median(data)) # 9 - 최빈값 (Mode): 가장 자주 등장하는 값
from scipy import stats data = [4, 6, 6, 9, 10] print(stats.mode(data, keepdims=True))
2. 산포도(퍼짐)의 측정 (자료의 “흩어짐”)
- 범위 (Range): 최대값 – 최소값
data = [70, 95] print(max(data) - min(data)) # 25 - 사분위 범위 (IQR): 75% 지점($Q3$) – 25% 지점($Q1$)
data = [2, 3, 4, 5, 6, 7, 8] q3, q1 = np.percentile(data, [75, 25]) iqr = q3 - q1 print(iqr) # 3 - 분산 (Variance): 각 데이터가 평균에서 얼마나 떨어져 있는지의 평균
data = [29, 34, 32, 35, 30] print(np.var(data, ddof=1)) # 6.5 - 표준편차 (Standard Deviation): 분산의 제곱근
data = [29, 34, 32, 35, 30] print(np.std(data, ddof=1)) # 2.55