【python資料探勘課程】二十三.時間序列金融資料預測及Pandas庫詳解
這是《Python資料探勘課程》系列文章,也是我上課內容及書籍中的一個案例。本文主要講述時間序列演算法原理,Pandas擴充套件包基本用法以及Python呼叫statsmodels庫的時間序列演算法。由於作者數學比較薄弱,自己也還在學習,所以原理推導部分本文只簡單敘述,同時參考了《Python金融大資料分析 ·Yves Hilpisch》書籍和其他大神的文章。
本篇文章為基礎性文章,希望對你有所幫助,提供些思路,也是自己教學的內容。如果文章中存在錯誤或不足之處,還請海涵。同時,推薦大家閱讀我以前的文章瞭解其他知識。
前文參考:
【Python資料探勘課程】一.安裝Python及爬蟲入門介紹
【Python資料探勘課程】二.Kmeans聚類資料分析及Anaconda介紹
【Python資料探勘課程】三.Kmeans聚類程式碼實現、作業及優化
【Python資料探勘課程】四.決策樹DTC資料分析及鳶尾資料集分析
【Python資料探勘課程】五.線性迴歸知識及預測糖尿病例項
【Python資料探勘課程】六.Numpy、Pandas和Matplotlib包基礎知識
【Python資料探勘課程】七.PCA降維操作及subplot子圖繪製
【Python資料探勘課程】八.關聯規則挖掘及Apriori實現購物推薦
【Python資料探勘課程】九.迴歸模型LinearRegression簡單分析氧化物資料
【python資料探勘課程】十.Pandas、Matplotlib、PCA繪圖實用程式碼補充
【python資料探勘課程】十一.Pandas、Matplotlib結合SQL語句視覺化分析
【python資料探勘課程】十二.Pandas、Matplotlib結合SQL語句對比圖分析
【python資料探勘課程】十三.WordCloud詞雲配置過程及詞頻分析
【python資料探勘課程】十四.Scipy呼叫curve_fit實現曲線擬合
【python資料探勘課程】十五.Matplotlib呼叫imshow()函式繪製熱圖
【python資料探勘課程】十六.邏輯迴歸LogisticRegression分析鳶尾花資料
【python資料探勘課程】十七.社交網路Networkx庫分析人物關係(初識篇)
【python資料探勘課程】十八.線性迴歸及多項式迴歸分析四個案例分享
【python資料探勘課程】十九.鳶尾花資料集視覺化、線性迴歸、決策樹花樣分析
【python資料探勘課程】二十.KNN最近鄰分類演算法分析詳解及平衡秤TXT資料集讀取
【python資料探勘課程】二十一.樸素貝葉斯分類器詳解及中文文字輿情分析
【python資料探勘課程】二十二.Basemap地圖包安裝入門及基礎知識講解
一. 時間序列基礎知識
社會經濟現象總是隨著時間的推移而變遷,呈現動態性。一個或一組變數x(t)進行觀測,將在一系列時刻t1、t2、...、tn得到離散數字組成的序列集合,稱之為時間序列。通過時間序列演算法,我們對事物進行動態的研究。
時間序列表示按時間先後順序排列的數列,通常X軸為時間要素,Y軸為資料要素,比如1986-2000年的人均GDP為y1、y2、...、yn,再如下圖所示太陽黑子運動規律。
指標通常包括時期指標(年度、月度)和時點指標(時刻)。時間序列分為以下三類:
1.隨機性時間序列:各指標變動受隨機因素影響
2.平穩時間序列:基本穩定在某個水平附近波動
3.非平穩時間序列:存在某種規律性變動,比如趨勢性、季節性
時間序列常用的特徵統計量如下所示:(參考:百度文庫)
二. 金融時間序列-Pandas庫
該部分是作者學習《Python金融大資料分析》書籍第6章的內容,僅供大家學習:
金融學中最重要的資料型別之一是金融時間序列,以日期時間作為索引的資料,例如股票、GDP、匯率等。Python處理時間序列主要使用Pandas庫,其DataFrame和Series等基本類靈感來源於R語言。Pandas庫允許從Web上讀取資料,比如雅虎財經、谷歌財經等,也可以讀取csv檔案(逗號分割)。下面詳細介紹Pandas庫的用法:
1.DataFrame類
首先我們通過DataFrame定義資料,包括資料、標籤和索引三部分,其中資料包括列表、元組、字典、ndarray等型別,索引包括數值、字串和時間等。示例程式碼如下:
import pandas as pd
import numpy as np
df = pd.DataFrame([10,20,30,40],columns=['num'],
index=['a','b','c','d'])
print df.index
print df.columns
print df.ix['c']
print df.ix[df.index[1:3]]
print df.sum()
print df.apply(lambda x:x**2)
輸出結果如下所示,包括輸出索引、標籤值,獲取“c”對應數值等,通過df.sum()對資料進行求和、df.mean()求平均值、df.apply(lambda x:x**2)實現數值平方計算。
Index([u'a', u'b', u'c', u'd'], dtype='object')
Index([u'num'], dtype='object')
num 30
Name: c, dtype: int64
num
b 20
c 30
num 100
dtype: int64
num
a 100
b 400
c 900
d 1600
DataFrame物件總體上比較方便、高效,相比ndarray物件更專業化。下面程式碼是進維度擴增,增加了一個float型別。
df['floats']=(1.5, 2.5, 3.5, 4.5)
print df
輸出結果如下所示:
num floats
a 10 1.5
b 20 2.5
c 30 3.5
d 40 4.5
接下來再增加一個維度,通過索引進行對應。程式碼如下:
print df['floats']
df['names'] = pd.DataFrame(["Ya","Ga","Ha","Da"],
index=['d','a','b','c'])
print df
輸出結果如下:
a 1.5
b 2.5
c 3.5
d 4.5
Name: floats, dtype: float64
num floats names
a 10 1.5 Ga
b 20 2.5 Ha
c 30 3.5 Da
d 40 4.5 Ya
2.DatetimeIndex類
接下來我們講解DatetimeIndex類,通過它定義時間。首先呼叫numpy.random函式 生成一個9*4的標準正態分佈偽隨機數,然後定義列標籤,程式碼如下:
# -*- coding: cp936 -*-
import pandas as pd
import numpy as np
a = np.random.standard_normal((9,4))
print a.round(6) #6位小數
#print a
df = pd.DataFrame(a)
df.columns = ["No1", "No2", "No3", "No4"]
print df
輸出結果如下,如果需要進行訪問則呼叫df['No2'][3]實現。
No1 No2 No3 No4
0 -0.320854 -0.625805 -0.421955 0.389512
1 0.370532 -1.221835 0.010364 1.393511
2 -0.229514 -0.477147 0.128166 -0.619752
3 -0.595702 1.799746 0.330161 1.669275
4 -0.692837 -0.208061 0.576877 1.007649
5 -1.021873 -0.358089 -0.967342 0.894291
6 0.490543 0.261311 -0.366073 0.435141
7 -0.566304 1.673199 -1.733883 -0.292425
8 -0.968336 0.648280 -0.489114 -2.275192
為高效處理金融事件序列資料,必須很好地處理時間索引,接下來通過date_range()函式對9行資料對應上時間,從2015-1-1開始,程式碼如下:dates = pd.date_range('2015-1-1',periods=9,freq='M')
print dates
df.index = dates
print df
輸出結果如下所示,可以看到每行資料對應一個年份,其中freq參數列示頻率引數,常見的值包括:B-交易日 D-日 W-每週 M-每月底 MS-月初 BM-每月最後一個交易日 A-每年底 H-每小時
DatetimeIndex(['2015-01-31', '2015-02-28', '2015-03-31', '2015-04-30',
'2015-05-31', '2015-06-30', '2015-07-31', '2015-08-31',
'2015-09-30'],
dtype='datetime64[ns]', freq='M')
No1 No2 No3 No4
2015-01-31 -0.320854 -0.625805 -0.421955 0.389512
2015-02-28 0.370532 -1.221835 0.010364 1.393511
2015-03-31 -0.229514 -0.477147 0.128166 -0.619752
2015-04-30 -0.595702 1.799746 0.330161 1.669275
2015-05-31 -0.692837 -0.208061 0.576877 1.007649
2015-06-30 -1.021873 -0.358089 -0.967342 0.894291
2015-07-31 0.490543 0.261311 -0.366073 0.435141
2015-08-31 -0.566304 1.673199 -1.733883 -0.292425
2015-09-30 -0.968336 0.648280 -0.489114 -2.275192
3.繪圖操作
接著我們進行繪圖操作,Pandas提供了Matplotlib的一個封裝器,專門為Dataframe物件設計。程式碼如下:
# -*- coding: cp936 -*-
import pandas as pd
import numpy as np
a = np.random.standard_normal((9,4))
df = pd.DataFrame(a)
df.columns = ["No1", "No2", "No3", "No4"]
dates = pd.date_range('2015-1-1',periods=9,freq='M')
df.index = dates
print df.cumsum()
df.plot(lw=2.0)
主要呼叫plot方法,引數包括x、y、title、grid(表格線)、ax、legend、kind(圖形型別,kde/line/bar/barh)、logx、yticks(刻度)、xlim(界限)、rot(旋轉度)等,繪製圖形如下所示:
4.Series類
從DataFrame物件中選擇一列時,則得到一個Series物件,程式碼如下:
# -*- coding: cp936 -*-
import pandas as pd
import numpy as np
a = np.random.standard_normal((9,4))
df = pd.DataFrame(a)
df.columns = ["No1", "No2", "No3", "No4"]
dates = pd.date_range('2015-1-1',periods=9,freq='M')
df.index = dates
print df['No1']
import matplotlib.pyplot as plt
df['No1'].cumsum().plot(style="r",lw=2.)
plt.xlabel('date')
plt.ylabel('value')
輸出結果如下:
2015-01-31 -0.349526
2015-02-28 -0.511097
2015-03-31 0.987965
2015-04-30 -1.045693
2015-05-31 0.237728
2015-06-30 -0.857229
2015-07-31 0.916528
2015-08-31 1.240449
2015-09-30 -0.687802
Freq: M, Name: No1, dtype: float64
僅僅獲取了"No1"資料並繪製如下圖所示圖形:
5.Groupby操作
Pandas具有靈活分組功能,工作方式類似於SQL中分組和Excel透視表,為進行分組,我們新增一組索引對應季度表,程式碼如下:
# -*- coding: cp936 -*-
import pandas as pd
import numpy as np
a = np.random.standard_normal((9,4))
df = pd.DataFrame(a)
df.columns = ["No1", "No2", "No3", "No4"]
dates = pd.date_range('2015-1-1',periods=9,freq='M')
df.index = dates
df['Quarter'] = ['Q1','Q1','Q1','Q2','Q2','Q2','Q3','Q3','Q3']
print df
groups = df.groupby('Quarter')
print groups.sum()
print groups.mean()
print groups.max()
print groups.size()
輸出結果如下所示:
No1 No2 No3 No4 Quarter
2015-01-31 0.674688 -0.201858 -0.399297 -0.706358 Q1
2015-02-28 -0.480280 -1.091486 0.667307 -0.039749 Q1
2015-03-31 -0.427795 -0.362502 -0.885939 -1.580051 Q1
2015-04-30 -0.493025 -0.297891 0.748269 -0.128684 Q2
2015-05-31 -1.217889 0.474075 0.146949 0.840250 Q2
2015-06-30 -0.092169 0.541781 0.231801 0.647952 Q2
2015-07-31 0.364487 1.682923 1.561643 0.391411 Q3
2015-08-31 0.353252 -1.086157 0.849758 -0.435598 Q3
2015-09-30 0.805192 -0.434796 0.842751 -0.657201 Q3
No1 No2 No3 No4
Quarter
Q1 -0.233388 -1.655847 -0.617930 -2.326157
Q2 -1.803084 0.717965 1.127018 1.359518
Q3 1.522931 0.161970 3.254152 -0.701388
No1 No2 No3 No4
Quarter
Q1 -0.077796 -0.551949 -0.205977 -0.775386
Q2 -0.601028 0.239322 0.375673 0.453173
Q3 0.507644 0.053990 1.084717 -0.233796
No1 No2 No3 No4
Quarter
Q1 0.674688 -0.201858 0.667307 -0.039749
Q2 -0.092169 0.541781 0.748269 0.840250
Q3 0.805192 1.682923 1.561643 0.391411
Quarter
Q1 3
Q2 3
Q3 3
dtype: int64
三. 時間序列演算法-ARIMA
作者本來想通過下面程式碼匯入雅虎財經資料,但是沒有成功,最終選擇自定義資料進行ARIMA演算法實驗。
時間序列是通過曲線擬合和引數估計來建立 數學模型的理論方法,基本步驟如下:
(1).獲取被觀測系統時間序列資料;
(2).對資料繪圖觀測是否為平穩時間序列、非平穩d階差分;
(3).得平穩時間序列,求其自相關係數ACF和偏自相關係數PACF,通過自相關和偏相關圖分析,得到最佳階層p和結束q;
(4).由d、q、p得到ARIMA模型,然後進行檢驗。
參考:
Python_Statsmodels包_時間序列分析_ARIMA模型
Python時間序列分析 - 部落格園
1.獲取資料匯入庫
# -*- coding: utf-8 -*-
import pandas as pd
import numpy as np
dta=[10930,10318,10595,10972,7706,6756,9092,10551,9722,10913,11151,8186,6422,
6337,11649,11652,10310,12043,7937,6476,9662,9570,9981,9331,9449,6773,6304,9355,
10477,10148,10395,11261,8713,7299,10424,10795,11069,11602,11427,9095,7707,10767,
12136,12812,12006,12528,10329,7818,11719,11683,12603,11495,13670,11337,10232,
13261,13230,15535,16837,19598,14823,11622,19391,18177,19994,14723,15694,13248,
9543,12872,13101,15053,12619,13749,10228,9725,14729,12518,14564,15085,14722,
11999,9390,13481,14795,15845,15271,14686,11054,10395]
dta = np.array(dta,dtype=np.float) #這裡要轉下資料型別,不然執行會報錯
df = pd.Series(dta)
print df
dates = pd.date_range('2001', periods=90, freq='A')
df.index = dates
print df
df.plot(figsize=(12,8))
程式碼從2001年到2090年共有90組資料,然後按照年份進行時間序列統計(freq='A'年份),輸出結果如下所示:2001-12-31 10930.0
2002-12-31 10318.0
2003-12-31 10595.0
2004-12-31 10972.0
2005-12-31 7706.0
....
2086-12-31 15845.0
2087-12-31 15271.0
2088-12-31 14686.0
2089-12-31 11054.0
2090-12-31 10395.0
Freq: A-DEC, Length: 90, dtype: float64
繪製圖形如下:
2.時間序列差分d
ARIMA模型要求是平穩型,如果是非平穩型的時間序列需要先做時間序列的差分,得到一個平穩的時間序列。如果時間序列做d次差分才能得到一個平穩序列,則可使用ARIMA(p,d,q)模型,其中d表示差分次數。程式碼如下:
主要呼叫df.diff(1)實現一階差分的效果,此資料一階和二階差分的結果類似,均值和方差基本問題,這裡的差分d值就取1。
# -*- coding: utf-8 -*-
import pandas as pd
import numpy as np
dta=[10930,10318,10595,10972,7706,6756,9092,10551,9722,10913,11151,8186,6422,
6337,11649,11652,10310,12043,7937,6476,9662,9570,9981,9331,9449,6773,6304,9355,
10477,10148,10395,11261,8713,7299,10424,10795,11069,11602,11427,9095,7707,10767,
12136,12812,12006,12528,10329,7818,11719,11683,12603,11495,13670,11337,10232,
13261,13230,15535,16837,19598,14823,11622,19391,18177,19994,14723,15694,13248,
9543,12872,13101,15053,12619,13749,10228,9725,14729,12518,14564,15085,14722,
11999,9390,13481,14795,15845,15271,14686,11054,10395]
dta = np.array(dta,dtype=np.float) #這裡要轉下資料型別,不然執行會報錯
df = pd.Series(dta)
print df
dates = pd.date_range('2001', periods=90, freq='A')
df.index = dates
print df
df.plot(figsize=(12,8))
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(12,8))
ax1= fig.add_subplot(111)
diff1 = df.diff(1)
diff1.plot(ax=ax1)
得到的平穩圖形如下圖所示:
注意:差分推導過程作者還在學習中,包括q和p值的計算,如果學會了後面會補充,這裡主要是程式碼的講解。
3.合適的q和p值
得到一個平穩的時間序列後,需要選擇合適的ARIMA模型,即ARIMA模型中的p和q值。
注意:這裡需要呼叫"pip install statsmodels"安裝統計數學分析的包,有時您的版本過低會導致錯誤(尤其是Anaconda 2.7版本),則需要呼叫"pip install --upgrade statsmodels"升級包至0.8版本。
程式碼如下:
# -*- coding: utf-8 -*-
import pandas as pd
import numpy as np
dta=[10930,10318,10595,10972,7706,6756,9092,10551,9722,10913,11151,8186,6422,
6337,11649,11652,10310,12043,7937,6476,9662,9570,9981,9331,9449,6773,6304,9355,
10477,10148,10395,11261,8713,7299,10424,10795,11069,11602,11427,9095,7707,10767,
12136,12812,12006,12528,10329,7818,11719,11683,12603,11495,13670,11337,10232,
13261,13230,15535,16837,19598,14823,11622,19391,18177,19994,14723,15694,13248,
9543,12872,13101,15053,12619,13749,10228,9725,14729,12518,14564,15085,14722,
11999,9390,13481,14795,15845,15271,14686,11054,10395]
dta = np.array(dta,dtype=np.float) #這裡要轉下資料型別,不然執行會報錯
df = pd.Series(dta)
print df
dates = pd.date_range('2001', periods=90, freq='A')
df.index = dates
print df
df.plot(figsize=(12,8))
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(12,8))
ax1= fig.add_subplot(111)
diff1 = df.diff(1)
diff1.plot(ax=ax1)
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
f = plt.figure(facecolor='white')
ax1 = f.add_subplot(211)
plot_acf(df, lags=40, ax=ax1)
ax2 = f.add_subplot(212)
plot_pacf(df, lags=40, ax=ax2)
plt.show()
輸出結果如下所示,主要 呼叫plot_acf和plot_pacf函式。
注意:這裡根據上述自相關圖選擇引數,最終選擇ARIMA(7,1)模型或ARIMA(8,0)模型,作者也還在研究學習中,後面會補充知識,還請讀者原諒。最重要的是第四部分的預測,我認為它是時間序列預測的重點知識。
四. 時間序列預測分析
最後給出選擇ARIMA(8,0)模型對未來10年資料進行的程式碼。程式碼如下:
# -*- coding: utf-8 -*-
import pandas as pd
import numpy as np
dta=[10930,10318,10595,10972,7706,6756,9092,10551,9722,10913,11151,8186,6422,
6337,11649,11652,10310,12043,7937,6476,9662,9570,9981,9331,9449,6773,6304,9355,
10477,10148,10395,11261,8713,7299,10424,10795,11069,11602,11427,9095,7707,10767,
12136,12812,12006,12528,10329,7818,11719,11683,12603,11495,13670,11337,10232,
13261,13230,15535,16837,19598,14823,11622,19391,18177,19994,14723,15694,13248,
9543,12872,13101,15053,12619,13749,10228,9725,14729,12518,14564,15085,14722,
11999,9390,13481,14795,15845,15271,14686,11054,10395]
dta = np.array(dta,dtype=np.float)
df = pd.Series(dta)
print df
dates = pd.date_range('2001', periods=90, freq='A')
df.index = dates
print df
df.plot(figsize=(12,8))
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(12,8))
ax1= fig.add_subplot(111)
diff1 = df.diff(1)
diff1.plot(ax=ax1)
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
f = plt.figure(facecolor='white')
ax1 = f.add_subplot(211)
plot_acf(df, lags=40, ax=ax1)
ax2 = f.add_subplot(212)
plot_pacf(df, lags=40, ax=ax2)
plt.show()
#預測結果
import statsmodels.api as sm
arma_mod80 = sm.tsa.ARMA(df,(8,0)).fit()
print(arma_mod80.aic, arma_mod80.bic, arma_mod80.hqic)
pre = arma_mod80.predict('2090', '2100', dynamic=True)
print(pre)
fig, ax = plt.subplots(figsize=(12, 8))
ax = df.ix['2000':].plot(ax=ax)
fig = arma_mod80.plot_predict('2090', '2100', dynamic=True, ax=ax, plot_insample=False)
plt.show()
輸出相關ARIMA(8,0)係數和預測的2090-2100年結果如下所示:(1597.9359982097687, 1622.9340949130715, 1608.0167002177614)
2090-12-31 9542.908069
2091-12-31 12908.529213
2092-12-31 13982.046108
2093-12-31 14501.674565
2094-12-31 13894.459886
2095-12-31 13249.595991
2096-12-31 10960.986520
2097-12-31 10073.503381
2098-12-31 12684.834790
2099-12-31 13477.793055
2100-12-31 13616.117709
Freq: A-DEC, dtype: float64
輸出圖形如下所示,可以看到後面綠色部分為預測值,根據前面的波動規律近似得到。本篇文章為基礎性文章,希望對你有所幫助,提供些思路,如果文章中存在錯誤或不足之處,還請海涵。同時,推薦大家閱讀我以前的文章瞭解基礎知識,自己要學習的東西好多啊。
(By:Eastmount 2018-05-09 晚上11點 http://blog.csdn.net/eastmount/ )
相關文章
- 資料探勘-預測模型彙總模型
- 資料清洗與預處理:使用 Python Pandas 庫Python
- 時間序列化資料庫選型?時序資料庫的選擇?資料庫
- 萌新向Python資料分析及資料探勘 前言Python
- Oracle資料庫啟動過程及狀態詳解Oracle資料庫
- 從零寫一個時間序列資料庫資料庫
- 【python資料探勘課程】二十七.基於SVM分類器的紅酒資料分析Python
- 時間序列資料的預處理及基於ARIMA模型進行趨勢預測-大資料ML樣本集案例實戰模型大資料
- 資料探勘與預測分析(第2版)
- 資料探勘之產品預測任務
- python pandas庫讀取excel/csv中指定行或列資料詳解PythonExcel
- Pandas 資料分析——Merge 資料拼接圖文詳解
- 時間序列資料的處理
- 【python資料探勘課程】二十六.基於SnowNLP的豆瓣評論情感分析Python
- 將VAE用於時間序列:生成時間序列的合成資料
- Python - pandas 資料分析Python
- 時間序列預測:探索性資料分析和特徵工程的實用指南特徵工程
- 【python資料探勘課程】二十四.KMeans文字聚類分析互動百科語料Python聚類
- 《資料分析與資料探勘》--天津大學公開課
- 《資料探勘導論》實驗課——實驗四、資料探勘之KNN,Naive BayesKNNAI
- 資料探勘的過程有哪些
- 資料庫課程作業筆記資料庫筆記
- Python 資料處理庫 pandas 入門教程Python
- Python 資料處理庫 pandas 進階教程Python
- Pandas資料結構詳解 | 輕鬆玩轉Pandas(1)資料結構
- Python Pandas 時間序列雙軸折線圖Python
- 資料庫效能測試:sysbench用法詳解資料庫
- 資料庫課程作業筆記 - 編寫資料填充資料庫筆記
- Pandas 資料分析——超好用的 Groupby 詳解
- Pandas讀寫資料庫資料庫
- 【python資料探勘課程】二十五.Matplotlib繪製帶主題及聚類類標的散點圖Python聚類
- 時間序列知識圖譜-《利用Python進行資料分析》Python
- Python資料分析之pandasPython
- 使用MongoDB儲存時間序列資料 - DACMongoDB
- 人工智慧 (07) 時間序列資料分析人工智慧
- SQL Server 2016資料庫快照代理過程詳解SQLServer資料庫
- 《資料庫系統原理》課程筆記資料庫筆記
- Redis乾貨|解鎖Redis 時間序列資料的應用Redis