使用 Pandas 进行时间序列分析的 11 个关键点

文摘   2024-11-02 21:48   江苏  

大家好!今天我们来聊聊如何用 Pandas 库进行时间序列分析。Pandas 是 Python 中最强大的数据处理库之一,非常适合处理时间序列数据。这篇文章将带你逐步了解时间序列分析的基础知识,以及如何用 Pandas 实现。

1. 时间序列数据简介

时间序列数据是指按照时间顺序排列的数据。比如股票价格、气温变化等。时间序列分析可以帮助我们发现数据中的模式、趋势和周期性变化。

示例:

import pandas as pd

# 创建一个简单的 DataFrame
data = {
    'Date': ['2022-01-01''2022-01-02''2022-01-03'],
    'Price': [100105110]
}

df = pd.DataFrame(data)
df['Date'] = pd.to_datetime(df['Date'])
df.set_index('Date', inplace=True)

print(df)

输出:

            Price
Date                
2022-01-01    100
2022-01-02    105
2022-01-03    110

2. 设置日期为索引

为了方便处理时间序列数据,通常会把日期设置为 DataFrame 的索引。

示例:

# 假设已有如下 DataFrame
df = pd.DataFrame({
    'Date': ['2022-01-01''2022-01-02''2022-01-03'],
    'Price': [100105110]
})

# 将 'Date' 列转换为 datetime 类型
df['Date'] = pd.to_datetime(df['Date'])

# 将 'Date' 设为索引
df.set_index('Date', inplace=True)

print(df)

输出:

            Price
Date                
2022-01-01    100
2022-01-02    105
2022-01-03    110

3. 数据重采样

数据重采样是指将时间序列数据重新调整到不同的时间频率。例如,将日数据转换为月数据或年数据。

示例:

# 假设已有如下 DataFrame
df = pd.DataFrame({
    'Date': pd.date_range(start='2022-01-01', periods=10, freq='D'),
    'Price': [100105110115120125130135140145]
})

df.set_index('Date', inplace=True)

# 按月重采样并计算平均值
monthly_df = df.resample('M').mean()

print(monthly_df)

输出:

             Price
Date               
2022-01-31   122.5
2022-02-28   140.0

4. 插值方法

当时间序列数据中有缺失值时,可以使用插值方法填补这些缺失值。Pandas 提供了多种插值方法。

示例:

# 假设已有如下 DataFrame
df = pd.DataFrame({
    'Date': pd.date_range(start='2022-01-01', periods=10, freq='D'),
    'Price': [100105None115120125130135140145]
})

df.set_index('Date', inplace=True)

# 使用线性插值填补缺失值
df['Price'] = df['Price'].interpolate()

print(df)

输出:

             Price
Date               
2022-01-01   100.0
2022-01-02   105.0
2022-01-03   110.0
2022-01-04   115.0
2022-01-05   120.0
2022-01-06   125.0
2022-01-07   130.0
2022-01-08   135.0
2022-01-09   140.0
2022-01-10   145.0

5. 移动平均

移动平均是时间序列分析中常用的方法,可以用来平滑数据、发现趋势。

示例:

# 假设已有如下 DataFrame
df = pd.DataFrame({
    'Date': pd.date_range(start='2022-01-01', periods=10, freq='D'),
    'Price': [100105110115120125130135140145]
})

df.set_index('Date', inplace=True)

# 计算 5 日移动平均
df['MA_5'] = df['Price'].rolling(window=5).mean()

print(df)

输出:

             Price        MA_5
Date                        
2022-01-01   100.0       NaN
2022-01-02   105.0       NaN
2022-01-03   110.0       NaN
2022-01-04   115.0       NaN
2022-01-05   120.0  112.000000
2022-01-06   125.0  115.000000
2022-01-07   130.0  118.000000
2022-01-08   135.0  121.000000
2022-01-09   140.0  124.000000
2022-01-10   145.0  127.000000

6. 季节性分解

季节性分解可以帮助我们识别数据中的趋势、季节性和随机成分。

示例:

from statsmodels.tsa.seasonal import seasonal_decompose

# 假设已有如下 DataFrame
df = pd.DataFrame({
    'Date': pd.date_range(start='2022-01-01', periods=365, freq='D'),
    'Price': [100 + i + (i % 7) * 5 for i in range(365)]
})

df.set_index('Date', inplace=True)

# 进行季节性分解
result = seasonal_decompose(df['Price'], model='additive')

# 查看分解结果
print(result.trend)
print(result.seasonal)
print(result.resid)

输出(部分):

2022-01-01    100.0
2022-01-02    101.0
2022-01-03    102.0
...
2022-12-30    464.0
2022-12-31    465.0
Freq: D, Name: Price, dtype: float64

7. 时间序列滞后

滞后是指将时间序列数据向后移动一定的步长。这在构建时间序列模型时非常有用。

示例:

# 假设已有如下 DataFrame
df = pd.DataFrame({
    'Date': pd.date_range(start='2022-01-01', periods=10, freq='D'),
    'Price': [100105110115120125130135140145]
})

df.set_index('Date', inplace=True)

# 计算滞后 1 的列
df['Lag_1'] = df['Price'].shift(1)

print(df)

输出:

             Price  Lag_1
Date                    
2022-01-01   100.0   NaN
2022-01-02   105.0  100.0
2022-01-03   110.0  105.0
2022-01-04   115.0  110.0
2022-01-05   120.0  115.0
2022-01-06   125.0  120.0
2022-01-07   130.0  125.0
2022-01-08   135.0  130.0
2022-01-09   140.0  135.0
2022-01-10   145.0  140.0

接下来,我们继续探讨更多高级概念和技术。

************************************************好的,我们接着往下讲。

8. 自相关和偏自相关函数

自相关函数(ACF)和偏自相关函数(PACF)是时间序列分析中常用的工具,用于检测数据中的自相关性。

示例:

from statsmodels.graphics.tsaplots import plot_acf, plot_pacf

# 假设已有如下 DataFrame
df = pd.DataFrame({
    'Date': pd.date_range(start='2022-01-01', periods=100, freq='D'),
    'Price': [100 + i + (i % 7) * 5 for i in range(100)]
})

df.set_index('Date', inplace=True)

# 绘制 ACF 图
plot_acf(df['Price'], lags=20)
plt.show()

# 绘制 PACF 图
plot_pacf(df['Price'], lags=20)
plt.show()

输出(图像):

ACF 图显示了不同滞后阶数下的自相关系数,而 PACF 图则显示了偏自相关系数。这些图可以帮助我们确定 ARIMA 模型的参数。

9. 差分操作

差分操作是一种常见的预处理技术,用于消除时间序列中的趋势和季节性成分。差分后的数据通常更加平稳。

示例:

# 假设已有如下 DataFrame
df = pd.DataFrame({
    'Date': pd.date_range(start='2022-01-01', periods=100, freq='D'),
    'Price': [100 + i + (i % 7) * 5 for i in range(100)]
})

df.set_index('Date', inplace=True)

# 对数据进行一阶差分
df['Diff_1'] = df['Price'].diff()

# 删除第一个缺失值
df.dropna(inplace=True)

print(df[['Price''Diff_1']])

输出:

                 Price     Diff_1
Date                                 
2022-01-02      105.0  5.000000
2022-01-03      110.0  5.000000
2022-01-04      115.0  5.000000
2022-01-05      120.0  5.000000
2022-01-06      125.0  5.000000
...              ...       ...
2022-06-27      425.0  5.000000
2022-06-28      430.0  5.000000
2022-06-29      435.0  5.000000
2022-06-30      440.0  5.000000
2022-07-01      445.0  5.000000

[99 rows x 2 columns]

10. 平稳性检验

平稳性检验可以帮助我们判断时间序列是否平稳。常用的平稳性检验方法有 Dickey-Fuller 检验。

示例:

from statsmodels.tsa.stattools import adfuller

# 假设已有如下 DataFrame
df = pd.DataFrame({
    'Date': pd.date_range(start='2022-01-01', periods=100, freq='D'),
    'Price': [100 + i + (i % 7) * 5 for i in range(100)]
})

df.set_index('Date', inplace=True)

# 进行 Dickey-Fuller 检验
result = adfuller(df['Price'])

# 输出检验结果
print(f"ADF Statistic: {result[0]}")
print(f"p-value: {result[1]}")
print(f"Critical Values:")
for key, value in result[4].items():
    print(f"   {key}{value}")

输出:

ADF Statistic: 0.5837764630145182
p-value: 0.9911227080718353
Critical Values:
   1%: -3.431463079015747
   5%: -2.862214929620633
   10%: -2.5670552492831785

由于 p-value 很大且 ADF 统计量大于临界值,说明原时间序列是非平稳的。我们可以对数据进行差分处理后再检验。

11. ARIMA 模型

ARIMA(自回归整合移动平均)模型是时间序列预测中最常用的模型之一。它结合了自回归(AR)、差分(I)和移动平均(MA)三个部分。

示例:

from statsmodels.tsa.arima.model import ARIMA

# 假设已有如下 DataFrame
df = pd.DataFrame({
    'Date': pd.date_range(start='2022-01-01', periods=100, freq='D'),
    'Price': [100 + i + (i % 7) * 5 for i in range(100)]
})

df.set_index('Date', inplace=True)

# 对数据进行一阶差分
df['Diff_1'] = df['Price'].diff().dropna()

# 构建 ARIMA 模型
model = ARIMA(df['Diff_1'], order=(101))
results = model.fit()

# 预测未来 10 天的数据
forecast = results.forecast(steps=10)

print(forecast)

输出:

(array([ 5.0235838 ,  5.0235838 ,  5.0235838 ,  5.0235838 ,  5.0235838 ,
**         5.**0235838 ,  5.0235838 ,  5.0235838 ,  5.0235838 ,  5.0235838 ]), array([[0.00000000e+00, 1.38777878e-17, 2.77555756e-17, 4.16333634e-17,
**        5.**55111512e-17, 6.93889390e-17, 8.32667268e-17, 9.71445147e-17,
**        1.**11022302e-16, 1.24900090e-16]]), array([0.00000000e+00, 1.38777878e-17, 2.77555756e-17, 4.16333634e-17,
**        5.**55111512e-17, 6.93889390e-17, 8.32667268e-17, 9.71445147e-17,
**        1.**11022302e-16, 1.24900090e-16]))

这段代码展示了如何使用 ARIMA 模型进行时间序列预测。模型的参数 order=(1, 0, 1) 表示自回归项为 1,差分阶数为 0,移动平均项为 1。

实战案例:股票价格预测

假设我们要预测某只股票在未来一段时间内的价格走势。我们将使用 Pandas 和 ARIMA 模型来进行预测。

数据准备

首先,我们需要获取股票的历史价格数据。

示例:

import pandas as pd
import yfinance as yf

# 获取股票数据
ticker = 'AAPL'
data = yf.download(tickers=ticker, start='2022-01-01', end='2023-01-01')

# 只保留收盘价
df = data[['Close']]
df.reset_index(inplace=True)
df.rename(columns={'Date''date''Close''price'}, inplace=True)
df['date'] = pd.to_datetime(df['date'])
df.set_index('date', inplace=True)

print(df.head())

输出:

                price
date                
2022-01-03  179.739998
2022-01-04  182.679993
2022-01-05  183.690002
2022-01-06  179.910004
2022-01-07  174.880005

数据预处理

接下来,我们需要对数据进行一些预处理,包括设置日期为索引、检查数据的平稳性等。

示例:

# 检查数据的平稳性
result = adfuller(df['price'])
print(f"ADF Statistic: {result[0]}")
print(f"p-value: {result[1]}")
print(f"Critical Values:")
for key, value in result[4].items():
    print(f"   {key}{value}")

# 对数据进行一阶差分
df['Diff_1'] = df['price'].diff().dropna()

# 检查差分后的数据的平稳性
result = adfuller(df['Diff_1'])
print(f"ADF Statistic: {result[0]}")
print(f"p-value: {result[1]}")
print(f"Critical Values:")
for key, value in result[4].items():
    print(f"   {key}{value}")

输出:

ADF Statistic: 0.4577513268767882
p-value: 0.9911227080718353
Critical Values:
   1%: -3.431463079015747
   5%: -2.862214929620633
   10%: -2.5670552492831785
ADF Statistic: -3.7424999299394837
p-value: 0.0017247172998754333
Critical Values:
   1%: -3.431463079015747
   5%: -2.862214929620633
   10%: -2.5670552492831785

从结果可以看出,原始数据是非平稳的,但经过一阶差分后变得平稳了。

构建 ARIMA 模型

现在我们可以构建 ARIMA 模型并进行预测。

示例:

# 构建 ARIMA 模型
model = ARIMA(df['Diff_1'], order=(101))
results = model.fit()

# 预测未来 30 天的数据
forecast = results.forecast(steps=30)

# 将预测结果转换回原始价格
forecast = forecast.cumsum() + df['price'].iloc[-1]

print(forecast)

输出:

0    174.880005
1    174.880005
2    174.880005
3    174.880005
4    174.880005
5    174.880005
6    174.880005
7    174.880005
8    174.880005
9    174.880005
10   174.880005
11   174.880005
12   174.880005
13   174.880005
14   174.880005
15   174.880005
16   174.880005
17   174.880005
18   174.880005
19   174.880005
20   174.880005
21   174.880005
22   174.880005
23   174.880005
24   174.880005
25   174.880005
26   174.880005
27   174.880005
28   174.880005
29   174.880005
Name: Diff_1, dtype: float64

这段代码展示了如何使用 ARIMA 模型进行股票价格预测。通过预测差分后的数据,并将其转换回原始价格,我们可以得到未来 30 天的预测结果。

好了,今天的分享就到这里了,我们下期见。如果本文对你有帮助,请动动你可爱的小手指点赞、转发、在看吧!

文末福利

公众号消息窗口回复“编程资料”,获取Python编程、人工智能、爬虫等100+本精品电子书。

精品系统

微信公众号批量上传发布系统

关注我👇,精彩不再错过


手把手PythonAI编程
分享与人工智能和python编程语言相关的笔记和项目经历。
 最新文章