python spss时间序列预测步骤数据 怎么预测

1893人阅读
深度学习(10)
  关键词:python、Keras、LSTM、Time-Series-Prediction
  关于技术理论部分,可以参考这两篇文章(、),本文主要从数据、代码角度,利用LSTM进行时间序列预测。
时间序列(或称动态数列)是指将同一统计指标的数值按其发生的时间先后顺序排列而成的数列。时间序列分析的主要目的是根据已有的历史数据对未来进行预测。
时间序列构成要素:长期趋势,季节变动,循环变动,不规则变动
长期趋势( T )现象在较长时期内受某种根本性因素作用而形成的总的变动趋势
季节变动( S )现象在一年内随着季节的变化而发生的有规律的周期性变动
循环变动( C )现象以若干年为周期所呈现出的波浪起伏形态的有规律的变动
不规则变动(I )是一种无规律可循的变动,包括严格的随机变动和不规则的突发性影响很大的变动两种类型
(1)原始时间序列数据(只列出了18行)
(2)处理数据使之符合LSTM的要求
为了更加直观的了解数据格式,代码中加入了一些打印(print),并且后面加了注释,就是输出值
def load_data(filename, seq_len):
f = open(filename, 'rb').read()
data = f.split('\n')
print('data len:',len(data))
print('sequence len:',seq_len)
sequence_length = seq_len + 1
result = []
for index in range(len(data) - sequence_length):
result.append(data[index: index + sequence_length])
print('result len:',len(result))
print('result shape:',np.array(result).shape)
result = np.array(result)
row = round(0.9 * result.shape[0])
train = result[:row, :]
np.random.shuffle(train)
x_train = train[:, :-1]
y_train = train[:, -1]
x_test = result[row:, :-1]
y_test = result[row:, -1]
x_train = np.reshape(x_train, (x_train.shape[0], x_train.shape[1], 1))
x_test = np.reshape(x_test, (x_test.shape[0], x_test.shape[1], 1))
print('X_train shape:',X_train.shape)
print('y_train shape:',y_train.shape)
print('X_test shape:',X_test.shape)
print('y_test shape:',y_test.shape)
return [x_train, y_train, x_test, y_test]
(3)LSTM模型
本文使用的是keras深度学习框架,读者可能用的是其他的,诸如theano、tensorflow等,大同小异。
LSTM的结构可以自己定制,Stack LSTM or Bidirectional LSTM
def build_model(layers):
model = Sequential()
model.add(LSTM(input_dim=layers[0],output_dim=layers[1],return_sequences=True))
model.add(Dropout(0.2))
model.add(LSTM(layers[2],return_sequences=False))
model.add(Dropout(0.2))
model.add(Dense(output_dim=layers[3]))
model.add(Activation("linear"))
start = time.time()
pile(loss="mse", optimizer="rmsprop")
print("Compilation Time : ", time.time() - start)
return model
(4)LSTM训练预测
1.直接预测
def predict_point_by_point(model, data):
predicted = model.predict(data)
print('predicted shape:',np.array(predicted).shape)
predicted = np.reshape(predicted, (predicted.size,))
return predicted
2.滚动预测
def predict_sequence_full(model, data, window_size):
#data X_test
curr_frame = data[0]
predicted = []
for i in xrange(len(data)):
#x = np.array([[[1],[2],[3]], [[4],[5],[6]]])
x.shape (2, 3, 1) x[0,0] = array([1])
x[:,np.newaxis,:,:].shape
(2, 1, 3, 1)
predicted.append(model.predict(curr_frame[newaxis,:,:])[0,0])
#np.array(curr_frame[newaxis,:,:]).shape (1L,50L,1L)
curr_frame = curr_frame[1:]
curr_frame = np.insert(curr_frame, [window_size-1], predicted[-1], axis=0)
#numpy.insert(arr, obj, values, axis=None)
return predicted
2.滑动窗口+滚动预测
def predict_sequences_multiple(model, data, window_size, prediction_len):
prediction_seqs = []
for i in xrange(len(data)/prediction_len):
curr_frame = data[i*prediction_len]
predicted = []
for j in xrange(prediction_len):
predicted.append(model.predict(curr_frame[newaxis,:,:])[0,0])
curr_frame = curr_frame[1:]
curr_frame = np.insert(curr_frame, [window_size-1], predicted[-1], axis=0)
prediction_seqs.append(predicted)
return prediction_seqs
(5)完整代码
from __future__ import print_function
import time
import warnings
import numpy as np
import time
import matplotlib.pyplot as plt
from numpy import newaxis
from keras.layers.core import Dense, Activation, Dropout
from keras.layers.recurrent import LSTM
from keras.models import Sequential
warnings.filterwarnings("ignore")
def load_data(filename, seq_len, normalise_window):
f = open(filename, 'rb').read()
data = f.split('\n')
print('data len:',len(data))
print('sequence len:',seq_len)
sequence_length = seq_len + 1
result = []
for index in range(len(data) - sequence_length):
result.append(data[index: index + sequence_length])
print('result len:',len(result))
print('result shape:',np.array(result).shape)
print(result[:1])
if normalise_window:
result = normalise_windows(result)
print(result[:1])
print('normalise_windows result shape:',np.array(result).shape)
result = np.array(result)
row = round(0.9 * result.shape[0])
train = result[:row, :]
np.random.shuffle(train)
x_train = train[:, :-1]
y_train = train[:, -1]
x_test = result[row:, :-1]
y_test = result[row:, -1]
x_train = np.reshape(x_train, (x_train.shape[0], x_train.shape[1], 1))
x_test = np.reshape(x_test, (x_test.shape[0], x_test.shape[1], 1))
return [x_train, y_train, x_test, y_test]
def normalise_windows(window_data):
normalised_data = []
for window in window_data:
normalised_window = [((float(p) / float(window[0])) - 1) for p in window]
normalised_data.append(normalised_window)
return normalised_data
def build_model(layers):
model = Sequential()
model.add(LSTM(input_dim=layers[0],output_dim=layers[1],return_sequences=True))
model.add(Dropout(0.2))
model.add(LSTM(layers[2],return_sequences=False))
model.add(Dropout(0.2))
model.add(Dense(output_dim=layers[3]))
model.add(Activation("linear"))
start = time.time()
pile(loss="mse", optimizer="rmsprop")
print("Compilation Time : ", time.time() - start)
return model
def predict_point_by_point(model, data):
predicted = model.predict(data)
print('predicted shape:',np.array(predicted).shape)
predicted = np.reshape(predicted, (predicted.size,))
return predicted
def predict_sequence_full(model, data, window_size):
curr_frame = data[0]
predicted = []
for i in xrange(len(data)):
predicted.append(model.predict(curr_frame[newaxis,:,:])[0,0])
curr_frame = curr_frame[1:]
curr_frame = np.insert(curr_frame, [window_size-1], predicted[-1], axis=0)
return predicted
def predict_sequences_multiple(model, data, window_size, prediction_len):
prediction_seqs = []
for i in xrange(len(data)/prediction_len):
curr_frame = data[i*prediction_len]
predicted = []
for j in xrange(prediction_len):
predicted.append(model.predict(curr_frame[newaxis,:,:])[0,0])
curr_frame = curr_frame[1:]
curr_frame = np.insert(curr_frame, [window_size-1], predicted[-1], axis=0)
prediction_seqs.append(predicted)
return prediction_seqs
def plot_results(predicted_data, true_data, filename):
fig = plt.figure(facecolor='white')
ax = fig.add_subplot(111)
ax.plot(true_data, label='True Data')
plt.plot(predicted_data, label='Prediction')
plt.legend()
plt.show()
plt.savefig(filename+'.png')
def plot_results_multiple(predicted_data, true_data, prediction_len):
fig = plt.figure(facecolor='white')
ax = fig.add_subplot(111)
ax.plot(true_data, label='True Data')
for i, data in enumerate(predicted_data):
padding = [None for p in xrange(i * prediction_len)]
plt.plot(padding + data, label='Prediction')
plt.legend()
plt.show()
plt.savefig('plot_results_multiple.png')
if __name__=='__main__':
global_start_time = time.time()
seq_len = 50
print('& Loading data... ')
X_train, y_train, X_test, y_test = load_data('sp500.csv', seq_len, True)
print('X_train shape:',X_train.shape)
print('y_train shape:',y_train.shape)
print('X_test shape:',X_test.shape)
print('y_test shape:',y_test.shape)
print('& Data Loaded. Compiling...')
model = build_model([1, 50, 100, 1])
model.fit(X_train,y_train,batch_size=512,nb_epoch=epochs,validation_split=0.05)
multiple_predictions = predict_sequences_multiple(model, X_test, seq_len, prediction_len=50)
print('multiple_predictions shape:',np.array(multiple_predictions).shape)
full_predictions = predict_sequence_full(model, X_test, seq_len)
print('full_predictions shape:',np.array(full_predictions).shape)
point_by_point_predictions = predict_point_by_point(model, X_test)
print('point_by_point_predictions shape:',np.array(point_by_point_predictions).shape)
print('Training duration (s) : ', time.time() - global_start_time)
plot_results_multiple(multiple_predictions, y_test, 50)
plot_results(full_predictions,y_test,'full_predictions')
plot_results(point_by_point_predictions,y_test,'point_by_point_predictions')
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:186312次
积分:2476
积分:2476
排名:第12764名
原创:68篇
评论:98条
机器学习、数据挖掘爱好者
文章:13篇
阅读:57340[python]&时间序列分析之ARIMA
1 时间序列与时间序列分析
在生产和科学研究中,对某一个或者一组变量
进行观察测量,将在一系列时刻
t1,t2,⋯,tn
所得到的离散数字组成的序列集合,称之为时间序列。
时间序列分析是根据系统观察得到的时间序列数据,通过曲线拟合和参数估计来建立数学模型的理论和方法。时间序列分析常用于国民宏观经济控制、市场潜力预测、气象预测、农作物害虫灾害预报等各个方面。
2 时间序列建模基本步骤
获取被观测系统时间序列数据;
对数据绘图,观测是否为平稳时间序列;对于非平稳时间序列要先进行d阶差分运算,化为平稳时间序列;
经过第二步处理,已经得到平稳时间序列。要对平稳时间序列分别求得其自相关系数ACF
和偏自相关系数PACF ,通过对自相关图和偏自相关图的分析,得到最佳的阶层
p 和阶数 q
由以上得到的d、q、p
,得到ARIMA模型。然后开始对得到的模型进行模型检验。
3 ARIMA实战解剖
原理大概清楚,实践却还是会有诸多问题。相比较R语言,在做时间序列分析的资料相对少很多。下面就通过Python语言详细解析后三个步骤的实现过程。
文中使用到这些基础库:
pandas,numpy,scipy,matplotlib,statsmodels。 对其调用如下
from __future__ import print_function
import pandas as pd
import numpy as np
from scipy import
import matplotlib.pyplot as plt
import statsmodels.api as sm
from statsmodels.graphics.api import qqplot
3.1 获取数据
这里我们使用一个具有周期性的测试数据,进行分析。
数据如下:
dta=[,,92,,,,
,,,70,49,55,
,,424,,,767,
,,,,,,10232,
,,,,,,13248,
,,,,,,14722,
,,,,10395]
dta=pd.Series(dta)
dta.index = pd.Index(sm.tsa.datetools.dates_from_range('2001','2100'))
dta.plot(figsize=(12,8))
3.2 时间序列的差分d
模型对时间序列的要求是平稳型。因此,当你得到一个非平稳的时间序列时,首先要做的即是做时间序列的差分,直到得到一个平稳时间序列。如果你对时间序列做d次差分才能得到一个平稳序列,那么可以使用ARIMA(p,d,q)模型,其中d是差分次数。
fig = plt.figure(figsize=(12,8))
ax1= fig.add_subplot(111)
diff1 = dta.diff(1)
diff1.plot(ax=ax1)
一阶差分的时间序列的均值和方差已经基本平稳,不过我们还是可以比较一下二阶差分的效果
fig = plt.figure(figsize=(12,8))
ax2= fig.add_subplot(111)
diff2 = dta.diff(2)
diff2.plot(ax=ax2)
可以看出二阶差分后的时间序列与一阶差分相差不大,并且二者随着时间推移,时间序列的均值和方差保持不变。因此可以将差分次数d设置为1。
其实还有针对平稳的检验,叫“ADF单位根平稳型检验”,以后再更。
3.3 合适的p,q
现在我们已经得到一个平稳的时间序列,接来下就是选择合适的ARIMA模型,即ARIMA模型中合适的p,q。
第一步我们要先检查平稳时间序列的自相关图和偏自相关图。
dta= dta.diff(1)#我们已经知道要使用一阶差分的时间序列,之前判断差分的程序可以注释掉
fig = plt.figure(figsize=(12,8))
ax1=fig.add_subplot(211)
fig = sm.graphics.tsa.plot_acf(dta,lags=40,ax=ax1)
ax2 = fig.add_subplot(212)
fig = sm.graphics.tsa.plot_pacf(dta,lags=40,ax=ax2)
其中lags 表示滞后的阶数,以上分别得到acf 图和pacf 图
通过两图观察得到:
* 自相关图显示滞后有三个阶超出了置信边界;
* 偏相关图显示在滞后1至7阶(lags 1,2,…,7)时的偏自相关系数超出了置信边界,从lag
7之后偏自相关系数值缩小至0
则有以下模型可以供选择:
1. ARMA(0,1)模型:即自相关图在滞后1阶之后缩小为0,且偏自相关缩小至0,则是一个阶数q=1的移动平均模型;
2. ARMA(7,0)模型:即偏自相关图在滞后7阶之后缩小为0,且自相关缩小至0,则是一个阶层p=3的自回归模型;
3. ARMA(7,1)模型:即使得自相关和偏自相关都缩小至零。则是一个混合模型。
4. …还可以有其他供选择的模型
现在有以上这么多可供选择的模型,我们通常采用ARMA模型的AIC法则。我们知道:增加自由参数的数目提高了拟合的优良性,AIC鼓励数据拟合的优良性
但是尽量避免出现过度拟合(Overfitting)的情况。所以优先考虑的模型应是AIC值最小的那一个。赤池信息准则的方法是寻找可以最好地解释数据
但包含最少自由参数的模型。不仅仅包括AIC准则,目前选择模型常用如下准则:
* AIC=-2 ln(L) + 2 k 中文名字:赤池信息量 akaike information criterion
* BIC=-2 ln(L) + ln(n)*k 中文名字:贝叶斯信息量 bayesian information
* HQ=-2 ln(L) + ln(ln(n))*k hannan-quinn criterion
构造这些统计量所遵循的统计思想是一致的,就是在考虑拟合残差的同时,依自变量个数施加“惩罚”。但要注意的是,这些准则不能说明某一个模型的精确度,也
即是说,对于三个模型A,B,C,我们能够判断出C模型是最好的,但不能保证C模型能够很好地刻画数据,因为有可能三个模型都是糟糕的。
arma_mod20 = sm.tsa.ARMA(dta,(7,0)).fit()
print(arma_mod20.aic,arma_mod20.bic,arma_mod20.hqic)
arma_mod30 = sm.tsa.ARMA(dta,(0,1)).fit()
print(arma_mod30.aic,arma_mod30.bic,arma_mod30.hqic)
arma_mod40 = sm.tsa.ARMA(dta,(7,1)).fit()
print(arma_mod40.aic,arma_mod40.bic,arma_mod40.hqic)
arma_mod50 = sm.tsa.ARMA(dta,(8,0)).fit()
print(arma_mod50.aic,arma_mod50.bic,arma_mod50.hqic)
可以看到ARMA(7,0)的aic,bic,hqic均最小,因此是最佳模型。
3.4 模型检验
在指数平滑模型下,观察ARIMA模型的残差是否是平均值为0且方差为常数的正态分布(服从零均值、方差不变的正态分布),同时也要观察连续残差是否(自)相关。
我们对ARMA(7,0)模型所产生的残差做自相关图
fig = plt.figure(figsize=(12,8))
ax1 = fig.add_subplot(211)
fig = sm.graphics.tsa.plot_acf(resid.values.squeeze(), lags=40, ax=ax1)
ax2 = fig.add_subplot(212)
fig = sm.graphics.tsa.plot_pacf(resid, lags=40, ax=ax2)
3.4.2 做D-W检验
德宾-沃森(Durbin-Watson)检验。德宾-沃森检验,简称D-W检验,是目前检验自相关性最常用的方法,但它只使用于检验一阶自相关性。因为自相关系数ρ的值介于-1和1之间,所以
0≤DW≤4。并且DW=O=>ρ=1   即存在正自相关性
DW=4<=>ρ=-1 即存在负自相关性
DW=2<=>ρ=0  即不存在(一阶)自相关性
因此,当DW值显著的接近于O或4时,则存在自相关性,而接近于2时,则不存在(一阶)自相关性。这样只要知道DW统计量的概率分布,在给定的显著水平下,根据临界值的位置就可以对原假设H0进行检验。
print(sm.stats.durbin_watson(arma_mod20.resid.values))
检验结果是2.,说明不存在自相关性。
3.4.3 观察是否符合正态分布
这里使用QQ图,它用于直观验证一组数据是否来自某个分布,或者验证某两组数据是否来自同一(族)分布。在教学和软件中常用的是检验数据是否来自于正态分布。QQ图细节,下次再更。
resid = arma_mod20.resid#残差
fig = plt.figure(figsize=(12,8))
ax = fig.add_subplot(111)
fig = qqplot(resid, line='q', ax=ax, fit=True)
3.4.4 Ljung-Box检验
test是对randomness的检验,或者说是对时间序列是否存在滞后相关的一种统计检验。对于滞后相关的检验,我们常常采用的方法还包括计算ACF
和PCAF并观察其图像,但是无论是ACF还是PACF都仅仅考虑是否存在某一特定滞后阶数的相关。LB检验则是基于一系列滞后阶数,判断序列总体的相关
性或者说随机性是否存在。
时间序列中一个最基本的模型就是高斯白噪声序列。而对于ARIMA模型,其残差被假定为高斯白噪声序列,所以当我们用ARIMA模型去拟合数据时,拟合后
我们要对残差的估计序列进行LB检验,判断其是否是高斯白噪声,如果不是,那么就说明ARIMA模型也许并不是一个适合样本的模型。
r,q,p = sm.tsa.acf(resid.values.squeeze(), qstat=True)
data = np.c_[range(1,41), r[1:], q, p]
table = pd.DataFrame(data, columns=['lag', "AC", "Q", "Prob(&Q)"])
print(table.set_index('lag'))
检验的结果就是看最后一列前十二行的检验概率(一般观察滞后1~12阶),如果检验概率小于给定的显著性水平,比如0.05、0.10等就拒绝原假设,其原假设是相关系数为零。就结果来看,如果取显著性水平为0.05,那么相关系数与零没有显著差异,即为白噪声序列。
3.5 模型预测
模型确定之后,就可以开始进行预测了,我们对未来十年的数据进行预测。
predict_sunspots = arma_mod20.predict('2090', '2100', dynamic=True)
print(predict_sunspots)
fig, ax = plt.subplots(figsize=(12, 8))
ax = dta.ix['2001':].plot(ax=ax)
predict_sunspots.plot(ax=ax)
前面90个数据为测试数据,最后10个为预测数据;从图形来,预测结果较为合理。至此,本案例的时间序列分析也就结束了。
参考文献与推荐阅读
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。利用python进行数据分析-时间序列2
利用python进行数据分析-时间序列2
1.带有重复索引的时间序列
dates=pd.DatetimeIndex(['1/1/2000','1/2/2000','1/2/2000','1/2/2000','1/3/2000'])
dup_ts=Series(np.arange(5),index=dates)
print dup_ts
dtype: int32
通过检查索引的is_unique属性,我们就可以知道它是不是唯一的
print dup_ts.index.is_unique
对这个时间序列进行索引,要么产生标量值,要么产生切片,具体要看所选的时间点是否重复
print dup_ts['1/3/2000']& #不重复
print dup_ts['1/2/2000']& #重复
dtype: int32
假设你想要对具有唯一时间戳的数据进行聚合。一个办法是使用groupby,并传入level=0(索引的唯一 一层!)
grouped=dup_ts.groupby(level=0)
print grouped.mean()
print grouped.count()
dtype: int32
dtype: int64
2.日期的范围、频率以及移动
dates=[datetime.datetime(),datetime.datetime(),
&&&&&& datetime.datetime(),datetime.datetime(),
&&&&&& datetime.datetime(),datetime.datetime()]
ts=Series(np.random.randn(6),index=dates)
print ts.resample('D')
&&& 1.068995
&&& 0.564281
&&& 1.910822
&& -0.339067
&& -1.671388
&& -0.679710
dtype: float64
&&& 1.068995
&&&&&&&& NaN
&&&&&&&& NaN
&&& 0.564281
&&&&&&&& NaN
&&& 1.910822
&& -0.339067
&&&&&&&& NaN
&& -1.671388
&&&&&&&& NaN
&& -0.679710
Freq: D, dtype: float64
3.生成日期范围
index=pd.date_range('4/1/2012','6/1/2012')
print index
DatetimeIndex(['', '', '', '',
&&&&&&&&&&&&&& '', '', '', '',
&&&&&&&&&&&&&& '', '', '', '',
&&&&&&&&&&&&&& '', '', '', '',
&&&&&&&&&&&&&& '', '', '', '',
&&&&&&&&&&&&&& '', '', '', '',
&&&&&&&&&&&&&& '', '', '', '',
&&&&&&&&&&&&&& '', '', '', '',
&&&&&&&&&&&&&& '', '', '', '',
&&&&&&&&&&&&&& '', '', '', '',
&&&&&&&&&&&&&& '', '', '', '',
&&&&&&&&&&&&&& '', '', '', '',
&&&&&&&&&&&&&& '', '', '', '',
&&&&&&&&&&&&&& '', '', '', '',
&&&&&&&&&&&&&& '', '', '', '',
&&&&&&&&&&&&&& '', ''],
&&&&&&&&&&&&& dtype='datetime64[ns]', freq='D')
默认情况下,date_range会产生按天计算的时间点。如果只传入起始或结束日期,那就还得传入一个表示一段时间的数字
print pd.date_range(start='4/1/2012',periods=20)
print pd.date_range(end='6/1/2012',periods=20)
DatetimeIndex(['', '', '', '',
&&&&&&&&&&&&&& '', '', '', '',
&&&&&&&&&&&&&& '', '', '', '',
&&&&&&&&&&&&&& '', '', '', '',
&&&&&&&&&&&&&& '', '', '', ''],
&&&&&&&&&&&&& dtype='datetime64[ns]', freq='D')
DatetimeIndex(['', '', '', '',
&&&&&&&&&&&&&& '', '', '', '',
&&&&&&&&&&&&&& '', '', '', '',
&&&&&&&&&&&&&& '', '', '', '',
&&&&&&&&&&&&&& '', '', '', ''],
&&&&&&&&&&&&& dtype='datetime64[ns]', freq='D')
起始和结束日期定义了日期索引的严格边界。如果你想生成一个由每月最后一个工作日组成的日期索引,可以传入“BM”频率,这样只会包含时间间隔内符合频率要求的日期
print pd.date_range('1/1/2000','12/1/2000',freq='BM')
DatetimeIndex(['', '', '', '',
&&&&&&&&&&&&&& '', '', '', '',
&&&&&&&&&&&&&& '', '', ''],
&&&&&&&&&&&&& dtype='datetime64[ns]', freq='BM')
有时,虽然起始和结束日期带有时间信息,但你希望产生一组规范化到午夜的时间戳。normalize选项即可实现该功能
print pd.date_range('5/2/:31',periods=5,normalize=True)
DatetimeIndex(['', '', '', '',
&&&&&&&&&&&&&& ''],
&&&&&&&&&&&&& dtype='datetime64[ns]', freq='D')
4.频率和日期偏移量
pandas中的频率是由一个基础频率和一个乘数组成的。基础频率通常以一个字符串别名表示,比如“M”表示每月,“H”表示每小时。对于每个基础频率,都有一个被称为日期偏移量的对象与之对应。例如,按小时计算的频率可以用Hour类表示
from pandas.tseries.offsets import Hour,Minute
hour=Hour()
print hour
传入一个整数即可定义偏移量的倍数
four_hours=Hour(4)
print four_hours
&4 * Hours&
一般来说,无需显示创建这样的对象,只需使用诸如“H”或“4H”这样的字符串别名即可。在基础频率前面放上一个整数即可创建倍数
print pd.date_range('1/1/2000','1/3/',freq='4h')
DatetimeIndex([' 00:00:00', ' 04:00:00',
&&&&&&&&&&&&&& ' 08:00:00', ' 12:00:00',
&&&&&&&&&&&&&& ' 16:00:00', ' 20:00:00',
&&&&&&&&&&&&&& ' 00:00:00', ' 04:00:00',
&&&&&&&&&&&&&& ' 08:00:00', ' 12:00:00',
&&&&&&&&&&&&&& ' 16:00:00', ' 20:00:00',
&&&&&&&&&&&&&& ' 00:00:00', ' 04:00:00',
&&&&&&&&&&&&&& ' 08:00:00', ' 12:00:00',
&&&&&&&&&&&&&& ' 16:00:00', ' 20:00:00'],
&&&&&&&&&&&&& dtype='datetime64[ns]', freq='4H')
大部分偏移量对象都可通过加法进行连接
print Hour(2)+Minute(30)
&150 * Minutes&
同理,你也可以传入频率字符串,这种字符串可以被高效地解析为等效的表达式
print pd.date_range('1/1/2000',periods=10,freq='1h30min')
&150 * Minutes&
DatetimeIndex([' 00:00:00', ' 01:30:00',
&&&&&&&&&&&&&& ' 03:00:00', ' 04:30:00',
&&&&&&&&&&&&&& ' 06:00:00', ' 07:30:00',
&&&&&&&&&&&&&& ' 09:00:00', ' 10:30:00',
&&&&&&&&&&&&&& ' 12:00:00', ' 13:30:00'],
&&&&&&&&&&&&& dtype='datetime64[ns]', freq='90T')
有些频率所描述的时间点并不是均匀分隔的。例如,“M”(日历月末)和“BM”(每月最后一个工作日)就取决于每月的天数。由于没有更好的术语,我将这些称为锚点偏移量
WOM能获得诸如“每月第3个星期五”之类的日期
rng=pd.date_range('1/1/2012','9/1/2012',freq='WOM-3FRI')
print list(rng)
[Timestamp(' 00:00:00', offset='WOM-3FRI'), Timestamp(' 00:00:00', offset='WOM-3FRI'), Timestamp(' 00:00:00', offset='WOM-3FRI'), Timestamp(' 00:00:00', offset='WOM-3FRI'), Timestamp('
00:00:00', offset='WOM-3FRI'), Timestamp(' 00:00:00', offset='WOM-3FRI'), Timestamp(' 00:00:00', offset='WOM-3FRI'), Timestamp(' 00:00:00', offset='WOM-3FRI')]
6.移动(超前和滞后)数据
移动指的是沿着时间轴将数据前移或后移。Series和DataFrame都有一个shift方法用于执行单纯的前移或后移操作,保持索引不变
ts=Series(np.random.randn(4),index=pd.date_range('1/1/2000',periods=4,freq='M'))
print ts.shift(2)
print ts.shift(-2)
&& -0.389670
&&& 0.541153
&&& 0.998715
&& -0.800795
Freq: M, dtype: float64
&&&&&&&& NaN
&&&&&&&& NaN
&& -0.389670
&&& 0.541153
Freq: M, dtype: float64
&&& 0.998715
&& -0.800795
&&&&&&&& NaN
&&&&&&&& NaN
Freq: M, dtype: float64
shift通常用于计算一个时间序列或多个时间序列中的百分比变化,可以这样表达:ts/ts.shift(1)-1
由于单纯的移位操作不会修改索引,所以部分数据会被丢弃。如果频率已知,则可以将其传给shift以便实现对时间戳进行位移而不是对数据进行简单位移
print ts.shift(2,freq='M')
&& -0.355693
&&& 0.708167
&&& 0.870448
&& -0.804584
Freq: M, dtype: float64
这里还可以使用其他频率
print ts.shift(3,freq='D')
print ts.shift(1,freq='3D')
print ts.shift(1,freq='90T')
&& -1.045612
&&& 2.034699
&& -0.189753
&& -0.314928
dtype: float64
&& -1.045612
&&& 2.034699
&& -0.189753
&& -0.314928
dtype: float64
01:30:00&& -1.045612
01:30:00&&& 2.034699
01:30:00&& -0.189753
01:30:00&& -0.314928
Freq: M, dtype: float64
7.通过偏移量对日期进行位移
pandas的日期偏移量还可以用在datetime或Timestamp对象上
from pandas.tseries.offsets import Day,MonthEnd
now=datetime.datetime()
print now+3*Day()
如果加的是锚点偏移量,第一次增重会将原日期向前滚动到符合频率规则的下一个日期
print now+MonthEnd()
print now+MonthEnd(2)
通过锚点偏移量的rollforward和rollback方法,可显式地将日期向前或向后“滚动”
offset=MonthEnd()
print offset.rollforward(now)
print offset.rollback(now)
日期偏移量还有一个巧妙的用法,即结合groupby使用这两个滚动方法
ts=Series(np.random.randn(20),index=pd.date_range('1/15/2000',periods=20,freq='4d'))
print ts.groupby(offset.rollforward).mean()
&& -0.024235
&& -0.182988
&& -0.458176
dtype: float64
更简单、更快速地是实现该功能的办法是使用resample
print ts.resample('M',how='mean')
&& -0.076951
&& -0.093232
&& -0.390766
Freq: M, dtype: float64
8.时区处理
时区名可以在文档中找到,也可以通过交互的方式查看
import pytz
mon_timezones[-5:]
['US/Eastern', 'US/Hawaii', 'US/Mountain', 'US/Pacific', 'UTC']
要从pytz中获取时区对象,使用pytz.timezone即可
tz=pytz.timezone('US/Eastern')
US/Eastern
9.本地化和转换
默认情况下,pandas中的时间序列是单纯的时区。看看下面这个时间序列
rng=pd.date_range('3/9/',periods=6,freq='D')
ts=Series(np.random.rand(len(rng)),index=rng)
其索引的tz字段为None
print ts.index.tz
在生成日期范围的时候还可以加上一个时区集
print pd.date_range('3/9/',periods=10,freq='D',tz='UTC')
DatetimeIndex([' 09:30:00+00:00', ' 09:30:00+00:00',
&&&&&&&&&&&&&& ' 09:30:00+00:00', ' 09:30:00+00:00',
&&&&&&&&&&&&&& ' 09:30:00+00:00', ' 09:30:00+00:00',
&&&&&&&&&&&&&& ' 09:30:00+00:00', ' 09:30:00+00:00',
&&&&&&&&&&&&&& ' 09:30:00+00:00', ' 09:30:00+00:00'],
&&&&&&&&&&&&& dtype='datetime64[ns, UTC]', freq='D')
从单纯到本地化的转换是通过tz_localize方法处理的
ts_utc=ts.tz_localize('UTC')
print ts_utc
09:30:00+00:00&&& 0.641279
09:30:00+00:00&&& 0.275813
09:30:00+00:00&&& 0.113782
09:30:00+00:00&&& 0.073940
09:30:00+00:00&&& 0.087528
09:30:00+00:00&&& 0.458625
Freq: D, dtype: float64
print ts_utc.index
DatetimeIndex([' 09:30:00+00:00', ' 09:30:00+00:00',
&&&&&&&&&&&&&& ' 09:30:00+00:00', ' 09:30:00+00:00',
&&&&&&&&&&&&&& ' 09:30:00+00:00', ' 09:30:00+00:00'],
&&&&&&&&&&&&& dtype='datetime64[ns, UTC]', freq='D')
一旦时间序列被本地化到某个特定时区,就可以用tz_convert将其转换到别的时区了
print ts_utc.tz_convert('US/Eastern')
04:30:00-05:00&&& 0.595619
04:30:00-05:00&&& 0.337900
05:30:00-04:00&&& 0.552080
05:30:00-04:00&&& 0.922716
05:30:00-04:00&&& 0.311070
05:30:00-04:00&&& 0.682581
Freq: D, dtype: float64
对于上面这种时间序列(它跨越了美国东部时区的夏令时转变期),我们可以将其本地化到EST,然后转换为UTC或柏林时间
ts_eastern=ts.tz_localize('US/Eastern')
print ts_eastern.tz_convert('UTC')
14:30:00+00:00&&& 0.696696
14:30:00+00:00&&& 0.798250
13:30:00+00:00&&& 0.237720
13:30:00+00:00&&& 0.826396
13:30:00+00:00&&& 0.304436
13:30:00+00:00&&& 0.162294
Freq: D, dtype: float64
print ts_eastern.tz_convert('Europe/Berlin')
15:30:00+01:00&&& 0.116943
15:30:00+01:00&&& 0.805555
14:30:00+01:00&&& 0.765655
14:30:00+01:00&&& 0.762651
14:30:00+01:00&&& 0.947182
14:30:00+01:00&&& 0.670358
Freq: D, dtype: float64
tz_localize和tz_convert也是DatatimeIndex的实例方法
print ts.index.tz_localize('Asia/Shanghai')
DatetimeIndex([' 09:30:00+08:00', ' 09:30:00+08:00',
&&&&&&&&&&&&&& ' 09:30:00+08:00', ' 09:30:00+08:00',
&&&&&&&&&&&&&& ' 09:30:00+08:00', ' 09:30:00+08:00'],
&&&&&&&&&&&&& dtype='datetime64[ns, Asia/Shanghai]', freq='D')
10.操作时区意识型Timestamp对象
跟时间序列和日期范围差不多,Timestamp对象也能从单纯型本地化为时区意识型,并从一个时区转换到另一个时区
stamp=pd.Timestamp(' 04:00')
stamp_utc=stamp.tz_localize('utc')
print stamp_utc.tz_convert('US/Eastern')
23:00:00-05:00
在创建Timestamp时,还可以传入一个时区信息
stamp_moscow=pd.Timestamp(' 04:00',tz='Europe/Moscow')
print stamp_moscow
04:00:00+03:00
时区意识型Timestamp对象在内部保存了一个UTC时间戳值。这个UTC值在时区转换过程中是不会发生变化的
print stamp_utc.value
print stamp_utc.tz_convert('US/Eastern').value
当使用pandas的DateOffset对象执行时间算术运算时,运算过程中会自动关注是否存在夏令时转变期
from pandas.tseries.offsets import Hour
#夏令时转变前30分钟
stamp=pd.Timestamp(' 01:30',tz='US/Eastern')
print stamp
print stamp+Hour()
#夏令时转变前90分钟
stamp=pd.Timestamp(' 00:30',tz='US/Eastern')
print stamp
print stamp+2*Hour()
01:30:00-04:00
02:30:00-04:00
00:30:00-04:00
01:30:00-05:00
11.不同时区之间的运算
如果两个时间序列的时区不同,在将它们合并到一起时,最终结果就会是UTC。由于时间戳其实是你UTC存储的,所以这是一个很简单的运算,并不需要发生任何转换
rng=pd.date_range('3/7/',periods=10,freq='B')
ts=Series(np.random.randn(len(rng)),index=rng)
09:30:00&&& 1.533603
09:30:00&& -0.224899
09:30:00&&& 0.542026
09:30:00&& -0.815753
09:30:00&& -1.421795
09:30:00&&& 0.399534
09:30:00&&& 0.293016
09:30:00&& -1.612594
09:30:00&&& 0.072332
09:30:00&&& 0.313340
Freq: B, dtype: float64
ts1=ts[:7].tz_localize('Europe/London')
ts2=ts1[2:].tz_convert('Europe/Moscow')
result=ts1+ts2
print result.index
DatetimeIndex([' 09:30:00+00:00', ' 09:30:00+00:00',
&&&&&&&&&&&&&& ' 09:30:00+00:00', ' 09:30:00+00:00',
&&&&&&&&&&&&&& ' 09:30:00+00:00', ' 09:30:00+00:00',
&&&&&&&&&&&&&& ' 09:30:00+00:00'],
&&&&&&&&&&&&& dtype='datetime64[ns, UTC]', freq='B')
12.日期及其算术运算
时期表示的是时间区间,比如数日、数月、数季、数年等。Period类所表示的就是这种数据类型,其构造函数需要用到一个字符串或整数,以及表中的频率
p=pd.Period(2007,freq='A-DEC')
这个Period对象表示的是从日到日之间的整段时间。只需对Period对象加上或减去一个整数即可达到根据其频率进行位移的效果
print p+5
如果两个Period对象拥有相同的频率,则它们的差就是它们之间的单位数量
print pd.Period('2014',freq='A-DEC')-p
period_range函数可用于创建规则的时期范围
rng=pd.date_range('1/1/2000','6/30/2000',freq='M')
DatetimeIndex(['', '', '', '',
&&&&&&&&&&&&&& '', ''],
&&&&&&&&&&&&& dtype='datetime64[ns]', freq='M')
PeriodIndex类保存了一组Period,它可以在任何pandas数据结构中被用做轴索引
print Series(np.random.randn(6),index=rng)
&& -1.375039
&& -0.143529
&&& 2.162475
&&& 2.109093
&&& 0.759747
&& -1.994800
Freq: M, dtype: float64
PeriodIndex类的构造函数还允许直接使用一组字符串
values=['2001Q3','2002Q2','2003Q1']
index=pd.PeriodIndex(values,freq='Q-DEC')
print index
PeriodIndex(['2001Q3', '2002Q2', '2003Q1'], dtype='int64', freq='Q-DEC')
我的热门文章
即使是一小步也想与你分享}

我要回帖

更多关于 python 时间序列预测 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信