Notice
Recent Posts
Recent Comments
Link
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

BASEMENT

Python 8주차 - 2 본문

Programming/Python

Python 8주차 - 2

2_34 2020. 8. 10. 09:02

 

파이썬 실습

 

1. 다음과 같이 문자열 출력

 

문자열 입력 : python
n
on
hon
thon
ython
python

string = input("문자열 입력 : ")
n = len(string)
for i in range(n):
    for j in range(i,-1,-1):
        print(string[n-1-j], end='')
    print()
    
# reversed와 join 사용
string = input("문자열 입력 : ")
r = ''

for i in reversed(string):
    r = ''.join(i) + r
    print(r)

 

2. 다음 주어진 숫자들을 작은수에서 큰수의 순서인 오름정렬의 프로그램 작성

- 파이썬 내장함수 sorted, 리스트 메소드 sort 사용하지 말 것

- for 반복문 사용

- 버블정렬

def bubble(data):
    for i in range(len(data)):
        for j in range(1,len(data)):
            if data[j] < data[j-1]:
                data[j], data[j-1] = data[j-1], data[j]
    return data
    
data = [90,20,40,3,7,14,76,45,28,38,17,9]
print(bubble(data))

 

cf) 선택정렬

def selection(data):
    for j in range(len(data)-1):
        min_ = j
        for i in range(j+1, len(data)):
            if data[i] < data[min_]:
                min_ = i
        data[j], data[min_] = data[min_], data[j]
    
    return data

data = [90,20,40,3,7,14,76,45,28,38,17,9]
print(selection(data))

 

cf) 삽입정렬

def insertion(data):
    for i in range(1,len(data)):
        for j in range(8,0,-1):
            if data[j-1] > data[j]:
               data[j-1], data[j] = data[j], data[j-1]

data = [90,20,40,3,7,14,76,45,28,38,17,9]
print(insertion(data))   

 

cf) 쉘정렬

import math

def shell(data):
    size = len(data)
    gap = size//2

    while gap >= 1:
        for i in range(gap,size):
            target = i
            while target>=gap and data[target-gap] > data[target]:
                data[target], data[target-gap] = data[target-gap], data[target]
                target -= gap
        gap //=2

    return data   

data = [90,20,40,3,7,14,76,45,28,38,17,9]
print(shell(data))

 

cf) 퀵정렬

 

선택된 데이터(피벗, pivot)를 기준으로 왼쪽에는 작은값이 오른쪽은 큰값을 배치하는 분할정복법의 정렬 방법

평균적으로 매우 빠른 정렬 방법

불안정한 정렬에 속함

퀵정렬은 전체 리스트를 2개의 부분리스트로 분할하고, 각각의 부분리스트를 다시 퀵정렬로 정렬

비균등 분할하며, 추가적 메모리 공간 필요 없음

정렬된 리스트에 대해서는 수행시간이 더 많이 걸림

많은 언어에서 사용하는 정렬방법으로 2009년에 제안된 dual pivot Quick 정렬 사용

 

시간복잡도

최상, 평균: O(nlog2n)

최악: O(n2)

import random

def rand_shuffle(data): #Knuth의 random shuffle
    N = len(data)
    for i in range(N):
        temp = random.randint(0,i)
        data[i],data[temp] = data[temp],data[i]

def quicksort(data):
    if len(data) < 1:
        return data
    else:
        pivot = data[0]
        less = [i for i in data[1:] if i <= pivot]
        greater = [ i for i in data[1:] if i > pivot]
        return quicksort(less) + [pivot] + quicksort(greater)

data = [50,3,8,11,45,70,37,20,8,29,77,65,33]
rand_shuffle(data)
print(data)
print(quicksort(data))

 

 

Pandas 기초 활용

1. 예제 - traffic_accident_2020.csv

 

1-1) 파일에서 데이터 읽어오기

utf-8 인코딩 오류 시, encoding='CP949' 입력

CP949에도 오류면 encoding='latin' 입력 시도

import pandas as pd
import numpy as np

file_path = "traffic_accident_2020.csv"
df = pd.read_csv(file_path, encoding='CP949')

df.info()
df.describe()

# 결과
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3233 entries, 0 to 3232
Data columns (total 23 columns):
 #   Column      Non-Null Count  Dtype  
---  ------      --------------  -----  
 0   발생년         3233 non-null   int64  
 1   발생년월일시      3233 non-null   int64  
 2   주야          3233 non-null   object 
 3   요일          3233 non-null   object 
 4   사망자수        3233 non-null   int64  
 5   부상자수        3233 non-null   int64  
 6   중상자수        3233 non-null   int64  
 7   경상자수        3233 non-null   int64  
 8   부상신고자수      3233 non-null   int64  
 9   발생지시도       3233 non-null   object 
 10  발생지시군구      3233 non-null   object 
 11  사고유형_대분류    3233 non-null   object 
 12  사고유형_중분류    3233 non-null   object 
 13  사고유형        3233 non-null   object 
 14  가해자법규위반     3233 non-null   object 
 15  도로형태_대분류    3233 non-null   object 
 16  도로형태        3233 non-null   object 
 17  가해자_당사자종별   3233 non-null   object 
 18  피해자_당사자종별   3233 non-null   object 
 19  발생위치X_UTMK  3233 non-null   float64
 20  발생위치Y_UTMK  3233 non-null   float64
 21  경도          3233 non-null   float64
 22  위도          3233 non-null   float64
dtypes: float64(4), int64(7), object(12)
memory usage: 581.1+ KB

발생년	발생년월일시	사망자수	부상자수	중상자수	경상자수	부상신고자수	발생위치X_UTMK	발생위치Y_UTMK	경도	위도
count	3233.0	3.233000e+03	3233.00000	3233.000000	3233.000000	3233.000000	3233.000000	3.233000e+03	3.233000e+03	3233.000000	3233.000000
mean	2019.0	2.019068e+09	1.03588	0.548098	0.225178	0.279307	0.043613	1.005579e+06	1.820305e+06	127.559523	36.377054
std	0.0	3.482074e+04	0.22515	1.765558	0.777163	1.090688	0.439696	7.699214e+04	1.174674e+05	0.854347	1.060132
min	2019.0	2.019010e+09	1.00000	0.000000	0.000000	0.000000	0.000000	7.561250e+05	1.470790e+06	124.723794	33.222138
25%	2019.0	2.019041e+09	1.00000	0.000000	0.000000	0.000000	0.000000	9.461720e+05	1.725952e+06	126.896384	35.527055
50%	2019.0	2.019071e+09	1.00000	0.000000	0.000000	0.000000	0.000000	9.753980e+05	1.827462e+06	127.226176	36.443029
75%	2019.0	2.019101e+09	1.00000	0.000000	0.000000	0.000000	0.000000	1.073766e+06	1.932679e+06	128.319218	37.392024
max	2019.0	2.019123e+09	6.00000	34.000000	17.000000	22.000000	15.000000	1.184860e+06	2.048977e+06	129.550265	38.437576

 

2) column 및 index 명칭 확인

df.columns.values
df.index.values

# 결과
array(['발생년월일시', '주야', '요일', '사망자수', '부상자수', '중상자수', '경상자수', '부상신고자수',
       '발생지시도', '발생지시군구', '사고유형_대분류', '사고유형_중분류', '도로형태_대분류', '도로형태',
       '가해자_당사자종별', '피해자_당사자종별', '경도', '위도'], dtype=object)

array([   0,    1,    2, ..., 3230, 3231, 3232], dtype=int64)

 

3) 불필요한 컬럼 삭제

- drop 함수 사용

- 삭제가 이루어지는 축방향(axis)선정, column 삭제면 1

- inplace = True이면 원본데이터프레임을 수정함

df.drop(['발생년','사고유형','가해자법규위반','발생위치X_UTMK', '발생위치Y_UTMK'], axis=1, inplace=True)

 

4) 컬럼이름 변경 및 새로운 컬럼 추가

 

df.rename(columns={'발생년월일시':'월일시','사망자수':'사망','사상자수':'사상','중상자수':'중상', '경상자수':'경상','부상신고자수':'부상','사고유형_대분류':'유형A','사고유형_중분류':'유형B','도로형태_대분류':'도로A','도로형태':'도로B',
'피해자_당사자종별':'피해','가해자_당사자종별':'가해',}, inplace=True)
df.columns.values

df['월']=df['월일시'].astype(str).str[4:6]
df['일']=df['월일시'].astype(str).str[6:8]
df['시']=df['월일시'].astype(str).str[8:]

df.drop(['월일시'], axis=1, inplace=True)
df.head()

# 결과
	주야	요일	사망	부상자수	중상	경상	부상	발생지시도	발생지시군구	유형A	유형B	도로A	도로B	가해	피해	경도	위도	월	일	시
0	야	화	1	0	0	0	0	부산	해운대구	차대사람	기타	교차로	교차로내	승용차	보행자	129.152465	35.157884	01	01	00
1	야	화	1	0	0	0	0	경기	안산시	차대차	정면충돌	단일로	기타단일로	승용차	승용차	126.857149	37.288292	01	01	03
2	주	화	1	0	0	0	0	경북	청도군	차대차	측면충돌	교차로	교차로부근	승용차	사륜오토바이(ATV)	128.609230	35.650108	01	01	16
3	야	화	1	0	0	0	0	대전	서구	차대사람	횡단중	교차로	교차로부근	승용차	보행자	127.379560	36.355946	01	01	19
4	야	화	1	0	0	0	0	경북	영천시	차대사람	기타	단일로	기타단일로	승용차	보행자	128.915041	35.899506	01	01	21

 

5) 결측치 확인

 

isnull() 사용

missing_df = df.isnull()
missing_type = df[['피해','가해']].isnull()

missing_type.describe()

new_df = df.dropna(subset=['피해'], axis=0)
new_df.head()

# 결과
피해	가해
count	3233	3233
unique	1	1
top	False	False
freq	3233	3233


주야	요일	사망	부상자수	중상	경상	부상	발생지시도	발생지시군구	유형A	유형B	도로A	도로B	가해	피해	경도	위도	월	일	시
0	야	화	1	0	0	0	0	부산	해운대구	차대사람	기타	교차로	교차로내	승용차	보행자	129.152465	35.157884	01	01	00
1	야	화	1	0	0	0	0	경기	안산시	차대차	정면충돌	단일로	기타단일로	승용차	승용차	126.857149	37.288292	01	01	03
2	주	화	1	0	0	0	0	경북	청도군	차대차	측면충돌	교차로	교차로부근	승용차	사륜오토바이(ATV)	128.609230	35.650108	01	01	16
3	야	화	1	0	0	0	0	대전	서구	차대사람	횡단중	교차로	교차로부근	승용차	보행자	127.379560	36.355946	01	01	19
4	야	화	1	0	0	0	0	경북	영천시	차대사람	기타	단일로	기타단일로	승용차	보행자	128.915041	35.899506	01	01	21

 

6) 

- 중복 없이 unique한 값 출력 및 고유값별로 데이터 개수 계산 : unique(), value_counts()

- 가장 개수가 많은 데이터 고유값 출력 : idxmax 사용

- 새로운  파일로 저장 : to_csv 사용

new_df['피해'].unique()
new_df['피해'].value_counts()

new_df['피해'].value_counts().idxmax()
new_df.to_csv("traffic_accident_pre.csv")

 

 

회귀분석 / 시계열 분석

 

1. 회귀분석 - 예제 : 프로야구선수 다음 해 연봉 예측

 

1) 데이터 탐색

# -*- coding: utf-8 -*-
%matplotlib inline

import pandas as pd
import numpy as numpy
import matplotlib.pyplot as plt

picher_file_path = 'picher_stats_2017.csv'
batter_file_path = 'batter_stats_2017.csv'
picher = pd.read_csv(picher_file_path)
batter = pd.read_csv(batter_file_path)
picher.columns
picher.head()
# print(picher.shape)

 

2) 회귀분석에 사용할 피처 탐색

picher_features_df = picher[['승', '패', '홀드', '블론', '경기', '선발', '이닝', '삼진/9', '볼넷/9', '홈런/9', 'BABIP', 'LOB%', 'ERA', 'ERA', 'RA9-WAR', 'FIP', 'kFIP', 'WAR', '연봉(2018)', '연봉(2017)']]

# 피처 각각에 대한 히스토그램 출력
def plot_hist_each_column(df):
    plt.rcParams['figure.figsize'] = [20,16]
    fig = plt.figure(1)

# df의 열 개수 만큼의 subplot 출력
    for i in range(len(df.columns)):
        ax = fig.add_subplot(5,5,i+1)
        plt.hist(df[df.columns[i]], bins=50)
        ax.set_title(df.columns[i])
    plt.show()

plot_hist_each_column(picher_features_df)

 

3) 각 피처 단위간의 정규화 작업

 

- 표준화 방법 적용 -> Z = ((X) – (X의 평균)) / X의 표준편차 

- pd.options.mode.chained_assignment = None -> float 모양으로 출력되게 해주는 코드

- 범주형 피처  정규화 -> get_dummies (원-핫 인코딩) 적용

pd.options.mode.chained_assignment = None 

def standard_scaling(df, scale_columns):
    for col in scale_columns:
        series_mean = df[col].mean()
        series_std = df[col].std()
        df[col] = df[col].apply(lambda x: (x-series_mean)/series_std)
    return df

scale_columns = ['승','패','세','홀드','블론','경기','선발','이닝','삼진/9','볼넷/9','홈런/9','BABIP','LOB%','ERA','RA9-WAR','FIP','kFIP','WAR','연봉(2017)']
picher_df = standard_scaling(picher, scale_columns)
picher_df = picher_df.rename(columns={'연봉(2018)': 'y'})
picher_df.head(5)

 

원-핫 인코딩

team_encoding = pd.get_dummies(picher_df['팀명'])
picher_df = picher_df.drop('팀명', axis=1)
picher_df = picher_df.join(team_encoding)
team_encoding.head(5)

 

4) 회귀분석

 

4-1) 회귀분석을 위한 학습데이터셋, 테스트 데이터셋으로 분리

 

train_test_split()

from sklearn import linear_model
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
from math import sqrt

X = picher_df[picher_df.columns.difference(['선수명','y'])]
y = picher_df['y']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=19)

 

4-2) 회귀분석 계수 학습 & 학습된 계수 출력

lr = linear_model.LinearRegression()
model = lr.fit(X_train, y_train)

print(lr.coef_)

 

 

5) 예측 모델 평가 - 어떤 피처가 가장 영향력이 강한 피처?

 

- 결정계수(R-squared)와 수정결정계수(Adj.R-squared) 가 회귀분석의 평가 지표

- 1에 가까울수록 데이터를 잘 설명하는 모델

- F 통계량의 p-value의 값이 0.05보다 작게 나오면 유의미한 의미라고 평가함

- P>|t| 는 각 피처의 검정 통계량에 대한 유의미성 평가, 0.05보다 적으면 의미있음

- Coef(계수)는 영향력이 큰 피처를 표현

import statsmodels.api as sm

# statsmodel 라이브러리로 회귀분석 수행
X_train = sm.add_constant(X_train)
model = sm.OLS(y_train, X_train).fit()
model.summary()

 

6) 어떤 피처가 가장 영향력이 강한 피처일까? - 시각화

import matplotlib as mpl
set(sorted([f.name for f in mpl.font_manager.fontManager.ttflist]))

# 한글 출력을 위한 사전 설정 단계
mpl.rc('font', family='NanumGothicOTF')
plt.rcParams['figure.figsize'] = [20,16]

# 회귀 계수를 리스트로 반환
coefs = model.params.tolist()
coefs_series = pd.Series(coefs)

# 변수명을 리스트로 반환
x_labels = model.params.index.tolist()

# 회귀계수 출력
ax = coefs_series.plot(kind='bar')
ax.set_title('feature_coef_graph')
ax.set_xlabel('x_features')
ax.set_ylabel('coef')
ax.set_xticklabels(x_labels)

 

7-1) 예측 모델 평가 : R2 score

# 학습 데이터와 테스트 데이터로 분리
X = picher_df[picher_df.columns.difference(['선수명','y'])]
y = picher_df['y']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=19)

# 회귀분석 모델 학습
lr = linear_model.LinearRegression()
model = lr.fit(X_train, y_train)

# 회귀분석 모델 평가
print(model.score(X_train, y_train))
print(model.score(X_test, y_test))

 

7-2) 예측 모델 평가 : RMSE score - 높을수록 예측이 부정확함

y_predictions = lr.predict(X_train)
print(sqrt(mean_squared_error(y_train, y_predictions)))     # train RMSE score 출력
y_predictions = lr.predict(X_test)
print(sqrt(mean_squared_error(y_test, y_predictions)))      # test RMSE score 출력

 

8) 피처들의 상관관계 분석 - heatmap 시각화

import seaborn as sns

# 피처 간의 상관계수 행렬 계산
corr = picher_df[scale_columns].corr(method='pearson')
show_cols = ['win','lose','save','hold','blon','match','start','inning','strike3','ball4','homerun','BABIP','LOB','ERA','RA9-WAR','FIP','kFIP','WAR','2017']

# corr 행렬 히트맵 시각화
plt.rc('font', family='NanumGothicOTF')
sns.set(font_scale=1.5)

hm = sns.heatmap(corr.values,
        cbar=True,
        annot=True,
        square=True,
        fmt='.2f',
        annot_kws={'size':15},
        yticklabels=show_cols,
        xticklabels=show_cols)

plt.tight_layout()
plt.show()

 

9) 회귀분석 예측 성능 높이는 방법 : 다중 공선성 확인

from statsmodels.stats.outliers_influence import variance_inflation_factor

# 피처마다의 VIF 계수 출력
vif = pd.DataFrame()
vif["VIF Factor"] = [ variance_inflation_factor(X.values, i) for i in range(X.shape[1])]
vif["features"] = X.columns
vif.round(1)

 

10) 분석 결과 시각화

# 2018년 연봉을 예측하여 데이터 프레임의 열로 생성
X = picher_df[['FIP','WAR','볼넷/9','삼진/9','연봉(2017)']]
predict_2018_salary = lr.predict(X)
picher_df['예측연봉(2018)'] = pd.Series(predict_2018_salary)

# 원래의 데이터 프레임을 다시 불러옴
picher = pd.read_csv(picher_file_path)
picher = picher[['선수명', '연봉(2017)']]

# 원래의 데이터 프레임에 2018년 연봉 정보를 합침
result_df = picher_df.sort_values(by=['y'], ascending=False)
result_df.drop(['연봉(2017)'], axis=1, inplace=True, errors='ignore')
result_df = result_df.merge(picher, on=['선수명'], how='left')
result_df = result_df[['선수명', 'y', '예측연봉(2018)', '연봉(2017)']]
result_df.columns = ['선수명', '실제연봉(2018)','예측연봉(2018)','작년연봉(2017)']

# 재계약하여 연봉이 변화한 선수만을 대상으로 관찰
result_df = result_df[result_df['작년연봉(2017)'] != result_df['실제연봉(2018)']]
result_df = result_df.reset_index()
result_df = result_df.ix[:10, :]
result_df.head(10)

 

11) 선수별 연봉 정보 막대그래프로 출력

mpl.rc('font', family='NanumGothicOTF')
result_df.plot(x='선수명', y=['작년연봉(2017)', '예측연봉(2018)', '실제연봉(2018)'], kind="bar")

 

 

2. 시계열 분석

 

1) 시계열 데이터 (Time Series Data)

 

시간적 순서를 가지는 데이터로 시간의 흐름에 따라 일정 간격으로 측정된 데이터

데이터의 index가 시간, index간의 시간 간격이 일정함 - 시계열 분석에서 시간의 흐름을 종속변수에 영향을 주는 변수로 취급하기 때문

 

 

2) 시계열 데이터 분석 목적

 

  • 미래값 예측
  • 시계열 데이터 특성 파악 : 경향, 주기, 계절성, 불규칙성 정상성 등
  • 정상성 : 시간 흐름에 영향을 받지 않음, 평균/분산의 안정화, 주기적 변동이 없는 시계열 분포

-> 비정상성 시계열 데이터는 정상화 시켜야 함

 

 

3) 시계열 모델의 과정

 

3-1) Data 확인

- 데이터 시간 확인/ 시간의 format 설정

- 데이터 상태 확인 : 결측치, 반복데이터 등

- 기초 통계 정보 분석 : 트렌드, 계절성 등

 

3-2) 시계열 모델 제작 (Fit Model)

- 모델 가정 확인 : 정상성, 계절성 확인

- 적합한 모델 조율 선택

 

3-3) 모델 검증

 

 

4) 데이터의 정상성 파악

 

  • 정상성 : Mean, variance이 시간에 걸쳐 일정하고 주기적 변동이 없는 시계열 분포
  • 즉, 공분산이 시간 t에 의존하지 않고 오직 시차(시간간격)에만 의존하는 데이터
  • 정상성 확인 방법 : 기초통계량의 시각화 / Dickey-Fuller test

 

 

3. 시계열 분석 예제1 - 1949~1960년 사이의 비행기 승객 수

 

1) 데이터 분석

 

- parse_dates : object 형태의 날짜 데이터를 datetime으로 변경

- index_col : column을 index로 변경

df = pd.read_csv('AirPassengers.csv', parse_dates=['Month'], index_col=['Month'])
plt.xlabel('Date')
plt.ylabel('Num of air Passengers')
plt.plot(df)

 

2) 정상성 확인

 

- Rolling statistics : 그래프로 확인

rolling_mean = df.rolling(window=12).mean()
rolling_std = df.rolling(window=12).std()

plt.plot(df, color='blue', label='Original')
plt.plot(rolling_mean, color='red', label='Rolling Mean')
plt.plot(rolling_std, color='black', label='Rolling Std')
plt.legend(loc='best')
plt.title('Rolling Mean & Rolling Standard Deviation')
plt.show()

 

- Dickey-Fuller Test : p-value < 0.05 정상성이 있음

result = adfuller(df['Passengers'])
print(f'ADF Statistic:{result[0]}')
print(f'p-value: {result[1]}')
print('Critical Values: ')
for key, value in result[4].items():
    print(f'\t{key}: {value}')

 

3) 비정상성 데이터를 정상성화

 

- 변환 : log함수 사용

df_log = np.log(df)
df_log.plot()

 

- 차분

def get_stationarity(timeseries):
#discrimination of stationary
    rolling_mean = timeseries.rolling(window=12).mean()
    rolling_std = timeseries.rolling(window=12).std()
    plt.plot(timeseries, color = 'blue',label='Original')
    plt.plot(rolling_mean,color='red',label='Rolling Mean')
    plt.plot(rolling_std,color='black',label='Rolling Std')
    plt.legend(loc='best')
    plt.title('Rolling Mean & Rolling Standard Deviation')
    plt.show()

    result = adfuller(timeseries['Passengers'])
    print(f'ADF Statistic:{result[0]}')
    print(f'p-value: {result[1]}')
    print('Critical Values: ')
    for key, value in result[4].items():
        print(f'\t{key}: {value}')

rolling_mean = df_log.rolling(window=12).mean()
df_log_minus_mean = df_log - rolling_mean
df_log_minus_mean.dropna(inplace=True)
get_stationarity(df_log_minus_mean)

# 평균 차분 이용
df_log_shift = df_log - df_log.shift()
df_log_shift.dropna(inplace=True)
get_stationarity(df_log_shift)

 

4) 정상화 이면서 트렌드와 계절성이 있는 데이터

 

트렌드와 계절성을 파악하고 두 속성만 분석, 또는 두 속성을 제거하고 시계열 분석

#trend와 seasonal effect를 파악
decomposition = seasonal_decompose(df_log)

#result.observed ## observed 데이터 출력
#result.trend ## trend 데이터 출력
#result.seasonal ## seasonal 데이터 출력
#result.residual

decomposition.plot()

 

5) 전처리한 데이터를 대상으로 ARIMA 생성

model = ARIMA(df_log, order=(2,1,2))
results = model.fit(disp=-1)
plt.plot(df_log_shift)
plt.plot(results.fittedvalues, color='red')

 

cf) ACF, PACF 구하기

 

p + q이 2미만

p * q이 0을 포함한 짝수일 경우 좋은 파라미터 조합 

from statsmodels.graphics.tsaplots import plot_acf
from statsmodels.graphics.tsaplots import plot_pacf

acf_origin = plot_acf(df['Passengers'])
pacf_origin = plot_pacf(df['Passengers'])

acf_log = plot_acf(df_log)
pacf_log = plot_pacf(df_log)

 

6) 모델 비교

predictions_ARIMA_diff = pd.Series(results.fittedvalues, copy=True)
predictions_ARIMA_diff_cumsum = predictions_ARIMA_diff.cumsum()
predictions_ARIMA_log = pd.Series(df_log['Passengers'].iloc[0], index=df_log.index)
predictions_ARIMA_log = predictions_ARIMA_log.add(predictions_ARIMA_diff_cumsum, fill_value=0)
predictions_ARIMA = np.exp(predictions_ARIMA_log)
plt.plot(df)
plt.plot(predictions_ARIMA)

 

7) 생성된 ARIMA모델을  사용하여 예측

 

- 12년간의 승객수에서 향후 10년간의 승객 수를 예측

- 12년 * 12개월 + 10년*12개월 = 264

results.plot_predict(1,264)

 

 

 

4. 시계열 분석 예제2 - 비트코인 시세 예측

 

1) 데이터 탐색 및 시계열 데이터 확인

%matplotlib inline

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

file_path = 'market-price.csv'
bitcoin_df = pd.read_csv(file_path, names = ['day','price'])

print(bitcoin_df.shape)
print(bitcoin_df.info())
bitcoin_df.tail()

 

2) to_datetime으로 day 피처를 시계열 피처로 변환

bitcoin_df['day'] = pd.to_datetime(bitcoin_df['day'])

# day 데이터프레임의 index로 설정
bitcoin_df.index = bitcoin_df['day']
bitcoin_df.set_index('day', inplace=True)
bitcoin_df.head()
bitcoin_df.plot()
plt.show()

 

3) ARIMA 모델

from statsmodels.tsa.arima_model import ARIMA
import statsmodels.api as sm
# (AR=2, 차분=1, MA=2) 파라미터로 ARIMA 모델을 학습
model = ARIMA(bitcoin_df.price.values, order=(2,1,2))
model_fit = model.fit(trend='c', full_output=True, disp=True)
print(model_fit.summary())

 

4) 모델의 성능 & 예측 결과 시각화

# 학습 데이터에 대한 예측 결과 (첫번째 그래프)
fig = model_fit.plot_predict()
# 잔차의 변동을 시각화 (두번째 그래프)
residuals = pd.DataFrame(model_fit.resid)
residuals.plot()

 

'Programming > Python' 카테고리의 다른 글

Python 8주차 - 1  (0) 2020.08.05
Python 7주차 - 2  (0) 2020.08.03
Python 7주차 - 1  (0) 2020.07.29
Python 6주차 - 2  (0) 2020.07.26
Python 6주차 - 1  (0) 2020.07.26
Comments