13.2 时间序列处理
NumPy时间序列处理教程:构建数组、滑动窗口计算与股票趋势分析
本NumPy教程详细讲解时间序列处理,包括时间序列数组构建、滑动窗口计算移动平均和标准差的方法,并通过股票价格趋势分析的实战示例,帮助新手快速掌握NumPy在时间序列分析中的应用。
NumPy时间序列处理:从基础到实战
引言
时间序列数据是按时间顺序排列的数据点,广泛应用于金融、气象、物联网等领域。NumPy作为Python的核心科学计算库,提供了强大的数组处理功能,非常适合时间序列分析。本教程将带你从零开始,学习如何使用NumPy处理时间序列数据,重点包括时间序列数组构建、滑动窗口计算(如移动平均和标准差),并通过实战案例——股票价格趋势分析,巩固所学知识。
时间序列数组构建
在NumPy中,时间序列数据通常表示为数组,其中一维表示时间点,另一维表示数据值。以下是构建时间序列数组的基本步骤。
1. 导入NumPy和其他必要库
首先,确保安装了NumPy。如果处理时间戳,可以结合Python的datetime模块。
import numpy as np
import datetime as dt
2. 创建时间戳数组
使用datetime模块创建时间戳列表,然后转换为NumPy数组。
# 生成日期范围
start_date = dt.datetime(2023, 1, 1)
dates = [start_date + dt.timedelta(days=i) for i in range(10)] # 10天的日期
# 转换为NumPy数组(通常是对象类型,但可以使用datetime64改进)
时间戳数组 = np.array(dates, dtype='datetime64[D]') # 使用datetime64提高效率
print(时间戳数组)
3. 创建数值数据数组
数值数据可以代表如股票价格、温度等。
# 示例:生成随机股票价格数据
np.random.seed(42) # 确保结果可复现
股票价格 = np.random.randn(10) * 10 + 100 # 均值为100,标准差为10的正态分布数据
print(股票价格)
4. 组合成时间序列数组
将时间戳和数值数据组合成一个二维数组或结构数组。常见方法是使用NumPy的record arrays或pandas(但本教程聚焦NumPy)。
# 使用结构化数组
时间序列 = np.array([(时间戳数组[i], 股票价格[i]) for i in range(10)],
dtype=[('date', 'datetime64[D]'), ('price', 'float64')])
print(时间序列)
或者,如果你只需要数值数据随时间变化,可以保持为两个一维数组,通过索引关联。
时间序列处理基础
一旦构建了时间序列数组,就可以进行各种操作。
索引和切片
NumPy数组支持基于位置的索引和切片,便于提取特定时间段的数据。
# 提取前5天的价格数据
前五天价格 = 股票价格[:5]
print(前五天价格)
缺失值处理
时间序列数据中常有缺失值。NumPy提供了np.nan表示缺失,可以使用掩码数组处理。
# 示例:模拟缺失值
股票价格_with_nan = 股票价格.copy()
股票价格_with_nan[2] = np.nan # 假设第3天数据缺失
print(股票价格_with_nan)
# 使用np.isnan检测缺失值
缺失索引 = np.where(np.isnan(股票价格_with_nan))[0]
print(f"缺失值索引: {缺失索引}")
滑动窗口计算:移动平均与标准差
滑动窗口是一种常见的时间序列分析方法,用于平滑数据或计算局部统计量。
1. 滑动窗口概念
滑动窗口将数据划分为重叠或非重叠的子序列,例如,一个窗口大小为3的滑动窗口在数组[1,2,3,4,5]上会生成子数组[1,2,3]、[2,3,4]、[3,4,5]。
2. 计算移动平均
移动平均(Moving Average, MA)通过计算窗口内数据的平均值来平滑时间序列。
使用np.convolve方法:
def moving_average(data, window_size):
"""计算简单移动平均"""
if window_size <= 0 or window_size > len(data):
raise ValueError("窗口大小必须为正且不超过数据长度")
# np.convolve用于卷积,通过归一化计算平均
weights = np.ones(window_size) / window_size
ma = np.convolve(data, weights, mode='valid') # mode='valid'避免边界效应
return ma
# 示例
数据 = np.array([10, 20, 30, 40, 50])
窗口大小 = 3
ma_result = moving_average(数据, 窗口大小)
print(f"移动平均结果: {ma_result}")
使用NumPy 1.20+的sliding_window_view(更高效):
# 确保NumPy版本支持
if hasattr(np.lib.stride_tricks, 'sliding_window_view'):
def moving_average_sliding(data, window_size):
windows = np.lib.stride_tricks.sliding_window_view(data, window_size)
ma = np.mean(windows, axis=1)
return ma
ma_sliding = moving_average_sliding(数据, 窗口大小)
print(f"使用sliding_window_view的移动平均: {ma_sliding}")
else:
print("您的NumPy版本较低,请升级以使用sliding_window_view。")
3. 计算移动标准差
移动标准差(Moving Standard Deviation)用于衡量数据的波动性。
类似地,使用滑动窗口计算标准差。
def moving_std(data, window_size):
"""计算移动标准差"""
if window_size <= 0 or window_size > len(data):
raise ValueError("窗口大小必须为正且不超过数据长度")
# 使用sliding_window_view(如果可用)
if hasattr(np.lib.stride_tricks, 'sliding_window_view'):
windows = np.lib.stride_tricks.sliding_window_view(data, window_size)
std = np.std(windows, axis=1, ddof=1) # ddof=1用于样本标准差
else:
# 备用方法:使用循环或np.convolve(但标准差计算更复杂)
std = np.array([np.std(data[i:i+window_size], ddof=1) for i in range(len(data)-window_size+1)])
return std
std_result = moving_std(数据, 窗口大小)
print(f"移动标准差结果: {std_result}")
4. 边界处理
滑动窗口计算时,边界数据可能不足。常见处理方式包括:
- 'valid':只计算完整窗口的数据(如上述示例)。
- 'same':输出大小与输入相同,边界用填充值。
- 填充数据:如用前值或后值填充。
实战:股票价格趋势分析
现在,我们将应用所学知识分析股票价格趋势。假设我们有某股票过去30天的每日收盘价数据。
步骤1:准备数据
使用NumPy生成模拟数据或加载真实数据(本教程使用模拟数据)。
# 生成模拟股票价格数据
np.random.seed(123)
days = 30
时间戳 = np.arange('2023-01-01', days, dtype='datetime64[D]') # 30天的时间戳
股票价格 = 100 + np.cumsum(np.random.randn(days) * 2) # 随机游走模拟价格
print(f"时间戳: {时间戳[:5]}...")
print(f"股票价格(前5天): {股票价格[:5]}")
步骤2:计算移动平均和标准差
使用滑动窗口分析趋势和波动。
窗口大小 = 5 # 例如,5天移动平均
# 计算移动平均
移动平均_价格 = moving_average(股票价格, 窗口大小)
# 计算移动标准差
移动标准差_价格 = moving_std(股票价格, 窗口大小)
print(f"移动平均(前几个值): {移动平均_价格[:5]}")
print(f"移动标准差(前几个值): {移动标准差_价格[:5]}")
步骤3:趋势分析
通过比较原始价格和移动平均,可以识别趋势。
- 当价格高于移动平均时,可能表示上升趋势。
- 当价格低于移动平均时,可能表示下降趋势。
- 移动标准差高表示波动大,风险较高。
# 简单趋势判断
趋势 = []
for i in range(len(移动平均_价格)):
if 股票价格[i+窗口大小-1] > 移动平均_价格[i]:
趋势.append("上升")
else:
趋势.append("下降")
print(f"趋势判断(示例): {趋势[:5]}")
步骤4:可视化(可选,使用matplotlib)
虽然NumPy不直接绘图,但可以结合matplotlib可视化结果。
# 如果需要可视化,安装matplotlib: pip install matplotlib
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 6))
plt.plot(时间戳[窗口大小-1:], 股票价格[窗口大小-1:], label='原始价格', color='blue')
plt.plot(时间戳[窗口大小-1:], 移动平均_价格, label=f'{窗口_size}天移动平均', color='red')
plt.fill_between(时间戳[窗口大小-1:],
移动平均_价格 - 移动标准差_价格,
移动平均_价格 + 移动标准差_价格,
color='gray', alpha=0.3, label='标准差带')
plt.xlabel('日期')
plt.ylabel('价格')
plt.title('股票价格趋势分析')
plt.legend()
plt.show()
总结与扩展
通过本教程,你学会了:
- 构建时间序列数组:使用NumPy和datetime模块创建时间戳和数值数组。
- 时间序列处理基础:索引、切片和缺失值处理。
- 滑动窗口计算:实现移动平均和移动标准差,使用
np.convolve或sliding_window_view。 - 实战应用:在股票价格趋势分析中,利用滑动窗口识别趋势和波动。
扩展学习
- 高级滑动窗口:探索加权移动平均(如指数移动平均)。
- 性能优化:对于大数据集,考虑使用NumPy的向量化操作避免循环。
- 集成其他库:结合pandas进行更复杂的时间序列分析。
NumPy是时间序列分析的强大工具,掌握这些基础后,你可以进一步探索机器学习或深度学习中的时间序列预测。祝你学习愉快!
注意:本教程使用模拟数据,实际应用中请确保数据来源可靠。NumPy版本建议1.20或更高以获得最佳功能支持。