🔥알림🔥
① 테디노트 유튜브 - 구경하러 가기!
② LangChain 한국어 튜토리얼 바로가기 👀
③ 랭체인 노트 무료 전자책(wikidocs) 바로가기 🙌

5 분 소요

이번 에피소드에서는 Pandas 데이터프레임(DataFrame)의 가장 유용하면서 탐색적 데이터 분석(Exploratory Data Analysis)에서 가장 유용하게 사용되는 기능인 통계 입니다.

numpy를 이미 익히셨다면, Pandas의 통계 함수를 사용함에 있어 크게 이질감이 없을 겁니다. 거의 사용방법이 같거든요.

왜냐하면 Pandas가 numpy 패키지 기반으로 만들어졌기 때문에 그렇습니다.

Pandas에서 제공하는 모든 통계 함수에 대해서는 굳이 알 필요없습니다. 자주 사용되는 통계 함수를 위주로 알아보겠습니다.

모듈 import

from IPython.display import Image
import numpy as np
import pandas as pd
import seaborn as sns

데이터셋 로드

df = sns.load_dataset('titanic')
df.head()
survived pclass sex age sibsp parch fare embarked class who adult_male deck embark_town alive alone
0 0 3 male 22.0 1 0 7.2500 S Third man True NaN Southampton no False
1 1 1 female 38.0 1 0 71.2833 C First woman False C Cherbourg yes False
2 1 3 female 26.0 0 0 7.9250 S Third woman False NaN Southampton yes True
3 1 1 female 35.0 1 0 53.1000 S First woman False C Southampton yes False
4 0 3 male 35.0 0 0 8.0500 S Third man True NaN Southampton no True

컬럼(columns) 설명

  • survivied: 생존여부 (1: 생존, 0: 사망)
  • pclass: 좌석 등급 (1등급, 2등급, 3등급)
  • sex: 성별
  • age: 나이
  • sibsp: 형제 + 배우자 수
  • parch: 부모 + 자녀 수
  • fare: 좌석 요금
  • embarked: 탑승 항구 (S, C, Q)
  • class: pclass와 동일
  • who: 성별과 동일
  • adult_male: 성인 남자 여부
  • deck: 데크 번호 (알파벳 + 숫자 혼용)
  • embark_town: 탑승 항구 이름
  • alive: 생존여부 (yes, no)
  • alone: 혼자 탑승 여부

통계

통계는 데이터 분석에서 굉장히 중요한 요소입니다.

데이터에 대한 통계 계산식을 Pandas 함수로 제공하기 때문에 어렵지 않게 통계 값을 산출할 수 있습니다.

describe() - 요약통계

전반적인 주요 통계를 확인할 수 있습니다.

기본 값으로 수치형(Numerical) 컬럼에 대한 통계표를 보여줍니다.

  • count: 데이터 개수
  • mean: 평균
  • std: 표준편차
  • min: 최솟값
  • max: 최대값
df.describe()
survived pclass age sibsp parch fare
count 891.000000 891.000000 714.000000 891.000000 891.000000 891.000000
mean 0.383838 2.308642 29.699118 0.523008 0.381594 32.204208
std 0.486592 0.836071 14.526497 1.102743 0.806057 49.693429
min 0.000000 1.000000 0.420000 0.000000 0.000000 0.000000
25% 0.000000 2.000000 20.125000 0.000000 0.000000 7.910400
50% 0.000000 3.000000 28.000000 0.000000 0.000000 14.454200
75% 1.000000 3.000000 38.000000 1.000000 0.000000 31.000000
max 1.000000 3.000000 80.000000 8.000000 6.000000 512.329200

문자열 컬럼에 대한 통계표도 확인할 수 있습니다.

  • count: 데이터 개수
  • unique: 고유 데이터의 값 개수
  • top: 가장 많이 출현한 데이터 개수
  • freq: 가장 많이 출현한 데이터의 빈도수
df.describe(include='object')
sex embarked who embark_town alive
count 891 889 891 889 891
unique 2 3 3 3 2
top male S man Southampton no
freq 577 644 537 644 549

count() - 개수

데이터의 개수

# DataFrame 전체의 개수를 구하는 경우
df.count()
survived       891
pclass         891
sex            891
age            714
sibsp          891
parch          891
fare           891
embarked       889
class          891
who            891
adult_male     891
deck           203
embark_town    889
alive          891
alone          891
dtype: int64
# 단일 column의 데이터 개수를 구하는 경우
df['age'].count()
714

mean() - 평균

데이터의 평균

# DataFrame 평균
df.mean()
survived       0.383838
pclass         2.308642
age           29.699118
sibsp          0.523008
parch          0.381594
fare          32.204208
adult_male     0.602694
alone          0.602694
dtype: float64
# Column 평균
df['age'].mean()
29.69911764705882

Mean - 조건별 평균

성인 남성의 나이의 평균 구하기

condition = (df['adult_male'] == True)
df.loc[condition, 'age'].mean()
33.17312348668281

연습문제

다음 조건을 만족하는 승객의 나이 평균과 조건을 만족하는 데이터의 개수를 구하세요.

  • fare를 30 이상 40 미만 지불한 승객
  • pclass는 1등급
df.head()
survived pclass sex age sibsp parch fare embarked class who adult_male deck embark_town alive alone
0 0 3 male 22.0 1 0 7.2500 S Third man True NaN Southampton no False
1 1 1 female 38.0 1 0 71.2833 C First woman False C Cherbourg yes False
2 1 3 female 26.0 0 0 7.9250 S Third woman False NaN Southampton yes True
3 1 1 female 35.0 1 0 53.1000 S First woman False C Southampton yes False
4 0 3 male 35.0 0 0 8.0500 S Third man True NaN Southampton no True
# 코드를 입력해 주세요 (데이터 개수 구하기)
condition1 = (df['fare'] >= 30) & (df['fare'] < 40)
condition2 = (df['pclass'] == 1)

df.loc[condition1 & condition2, 'age'].count()
21
# 코드를 입력해 주세요 (나이 평균 구하기)
df.loc[condition1 & condition2, 'age'].mean()
44.095238095238095

skipna=True 옵션

기술 통계 함수에서는 skipna=True기본으로 설정 되어 있습니다.

만약, skipna=False로 설정하게 된다면, NaN 값이 있는 column은 NaN 값으로 출력 됩니다.

# skipna=False를 지정한 경우
df.mean(skipna=False)
survived       0.383838
pclass         2.308642
age                 NaN
sibsp          0.523008
parch          0.381594
fare          32.204208
adult_male     0.602694
alone          0.602694
dtype: float64
# skipna=True를 지정한 경우
df.mean(skipna=True)
survived       0.383838
pclass         2.308642
age           29.699118
sibsp          0.523008
parch          0.381594
fare          32.204208
adult_male     0.602694
alone          0.602694
dtype: float64

median() - 중앙값

데이터의 중앙 값을 출력 합니다. 데이터를 오름차순 정렬하여 중앙에 위치한 값입니다.

이상치(outlier)가 존재하는 경우, mean()보다 median()을 대표값으로 더 선호합니다.

pd.Series([1, 2, 3, 4, 5]).median()
3.0
pd.Series([4, 5, 1, 2, 3]).median()
3.0

짝수개의 데이터가 있는 경우에는 가운데 2개 중앙 데이터의 평균 값을 출력 합니다.

pd.Series([1, 2, 3, 4, 5, 6]).median()
3.5

나이의 평균(mean)과 중앙값(median)은 약간의 차이가 있음을 확인할 수 있습니다.

print(f"나이 평균: {df['age'].mean():.5f}\n나이 중앙값: {df['age'].median()}\n차이: {df['age'].mean() - df['age'].median():.5f}")
나이 평균: 29.69912
나이 중앙값: 28.0
차이: 1.69912

sum() - 합계

데이터의 합계입니다. 문자열 column은 모든 데이터가 붙어서 출력될 수 있습니다.

df.sum()
survived                                                    342
pclass                                                     2057
sex           malefemalefemalefemalemalemalemalemalefemalefe...
age                                                     21205.2
sibsp                                                       466
parch                                                       340
fare                                                    28693.9
class         ThirdFirstThirdFirstThirdThirdFirstThirdThirdS...
who           manwomanwomanwomanmanmanmanchildwomanchildchil...
adult_male                                                  537
alive         noyesyesyesnonononoyesyesyesyesnononoyesnoyesn...
alone                                                       537
dtype: object

단일 column에 대한 합계 출력

df['fare'].sum()
28693.9493

cumsum() - 누적합, cumprod() - 누적곱

누적되는 합계를 구할 수 있습니다.

df['age'].cumsum()
0         22.00
1         60.00
2         86.00
3        121.00
4        156.00
         ...   
886    21128.17
887    21147.17
888         NaN
889    21173.17
890    21205.17
Name: age, Length: 891, dtype: float64

누적되는 곱도 구할 수 있으나, 일반적으로 값이 너무 커지므로 잘 활용하지는 않습니다.

df['age'].cumprod()
0            22.0
1           836.0
2         21736.0
3        760760.0
4      26626600.0
          ...    
886           inf
887           inf
888           NaN
889           inf
890           inf
Name: age, Length: 891, dtype: float64

var() - 분산

# 평균
fare_mean = df['fare'].values.mean()

# 분산
my_var = ((df['fare'].values - fare_mean) ** 2).sum() / (df['fare'].count() - 1)
my_var
2469.436845743116
df['fare'].var()
2469.436845743117

std() - 표준편차

분산(var)의 제곱근

np.sqrt(df['fare'].var())
49.693428597180905
np.sqrt(my_var)
49.6934285971809

min() - 최소값, max() - 최대값

# 최소값
df['age'].min()
0.42
# 최대값
df['age'].max()
80.0

quantile() - 분위

Quantile이란 주어진 데이터를 동등한 크기로 분할하는 지점을 말합니다

10%의 경우 0.1을, 80%의 경우 0.8을 대입하여 값을 구합니다.

# 10% quantile
df['age'].quantile(0.1)
14.0
# 60% quantile
df['age'].quantile(0.8)
41.0

unique() - 고유값, nunique() - 고유값 개수

고유값과 고유값의 개수를 구하고자 할 때 사용합니다.

unique()

df['who'].unique()
array(['man', 'woman', 'child'], dtype=object)

nunique(): 고유값의 개수를 출력합니다.

df['who'].nunique()
3

mode() - 최빈값

최빈값은 가장 많이 출현한 데이터를 의미합니다.

df['who'].mode()
0    man
dtype: object

카테고리형 데이터에도 적용 가능합니다.

df['deck'].mode()
0    C
Name: deck, dtype: category
Categories (7, object): [A, B, C, D, E, F, G]

corr() - 상관관계

corr()로 컬럼(column)별 상관관계를 확인할 수 있습니다.

  • -1~1 사이의 범위를 가집니다.
  • -1에 가까울 수록 반비례 관계, 1에 가까울수록 정비례 관계를 의미합니다.
df.corr()
survived pclass age sibsp parch fare adult_male alone
survived 1.000000 -0.338481 -0.077221 -0.035322 0.081629 0.257307 -0.557080 -0.203367
pclass -0.338481 1.000000 -0.369226 0.083081 0.018443 -0.549500 0.094035 0.135207
age -0.077221 -0.369226 1.000000 -0.308247 -0.189119 0.096067 0.280328 0.198270
sibsp -0.035322 0.083081 -0.308247 1.000000 0.414838 0.159651 -0.253586 -0.584471
parch 0.081629 0.018443 -0.189119 0.414838 1.000000 0.216225 -0.349943 -0.583398
fare 0.257307 -0.549500 0.096067 0.159651 0.216225 1.000000 -0.182024 -0.271832
adult_male -0.557080 0.094035 0.280328 -0.253586 -0.349943 -0.182024 1.000000 0.404744
alone -0.203367 0.135207 0.198270 -0.584471 -0.583398 -0.271832 0.404744 1.000000

특정 컬럼에 대한 상관관계를 확인할 수 있습니다.

df.corr()['survived']
survived      1.000000
pclass       -0.338481
age          -0.077221
sibsp        -0.035322
parch         0.081629
fare          0.257307
adult_male   -0.557080
alone        -0.203367
Name: survived, dtype: float64

댓글남기기