Skip to Content

기술통계

초급

학습 목표

이 레시피를 완료하면 다음을 할 수 있습니다:

  • 중심 경향 지표 (평균, 중앙값, 최빈값) 계산
  • 산포도 지표 (표준편차, 분산, IQR) 이해
  • 분포 형태 파악 (왜도, 첨도)
  • Pandas와 SQL로 기술통계 계산

0. 사전 준비 (Setup)

데이터 실습을 위해 CSV 파일을 로드합니다.

import pandas as pd import numpy as np import seaborn as sns import matplotlib.pyplot as plt from scipy import stats # Load Data orders = pd.read_csv('src_orders.csv', parse_dates=['created_at']) items = pd.read_csv('src_order_items.csv') products = pd.read_csv('src_products.csv') users = pd.read_csv('src_users.csv') # Merge for Analysis df = orders.merge(items, on='order_id').merge(products, on='product_id').merge(users, on='user_id')

1. 중심 경향 측정

이론

중심 경향(Central Tendency)은 데이터가 어디에 모여있는지를 나타냅니다.

지표설명장점단점
평균(Mean)모든 값의 합 ÷ 개수모든 데이터 반영이상치에 민감
중앙값(Median)정렬 후 중간값이상치에 강건분포 꼬리 무시
최빈값(Mode)가장 빈번한 값범주형에 유용유일하지 않을 수 있음

Pandas로 계산

import pandas as pd import numpy as np # 기본 통계 print("=== 중심 경향 ===") print(f"평균: ${df['sale_price'].mean():.2f}") print(f"중앙값: ${df['sale_price'].median():.2f}") print(f"최빈값: ${df['sale_price'].mode()[0]:.2f}") # describe()로 한번에 print("\n=== describe() ===") print(df['sale_price'].describe())
실행 결과
=== 중심 경향 ===
평균: $59.73
중앙값: $39.99
최빈값: $25.00

=== describe() ===
count    181026.000000
mean         59.728416
std          67.142661
min           0.020000
25%          24.900000
50%          39.990002
75%          69.949997
max         999.000000
Name: sale_price, dtype: float64

SQL로 계산

SELECT AVG(sale_price) as mean_price, PERCENTILE_CONT(sale_price, 0.5) OVER() as median_price, MIN(sale_price) as min_price, MAX(sale_price) as max_price FROM src_order_items

2. 산포도 측정

이론

산포도(Dispersion)는 데이터가 얼마나 퍼져있는지를 나타냅니다.

지표설명공식
범위(Range)최대 - 최소max - min
분산(Variance)평균과의 차이 제곱의 평균Σ(x-μ)² / n
표준편차(SD)분산의 제곱근√Variance
IQRQ3 - Q175% - 25%
변동계수(CV)상대적 변동SD / Mean × 100%

Pandas로 계산

print("=== 산포도 ===") print(f"범위: {df['sale_price'].max() - df['sale_price'].min():.2f}") print(f"분산: {df['sale_price'].var():.2f}") print(f"표준편차: {df['sale_price'].std():.2f}") print(f"IQR: {df['sale_price'].quantile(0.75) - df['sale_price'].quantile(0.25):.2f}") print(f"변동계수: {df['sale_price'].std() / df['sale_price'].mean() * 100:.1f}%")
실행 결과
=== 산포도 ===
범위: 998.98
분산: 4508.14
표준편차: 67.14
IQR: 45.05
변동계수: 112.4%

변동계수 활용

# 단위가 다른 변수 비교 cv_price = df['sale_price'].std() / df['sale_price'].mean() * 100 cv_age = df['age'].std() / df['age'].mean() * 100 print(f"가격 변동계수: {cv_price:.1f}%") print(f"나이 변동계수: {cv_age:.1f}%") # 변동계수가 높을수록 상대적으로 더 퍼져있음
실행 결과
가격 변동계수: 112.4%
나이 변동계수: 41.6%

3. 분포 형태

왜도 (Skewness)

왜도는 분포의 비대칭성을 측정합니다.

  • 왜도 = 0: 대칭 분포
  • 왜도 > 0: 오른쪽 꼬리 (양의 왜도)
  • 왜도 < 0: 왼쪽 꼬리 (음의 왜도)
from scipy import stats skewness = stats.skew(df['sale_price'].dropna()) print(f"왜도: {skewness:.3f}") if skewness > 0.5: print("→ 오른쪽으로 치우침 (고가 제품이 일부 있음)") elif skewness < -0.5: print("→ 왼쪽으로 치우침") else: print("→ 대칭에 가까움")
실행 결과
왜도: 5.062
→ 오른쪽으로 치우침 (고가 제품이 일부 있음)

첨도 (Kurtosis)

첨도는 분포의 뾰족한 정도를 측정합니다.

  • 첨도 = 0: 정규분포와 유사
  • 첨도 > 0: 더 뾰족함 (극단값 많음)
  • 첨도 < 0: 더 평평함
kurtosis = stats.kurtosis(df['sale_price'].dropna()) print(f"첨도: {kurtosis:.3f}")
실행 결과
첨도: 45.596

4. 그룹별 기술통계

Pandas groupby + agg

# 부서별 기술통계 dept_stats = df.groupby('department')['sale_price'].agg([ ('개수', 'count'), ('평균', 'mean'), ('중앙값', 'median'), ('표준편차', 'std'), ('최소', 'min'), ('최대', 'max') ]).round(2) print("부서별 가격 통계:") print(dept_stats)
실행 결과
부서별 가격 통계:
             개수  ...     최대
department         ...       
Men         90612  ...  999.0
Women       90414  ...  903.0

[2 rows x 6 columns]

SQL로 그룹별 통계

SELECT department, COUNT(*) as count, AVG(sale_price) as mean, STDDEV(sale_price) as std, MIN(sale_price) as min, MAX(sale_price) as max FROM src_order_items oi JOIN src_products p ON oi.product_id = p.product_id GROUP BY department ORDER BY mean DESC

퀴즈 1: 기술통계 계산

문제

주문 데이터에서 주문당 아이템 수(num_of_item)에 대해:

  1. 평균, 중앙값, 표준편차 계산
  2. 평균과 중앙값의 차이 해석
  3. 변동계수 계산

정답 보기

# 1. 기본 통계 mean_items = df['num_of_item'].mean() median_items = df['num_of_item'].median() std_items = df['num_of_item'].std() print(f"평균: {mean_items:.2f}") print(f"중앙값: {median_items:.2f}") print(f"표준편차: {std_items:.2f}") # 2. 해석 if mean_items > median_items: print("\n→ 평균 > 중앙값: 오른쪽 꼬리 분포 (대량 주문이 일부 있음)") elif mean_items < median_items: print("\n→ 평균 < 중앙값: 왼쪽 꼬리 분포") else: print("\n→ 대칭 분포") # 3. 변동계수 cv = std_items / mean_items * 100 print(f"\n변동계수: {cv:.1f}%")
실행 결과
평균: 1.89
중앙값: 2.00
표준편차: 1.06

→ 평균 < 중앙값: 왼쪽 꼬리 분포

변동계수: 55.9%

정리

핵심 함수 요약

통계량PandasSQL
평균df['col'].mean()AVG(col)
중앙값df['col'].median()PERCENTILE_CONT(col, 0.5)
표준편차df['col'].std()STDDEV(col)
분산df['col'].var()VARIANCE(col)
최소/최대min(), max()MIN(), MAX()
백분위수quantile(0.25)PERCENTILE_CONT(col, 0.25)

통계량 선택 가이드

상황추천
이상치 없음평균, 표준편차
이상치 있음중앙값, IQR
분포 비교변동계수
비대칭 확인왜도

다음 단계

기술통계를 마스터했습니다! 다음으로 상관관계 분석에서 변수 간 관계를 분석하는 방법을 배워보세요.

Last updated on

🤖AI 모의면접실전처럼 연습하기