python의 pandas를 이용해 데이터의 기초 통계를 알아보자.
데이터 불러오기
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
from datetime import datetime
from statsmodels.tsa.seasonal import seasonal_decompose
# 한글 깨짐
plt.rc('font', family='NanumBarunGothic')
df = pd.read_excel('../data/도로교통공단_일자별 시군구별 교통사고 건수.xlsx')
df.head()
현재 발생월, 일이 조금 알아보기 어려운 형태라 이 부분만 조금 수정해 보자.
# date format 변경
a = range(0, 59724)
b = range(0, 59724)
df['dt'] = pd.DataFrame(list(map(lambda x, y: '2020-'+ str(df['발생월'][x]) + '-' + str(df['발생일'][y]), a, b)))
df['ym'] = pd.DataFrame(list(map(lambda x: '2020-'+ str(df['발생월'][x]), a)))
df['dt'] = df['dt'].map(lambda x : datetime.strptime(x, '%Y-%m-%d').strftime('%Y-%m-%d'))
df['ym'] = df['ym'].map(lambda x : datetime.strptime(x, '%Y-%m').strftime('%Y-%m'))
df.head()
기초 통계
df.describe()
- count: 데이터의 row가 몇 개인지
- mean: 평균
- std: 표준편차
- min: 최솟값
- max: 최댓값
그런데 이렇게 describe()를 사용하지 않고 각 통계를 알아보는 방법도 살펴보자.
산술평균
df.mean()
특정 컬럼에 대한 평균값만 구하고 싶을때는 다음과 같다.
df.groupby('ym').사고건수.mean()
다음 코드는 위와 동일한 계산이다.
df.groupby('ym').사고건수.sum()/df.groupby('ym').사고건수.count()
중앙값
df.median()
사실 이 값이 아까 describe()에서 봤던 50%의 값이다.
최빈값
df.mode()
이 결과는 각 컬럼에 대해서 최빈값을 구하는 거라 통일성이 없다.
df['사고건수'].describe()
만약에 월별로 특정 컬럼에서 최빈값을 알고 싶을 때는 다음과 같이 하면 된다.
df.groupby('ym')['사고건수'].agg(pd.Series.mode)
기하평균
기하평균을 구해보기 전에 기하평균의 정의를 생각해 보자.
기하평균은 위 그림처럼 이해하면 된다.
그럼 이제 우리 데이터에서 2020년 월평균 사고건수의 증가율을 알아보자.
pandas 이용해서 기하평균 구하기
우선 데이터를 확인해 보자.
현재 데이터는 일별로 나와있기 때문에 월별로 사고건수를 합쳐보자
사실 이렇게 하는 건 데이터프레임이 아니기 때문에 데이터프레임으로 바꿔주자.
데이터프레임 만들기
아래와 같이 reset_index()를 안 해주면 ym이 인덱스가 되어버리기 때문에 reset_index()를 해주자.
tmp = pd.DataFrame(df.groupby(['ym']).사고건수.sum()).reset_index()
tmp
이제 여기서 각 월별로 얼마큼 증가하고 감소하는지 확인해 보자.
shift 사용
우선 shift(1)을 적용해 보자
0번은 없고(NaN) 1번이 16968.0이다.
위 데이터와 비교해 보면 데이터가 하나씩 내려온 모습이다.
tmp['사고건수'].shift(2)
이렇게 보면 두 개씩 내려간 모습이다.
우리는 이제 다음 달 거랑 비교를 해야 하기 때문에 0번째 데이터 옆에 첫 번째 데이터가 와야 한다. (그래야 그 추이를 알 수 있다.)
이때 shift(-1)을 해준다.
tmp['사고건수'].shift(-1)
이렇게 만든 값을 알아보기 쉽게 컬럼으로 추가해 주자
tmp['shift_data'] = tmp['사고건수'].shift(-1)
tmp
이제 '사고건수'에서 'shift_data'로 값이 얼마나 증가했는지 구해보자
증가율 계산하기
rate1에는 실제 증가율을 넣어주자.
tmp['rate1'] = ((tmp['shift_data']-tmp['사고건수']) / tmp['사고건수'])
tmp
이렇게 구해진 값을 이제 1에 대입해서 마이너스면 1에서 빼줘야 하고, 플러스면 1을 더해주는 작업을 해줘야 한다. 이 데이터를 rate2에 저장해 줄 생각이다.
tmp['rate2'] = ''
tmp
tmp.loc[tmp['rate1'] > 0, 'rate2'] = tmp['rate1'] + 1
tmp
tmp['rate1'] > 0라는 조건에 만족하면 'rate2'에 tmp['rate1'] + 1 값을 넣어라 라는 의미다
tmp.loc[tmp['rate1'] < 0, 'rate2'] = 1 - abs(tmp['rate1'])
tmp
이렇게 나온 데이터를 확인해 보자.
1월 데이터로 보자면 사고건수 16968에 95퍼센트(rate2)를 곱하면 shift_data가 나온다.
16968.0*0.959748
>>> 16285.004064
기하평균 구하기
기하평균을 계산하기 위해 모든 값을 곱한 후 1/n 제곱을 해준다.
일단 데이터에서 12월에 있는 NaN를 없애고 시작하자.
tmp.dropna(axis=0, inplace=True)
tmp
여기서 나온 rate2 값이 위에서 기하평균을 설명하기 위한 그림의 2, 0.833 같은 데이터를 의미한다.
각각의 값을 누적해서 곱하는 방법에는 두 가지가 있다. 하나는 reduce다.
from functools import reduce
arr = tmp['rate2']
reduce(lambda x, y: x * y, arr)
>>> 0.9623998114097124
또 다른 방법으로는 eval이 있다.
'*'.join([str(n) for n in arr])
num1 = eval('*'.join([str(n) for n in arr]))
이렇게 하면 모든 값이 곱해진다.
이제 제곱을 해주자.
import math
num2 = math.pow(num1, 1/11) # 1/11은 데이터가 11개라 그렇다
num2
>>> 0.9965219433837762
여기서 나온 0.99는 0.99%라는 소리다. 사실상 사고건수가 거의 변하지 않는다는 의미다.
이렇게 있을 때 이제 시작점인 16968에서 매번 0.9965를 곱해주면 이제 num2값이 평균이니까 가장 마지막 숫자랑 동일해져야 한다.
val = 16968
for i in range(len(tmp)):
val = val*num2
print(val)
'EDA' 카테고리의 다른 글
사분위 범위 및 Boxplot으로 데이터 분포 분석 (2) (0) | 2024.08.26 |
---|---|
[넷플릭스 데이터 분석 - 3] 넷플릭스 데이터 시각화(수치 시각화, 워드 클라우드) (5) | 2024.08.05 |
[넷플릭스 데이터 분석 - 2] Feature Engineering (0) | 2024.08.05 |
[넷플릭스 데이터 분석 - 1] 결측치 처리 (0) | 2024.08.05 |