728x90
Chapter03 시계열의 탐색적 자료 분석¶
경로 지정¶
In [1]:
from google.colab import drive
drive.mount('/content/drive')
Mounted at /content/drive
In [2]:
%cd /content/drive/MyDrive/KHUDA/KHUDA_Chap03/
/content/drive/MyDrive/KHUDA/KHUDA_Chap03
필요한 라이브러리 불러오기¶
In [3]:
import rpy2
%load_ext rpy2.ipython
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import statsmodels.graphics.tsaplots as sgt
import seaborn as sns
from pylab import rcParams
from statsmodels.graphics.tsaplots import month_plot
from mpl_toolkits.mplot3d import Axes3D
/usr/local/lib/python3.7/dist-packages/statsmodels/tools/_testing.py:19: FutureWarning: pandas.util.testing is deprecated. Use the functions in the public API at pandas.testing instead.
import pandas.util.testing as tm
데이터 셋 설명¶
- EuStockMarkets
- 1991년부터 1998년까지 유럽 4대 주요 주가 지수 일일 종가 기록
3.1 친숙한 방법¶
- 새로운 데이터를 다룰 때 기존의 질문
- 긴밀한 상관 관계를 가지는 열이 있나요?
- 관심 대상 변수의 전체 평균과 분산은 무엇인가요?
- 시간을 고려한 질문
- 분석값의 범위가 무엇인가요?
- 다른 논리적 단위나 기간에 따라 값이 달라지나요?
- 데이터가 일관성을 갖고 균등하게 측정됐나요?
- 아니면 시간이 흐르면서 측정이나 동작 방식에 변화가 있었나요?
- 궁금증을 해결할 수 있는 방법
- 히스토그램, 산점도, 요약 통계 + 시간축
3.1.1 도표 그리기¶
In [4]:
# R
%%R
# 데이터 셋 불러오고, 동시에 상위 5개 행 출력
head(EuStockMarkets)
DAX SMI CAC FTSE
[1,] 1628.75 1678.1 1772.8 2443.6
[2,] 1613.63 1688.5 1750.5 2460.2
[3,] 1606.51 1678.6 1718.0 2448.2
[4,] 1621.04 1684.1 1708.1 2470.4
[5,] 1618.16 1686.6 1723.1 2484.7
[6,] 1610.61 1671.6 1714.3 2466.8
In [5]:
# Python
# 데이터셋 불러오기
EuStockMarkets = pd.read_csv('dataset/dataset-62794.csv')
EuStockMarkets
Out[5]:
DAX | SMI | CAC | FTSE | |
---|---|---|---|---|
0 | 1628.75 | 1678.1 | 1772.8 | 2443.6 |
1 | 1613.63 | 1688.5 | 1750.5 | 2460.2 |
2 | 1606.51 | 1678.6 | 1718.0 | 2448.2 |
3 | 1621.04 | 1684.1 | 1708.1 | 2470.4 |
4 | 1618.16 | 1686.6 | 1723.1 | 2484.7 |
... | ... | ... | ... | ... |
1855 | 5460.43 | 7721.3 | 3939.5 | 5587.6 |
1856 | 5285.78 | 7447.9 | 3846.0 | 5432.8 |
1857 | 5386.94 | 7607.5 | 3945.7 | 5462.2 |
1858 | 5355.03 | 7552.6 | 3951.7 | 5399.5 |
1859 | 5473.72 | 7676.3 | 3995.0 | 5455.0 |
1860 rows × 4 columns
In [6]:
# Python
# 상위 5개 행 출력
EuStockMarkets.head()
Out[6]:
DAX | SMI | CAC | FTSE | |
---|---|---|---|---|
0 | 1628.75 | 1678.1 | 1772.8 | 2443.6 |
1 | 1613.63 | 1688.5 | 1750.5 | 2460.2 |
2 | 1606.51 | 1678.6 | 1718.0 | 2448.2 |
3 | 1621.04 | 1684.1 | 1708.1 | 2470.4 |
4 | 1618.16 | 1686.6 | 1723.1 | 2484.7 |
In [7]:
# Python
# 데이터 정보 살펴보기(1)
EuStockMarkets.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1860 entries, 0 to 1859
Data columns (total 4 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 DAX 1860 non-null float64
1 SMI 1860 non-null float64
2 CAC 1860 non-null float64
3 FTSE 1860 non-null float64
dtypes: float64(4)
memory usage: 58.2 KB
상세 설명
- Column: 열 이름
- Non-Null Count: NULL이 아닌 행 개수
- Dtype: 데이터 타입
In [8]:
# Python
# 데이터 정보 살펴보기(2)
EuStockMarkets.describe()
Out[8]:
DAX | SMI | CAC | FTSE | |
---|---|---|---|---|
count | 1860.000000 | 1860.000000 | 1860.000000 | 1860.000000 |
mean | 2530.656882 | 3376.223710 | 2227.828495 | 3565.643172 |
std | 1084.792740 | 1663.026465 | 580.314198 | 976.715540 |
min | 1402.340000 | 1587.400000 | 1611.000000 | 2281.000000 |
25% | 1744.102500 | 2165.625000 | 1875.150000 | 2843.150000 |
50% | 2140.565000 | 2796.350000 | 1992.300000 | 3246.600000 |
75% | 2722.367500 | 3812.425000 | 2274.350000 | 3993.575000 |
max | 6186.090000 | 8412.000000 | 4388.500000 | 6179.000000 |
상세 설명
- count: 개수
- mean: 평균
- std: 표준편차
- min: 최솟값
- 25%: 오름차순 정렬 후, 1/4 지점 값
- 50%: 오름차순 정렬 후, 2/4 지점 값
- 75%: 오름차순 정렬 후, 3/4 지점 값
- max: 최댓값
In [9]:
# R
%%R
# 그래프 그리기
plot(EuStockMarkets)
In [10]:
# Python
# 그래프 그리기
EuStockMarkets.plot()
Out[10]:
<matplotlib.axes._subplots.AxesSubplot at 0x7faa7af9ce50>
In [11]:
# Python
# 그래프 그리기 (4행 1열 1번째)
plt.subplot(4, 1, 1)
plt.plot(EuStockMarkets['DAX'])
plt.ylabel('DAX')
# 그래프 그리기 (4행 1열 2번째)
plt.subplot(4, 1, 2)
plt.plot(EuStockMarkets['SMI'])
plt.ylabel('SMI')
# 그래프 그리기 (4행 1열 3번째)
plt.subplot(4, 1, 3)
plt.plot(EuStockMarkets['CAC'])
plt.ylabel('CAC')
# 그래프 그리기 (4행 1열 4번째)
plt.subplot(4, 1, 4)
plt.plot(EuStockMarkets['FTSE'])
plt.ylabel('FTSE')
Out[11]:
Text(0, 0.5, 'FTSE')
상세 설명
3.1.2 히스토그램¶
- 히스토그램 (Histogram)
- 도수분포표를 그래프로 나타낸 것
- 가로축: 계급
- 세로축: 도수 (횟수나 개수 등)
- 히스토그램 + 시간축
- 시간상 인접한 데이터 간의 차이를 구할 수 있다.
- 차이에 대한 히스토그램을 측정할 수 있다.
- 예상치 못한 관점에서 데이터를 바라볼 수 있다.
In [12]:
# R
%%R
# 어떠한 변화도 가하지 않은 히스토그램
hist( EuStockMarkets[, 'SMI'], 30)
# 차분에 대한 히스토그램
hist(diff(EuStockMarkets[, 'SMI'], 30))
In [13]:
# Python
# 어떠한 변화도 가하지 않은 히스토그램
plt.hist(x = EuStockMarkets['SMI'], bins = 30)
plt.grid()
plt.show()
# 차분에 대한 히스토그램
# 추세를 제거하기 위해 시간상 인접한 데이터의 차이를 구하면, 정규분포를 따르는 형태로 변화함.
plt.hist(x = EuStockMarkets['SMI'].diff(), bins = 30)
plt.grid()
plt.show()
3.1.3 산점도¶
- 산점도 (Scatter plot)
- 두 변수의 상관관계를 점으로 나타낸 것
- 가로축: 계급
- 세로축: 도수 (횟수나 개수 등)
- 산점도 + 시간축
- 특정 시간에 대한 두 변수의 관계를 결정할 수 있다.
- 두 변수의 시간에 따른 각각의 변수 값 변동이 갖는 연관성을 결정할 수 있다.
In [14]:
# R
%%R
# 시간에 따른 서로 다른 두 주식의 가치
plot( EuStockMarkets[, 'SMI'], EuStockMarkets[, 'DAX'])
# 차분에 대한 두 주식의 일일 가치 변동
plot(diff(EuStockMarkets[, 'SMI']), diff(EuStockMarkets[, 'DAX']))
In [15]:
#Python
# 시간에 따른 서로 다른 두 주식의 가치
plt.scatter(x = EuStockMarkets['SMI'], y = EuStockMarkets['DAX'])
plt.grid()
plt.show()
# 차분에 대한 두 주식의 일일 가치 변동
plt.scatter(x = EuStockMarkets['SMI'].diff(), y = EuStockMarkets['DAX'].diff())
plt.grid()
plt.show()
In [16]:
# R
%%R
# lag 함수를 적용한 산점도
# lag : 시간을 미루는 함수
plot(lag(diff(EuStockMarkets[, 'SMI']), 1),
diff(EuStockMarkets[, 'DAX']))
In [17]:
# Python
# shift(=lag) 함수 적용한 산점도
# 두 주가의 상관관계가 사라짐
# 즉 한 변수로 다른 변수를 예측하지 못함
plt.scatter(x = EuStockMarkets['SMI'].diff().shift(1),
y = EuStockMarkets['DAX'].diff())
plt.grid()
plt.show()
3.2 시계열에 특화된 탐색법¶
시계열을 분류할 때 사용하는 개념¶
- 정상성 (stationarity)
- 시계열이 정상성이 된다는 의미
- 정상성에 대한 통계적 검사
- 안정성
- 자체상관 (self correlation)
- 시계열 그 자체로 연관성이 있다는 의미
- 연관성이 시계열의 내재된 역동성에 대해 보여주고자 하는 것
- 내부적인 역학 존재 결정
- 허위상관 (squrious correlation)
- 상관관계가 허위가 된다는 의미
- 허위 상관을 마주칠 만한 상황
- 인과 관계가 아니라는 것
시계열을 분류할 때 사용하는 기법¶
- 롤링 윈도와 확장 윈도 함수
- 자체 상관 함수
- 자기 상관 함수
- 편자기 상관 함수
3.2.1 정상성 이해하기¶
- 정상성 (stationarity)
- 시스템의 안정적인 상태
- 정상 시계열은 시간이 경과해도 안정적인 통계적 속성을 가짐
- 평균, 분산이 시간에 따라 일정
- 정상이 아닌 경우
- 평균값이 일정하게 유지되지 않음
- 분산이 일정하게 유지되지 않음
- 강한 계절성을 보여줌
- 무엇이 정상 시계열 일까요?
- (a) 200 거래일 동안의 구글 주식 가격
- (b) 200 거래일 동안의 구글 주식 가격의 일일 변동
- (c) 미국의 연간 파업 수
- (d) 미국에서 판매되는 새로운 단독 주택의 월별 판매액
- (e) 미국에서 계란 12개의 연간 가격(고정 달러)
- (f) 호주 빅토리아 주에서 매월 도살한 돼지의 전체 수
- (g) 캐나다 북서부의 맥킨지 강 지역에서 연간 포획된 스라소니의 전체 수
- (h) 호주 월별 맥주 생산량
- (i) 호주 월별 전기 생산량
정답
- 정상 시계열 : (b), (g)
- 정상이 아닌 시계열
- 계절성 : (d), (h), (i)
- 추세 : (a), (c), (e), (f), (i)
- 정상 시계열 변환
- 변동폭이 일정하지 않은 경우
- 로그 변환
- 추세, 계절성이 존재하는 경우
- 차분
- 단, 1차 차분으로 정상성을 띄지 않으면 차분 반복
- 최대 3번까지만 권장
- 변동폭이 일정하지 않은 경우
3.2.2 윈도 함수 적용¶
- 롤링 윈도
- 이동 평균 및 계열의 선형 함수와 관련된 다른 계산 용이
In [18]:
# R
%%R
# rnorm 함수로 정규분포를 따르는 난수를 100개 추출
x <- rnorm(n=100, mean=0, sd=10) + 1:100
# rep 함수로 1/n 값을 n번 반복하는 배열을 만드는 함수를 만듭니다.
mn <- function(n) rep(1/n, n)
# 그래프 그리기
plot(x, type = 'l', lwd = 1)
# 기본 R의 filter 함수로 롤링 평균을 계산합니다.
# 각각 5개, 50개 단위로 롤링합니다.
lines(filter(x, mn(5)), col = 2, lwd = 3, lty = 2)
lines(filter(x, mn(50)), col = 3, lwd = 3, lty = 2)
In [19]:
# Python
# 정규분포를 따르는 난수 100개 추출
mu = 0
sd = 10
size = 100
np.random.seed(100)
n = np.random.normal(mu, sd, size)
# 데이터 프레임 만들기
data = pd.DataFrame(n)
# 그래프 그리기
plt.plot(n)
plt.plot(data.rolling(window=5).mean())
plt.plot(data.rolling(window=50).mean())
Out[19]:
[<matplotlib.lines.Line2D at 0x7faa7a7290d0>]
- 확장 윈도
In [20]:
# R
%%R
# 그래프 그리기
plot(x, type = 'l', lwd = 1)
lines(cummax(x), col = 2, lwd = 3, lty = 2)
lines(cumsum(x)/1:length(x), col = 3, lwd = 3, lty = 3)
3.2.3 자체상관의 파악과 이해¶
- 자기상관 기능
- 관측치 사이의 유사성을 이들의 시차에 대한 함수로써 구하는 것
- 계열 상관
- 자기 상관 함수 (ACF) 특징
- ACF의 주기성 = 원래 과정 주기성
- 주기 함수들의 합의 자기상관 = 각 개별 함수에 대한 자기 상관의 합
- 시차 = 0 인 경우, 모든 시계열의 자기 상관 계수 = 1
- ACF 는 양과 음의 시차에 관해서 대칭
- 0이 아닌 유효한 ACF 추정을 결정하는 통계적 규칙은 +/- 1.96 x sqrt(n) 의 임계영역 사용하는 것
In [21]:
# R
%%R
# sin 그래프와 ACF 그래프
x <- 1:100
y <- sin(x * pi/3)
plot(y, type = 'b')
acf(y)
In [22]:
# Python
# sin 함수 만들기
x = np.linspace(0, 100)
y = np.sin(x * np.pi / 3)
# sin 그래프와 ACF 그래프 그리기
plt.plot(y)
sgt.plot_acf(y)
plt.show()
- 편자기상관함수
- 자신에 대한 그 시차의 편상관
- 두 시점 사이에 존재하는 모든 정보 고려
- 편자기 상관 함수 (PACF) 특징
- 어떤 데이터가 유용한 정보를 가지고, 어떤 데이터가 단기간의 고조파인지 보여줄 수 있다.
In [23]:
# R
%%R
# sin 그래프와 PACF 그래프
y <- sin(x * pi / 3)
plot(y[1:30], type = 'b')
pacf(y)
In [24]:
# Python
# sin 함수 만들기
y = np.sin(x * np.pi / 3)
# sin 그래프와 PACF 그래프 그리기
plt.plot(y)
sgt.plot_pacf(y)
plt.show()
/usr/local/lib/python3.7/dist-packages/statsmodels/regression/linear_model.py:1358: RuntimeWarning: invalid value encountered in sqrt
return rho, np.sqrt(sigmasq)
- 자기 상관 함수 (ACF) vs 편자기 상관 함수 (PACF) - 노이즈가 없는 경우
- 자기 상관 함수 (ACF) vs 편자기 상관 함수 (PACF) - 노이즈가 있는 경우
3.2.4 허위상관¶
- 허위 상관을 나타내는 시계열의 특징
- 근본적인 추세를 가진 데이터
- 계절성을 가진 데이터
- 시간이 지나면서 변한 데이터의 수준이나 경사의 이동
- 누적 합계
3.3 유용한 시각화¶
3.3.1 1차원 시각화¶
- 개별 변수의 종합적인 시각 분포도를 이해하기 위함
In [25]:
# Python
# 가로 막대 그래프
df = pd.DataFrame(np.random.randn(4,4))
df.plot(kind='barh')
Out[25]:
<matplotlib.axes._subplots.AxesSubplot at 0x7faa77da2e90>
3.3.2 2차원 시각화¶
- 시간에 따른 여러 측정치의 전형적인 궤적을 이해하기 위함
- 오랜 세월에 걸친 측정이나 동일한 현상을 측정한 여러 시계열
In [26]:
# Python
# lineplot
flights = sns.load_dataset("flights")
sns.lineplot(data=flights,
x='month',
y='passengers',
hue='year',
legend='full')
plt.title('Seasonal plot')
plt.legend(bbox_to_anchor=(1.05, 1), loc=2);
In [27]:
# Python
# plt.plot()
AirPassengers = pd.read_csv('dataset/dataset-58057.csv')
plt.plot(np.arange(0, 12), np.mat(AirPassengers['AirPassengers'].values.reshape(12,12)),
linestyle = '-', linewidth = 2.5)
plt.show()
In [28]:
# Python
# month_plot
df = pd.read_csv('dataset/shampoo.csv')
date = pd.date_range(start='1/1/2001', end='12/31/2003', freq='M')
df['Time_Stamp'] = pd.DataFrame(date,columns=['Date'])
df = df.set_index('Time_Stamp')
df_final = df.drop(['Month'], axis=1)
plt.rc('xtick',labelsize=15)
plt.rc('ytick',labelsize=15)
month_plot(df_final['Sales'],ylabel='Sales')
plt.grid();
In [29]:
# Python
# Heatmap
arr = np.random.standard_normal((30, 40))
plt.matshow(arr)
plt.colorbar(shrink=0.8, aspect=10)
plt.clim(-1.0, 1.0)
plt.show()
In [30]:
# Python
# hexbin
mean, cov = [0, 1], [(1, .5), (.5, 1)]
x, y = np.random.multivariate_normal(mean, cov, 1000).T
with sns.axes_style("white"):
sns.jointplot(x=x, y=y, kind="hex", color="k")
3.3.3 3차원 시각화¶
- 두 개의 차원을 차지하는 시간, 또는 차원을 전혀 차지하지 않지만 내재된 시간
In [31]:
# Python
# 3D scatter plot
n = 100
xmin, xmax, ymin, ymax, zmin, zmax = 0, 20, 0, 20, 0, 50
cmin, cmax = 0, 2
xs = np.array([(xmax - xmin) * np.random.random_sample() + xmin for i in range(n)])
ys = np.array([(ymax - ymin) * np.random.random_sample() + ymin for i in range(n)])
zs = np.array([(zmax - zmin) * np.random.random_sample() + zmin for i in range(n)])
color = np.array([(cmax - cmin) * np.random.random_sample() + cmin for i in range(n)])
fig = plt.figure(figsize=(6, 6))
ax = fig.add_subplot(111, projection='3d')
ax.scatter(xs, ys, zs, c=color, marker='o', s=15, cmap='Greens')
plt.show()
In [32]:
# Python
# 3d contour plot
x = np.linspace(-10, 10, 100)
y = np.linspace(-15, 15, 100)
X, Y = np.meshgrid(x, y)
Z = np.sin(X) + np.cos(Y)
fig = plt.figure(figsize=(9, 6))
ax = plt.axes(projection = '3d')
ax.contour3D(X, Y, Z, 100, cmap = 'viridis')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
/usr/local/lib/python3.7/dist-packages/mpl_toolkits/mplot3d/art3d.py:304: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray.
self._segments3d = np.asanyarray(segments)
Out[32]:
Text(0.5, 0, 'z')
In [1]:
from IPython.core.display import display, HTML
display(HTML("<style>.container {width:90% !important;}</style>"))
위 내용은 경희대학교 교내 동아리 KHUDA 에서 공부한 내용을 바탕으로 작성했습니다. 😜
공부한 책은 아래의 링크를 참고해주세요 !
'AI > Machine Learning' 카테고리의 다른 글
[Practical Time Series Analysis (실전 시계열 분석)] Chapter 06 시계열의 통계 모델 (0) | 2022.03.23 |
---|---|
[Practical Time Series Analysis (실전 시계열 분석)] Chapter 05 시간 데이터 저장 (0) | 2022.03.23 |
[Practical Time Series Analysis (실전 시계열 분석)] Chapter 04 시계열 데이터의 시뮬레이션 (0) | 2022.03.22 |
[DACON] 문화 | 영화 관객수 예측 모델 개발 (0) | 2022.03.05 |
[DACON] 영화 데이터를 활용한 데이터 분석1 (EDA) (0) | 2022.01.30 |