作者: 屈希峰, 资深 Python 工程师, 知乎多个专栏作者
01 概述
时间序列 (Time series) 是指将某种现象某一个统计指标在不同时间上的各个数值, 按时间先后顺序排列而形成的序列. 时间序列法是一种定量预测方法, 也称简单外延法, 在统计学中作为一种常用的预测手段被广泛应用.
时间序列分析在第二次世界大战前应用于经济预测."二战" 中和 "二战" 后, 在军事科学, 空间科学, 气象预报和工业自动化等领域的应用更加广泛.
时间序列分析 (Time Series Analysis) 是一种动态数据处理的统计方法. 该方法基于随机过程理论和数理统计学方法, 研究随机数据序列所遵从的统计规律, 用于解决实际问题. 时间序列构成要素是现象所属的时间和反映现象发展水平的指标数值 , 如下图所示.
▲时间序列
时间序列中的每个观察值大小, 是影响变化的各种不同因素在同一时刻发生作用的综合结果. 从这些影响因素发生作用的大小和方向变化的时间特性来看, 这些因素造成的时间序列数据的变动分为如下 4 种类型.
趋势性: 某个变量随着时间进展或自变量变化, 呈现出一种比较缓慢而长期的持续上升, 下降, 停留的同性质变动趋向, 但变动幅度可能不相等.
周期性: 某因素由于外部影响随着自然季节的交替出现高峰与低谷的规律.
随机性: 个别为随机变动, 整体呈统计规律.
综合性: 实际变化情况是几种变动的叠加或组合. 预测时设法过滤除去不规则变动, 突出反映趋势性和周期性变动.
02 实例
时间序列代码示例如下所示.
代码示例1
- from bokeh.sampledata.stocks import AAPL
- import numpy as np
- # 数据
- aapl = np.array(AAPL['adj_close'])
- aapl_dates = np.array(AAPL['date'], dtype=np.datetime64)
- window_size = 30
- Windows = np.ones(window_size)/float(window_size)
- aapl_avg = np.convolve(aapl, Windows, 'same')
- # 画布
- p = figure(width=800, height=350, x_axis_type="datetime")
- # 图层
- p.circle(aapl_dates, aapl, size=4, color='darkgrey', alpha=0.2, legend='close')
- p.line(aapl_dates, aapl_avg, color='red', legend='avg')
- # 自定义属性
- p.title.text = "AAPL One-Month Average"
- p.legend.location = "top_left"
- p.grid.grid_line_alpha=0
- p.xaxis.axis_label = 'Date'
- p.yaxis.axis_label = 'Price'
- p.ygrid.band_fill_color="gray"
- p.ygrid.band_fill_alpha = 0.1
- p.legend.click_policy="hide" # 点击图例显示隐藏数据
- # 显示结果
- show(p)
运行结果如图 1 所示.
▲图 1 代码示例1运行结果
代码示例1第 8 行 np.convolve 用来计算离散点的移动平均值; 第 10 行在画布中预定义 x 轴的数据类型为 datetime; 第 12 行绘制离散的点(散点图); 第 13 行绘制曲线. 第 15~22 行是关于图例, 坐标轴的一些自定义属性, 将在后文进行详述.
代码示例2
import numpy as np from bokeh.models import ColumnDataSource, CustomJSTransform from bokeh.plotting import figure from bokeh.io import output_file, show from bokeh.sampledata.stocks import AAPL, GOOG from bokeh.transform import transform # 数据转换为时间类型 def datetime(x): return np.array(x, dtype=np.datetime64) # 画布 plot = figure(x_axis_type="datetime", title="Normalized Stock Closing Prices", plot_width=800, plot_height=350) # 其他 plot.background_fill_color = "#f0f0f0" plot.xgrid.grid_line_color = None plot.ygrid.grid_line_color = "black" plot.ygrid.grid_line_alpha = 0.1 plot.xaxis.axis_label = 'Date' plot.yaxis.axis_label = 'Normalized Price' # 数据 aapl_source = ColumnDataSource(data=dict( aapl_date=datetime(AAPL['date']), aapl_close=AAPL['adj_close'], )) goog_source = ColumnDataSource(data=dict( goog_date=datetime(GOOG['date']), goog_close=GOOG['adj_close'], )) # CustomJSTransform v_func = """ const first = xs[0] const norm = new Float64Array(xs.length) for (let i = 0; i < xs.length; i++) { norm[i] = xs[i] / first } return norm """ normalize = CustomJSTransform(v_func=v_func) # 绘图 plot.line(x='aapl_date', y=transform('aapl_close', normalize), line_width=2, color='#cf3c4d', alpha=0.6,legend="Apple", source=aapl_source) plot.line(x='goog_date', y=transform('goog_close', normalize), line_width=2, color='#2f7bce', alpha=0.6, legend="Google", source=goog_source) plot.legend.location='top_left' # 显示 show(plot)
运行结果如图 3 所示.
▲图 3 代码示例2运行结果
代码示例2第 11 行在画布中预定义 x 轴的数据类型为 datetime; 第 41,43 行绘制两条时间序列曲线. 第 31 行采用 JavaScript 函数对 y 轴数据进行标准化处理, 如果对 JavaScript 函数不熟悉, 可以在 Pandas 中对原始数据进行预处理, 然后直接进行调用.
代码示例3
from bokeh.models import BoxAnnotation from bokeh.sampledata.glucose import data as data_or import numpy as np # 工具条 TOOLS = "pan,wheel_zoom,box_zoom,reset,save" # 数据 data = data_or.sort_index()['2010-03-24':'2010-03-25'] # 画布 p = figure(x_axis_type="datetime", tools=TOOLS, title="Glocose Readings, Oct 4th (Red = Outside Range)") # 绘图 p.line(np.array(data.index.tolist(), dtype=np.datetime64), data.glucose.values, line_color='gray') p.circle(data.index, data.glucose, color='grey', size=1) # 箱形标记 p.add_layout(BoxAnnotation(top=80, fill_alpha=0.1, fill_color='red', line_color='red')) p.add_layout(BoxAnnotation(bottom=180, fill_alpha=0.1, fill_color='red', line_color='red')) # 其他 p.background_fill_color = "#efefef" p.xgrid.grid_line_color=None p.xaxis.axis_label = 'Time' p.yaxis.axis_label = 'Value' show(p)
运行结果如图 3 所示.
▲图 3 代码示例3运行结果
代码示例3在时间序列曲线的基础上增加了箱形标记, 深色区域为需要突出显示的数据, 读者仅需要知道这种标记展示方式, 后文会详述箱形标记方法.
代码示例4
import numpy as np from bokeh.layouts import gridplot from bokeh.sampledata.stocks import AAPL, GOOG, IBM, MSFT def datetime(x): return np.array(x, dtype=np.datetime64) # 画布 1 p1 = figure(x_axis_type="datetime", title="Stock Closing Prices") p1.grid.grid_line_alpha=0.3 p1.xaxis.axis_label = 'Date' p1.yaxis.axis_label = 'Price' # 绘图 1 p1.line(datetime(AAPL['date']), AAPL['adj_close'], color='#A6CEE3', legend='AAPL') p1.line(datetime(GOOG['date']), GOOG['adj_close'], color='#B2DF8A', legend='GOOG') p1.line(datetime(IBM['date']), IBM['adj_close'], color='#33A02C', legend='IBM') p1.line(datetime(MSFT['date']), MSFT['adj_close'], color='#FB9A99', legend='MSFT') p1.legend.location = "top_left" # 数据 2 aapl = np.array(AAPL['adj_close']) aapl_dates = np.array(AAPL['date'], dtype=np.datetime64) window_size = 30 Windows = np.ones(window_size)/float(window_size) aapl_avg = np.convolve(aapl, Windows, 'same') # 画布 2 p2 = figure(x_axis_type="datetime", title="AAPL One-Month Average") p2.grid.grid_line_alpha = 0 p2.xaxis.axis_label = 'Date' p2.yaxis.axis_label = 'Price' p2.ygrid.band_fill_color = "olive" p2.ygrid.band_fill_alpha = 0.1 p2.circle(aapl_dates, aapl, size=4, legend='close', color='darkgrey', alpha=0.2) p2.line(aapl_dates, aapl_avg, legend='avg', color='navy') p2.legend.location = "top_left" # 显示 show(gridplot([[p1,p2]],plot_width=400, plot_height=400))
运行结果如图 4 所示.
▲图 4 代码示例4运行结果
代码示例4采用网格布局显示两张时间序列曲线, 可以对某一曲线进行横向比较.
代码示例5
from numpy import pi, exp, linspace, sin import time from bokeh.util.browser import view from bokeh.document import Document from bokeh.embed import file_html from bokeh.models.glyphs import Circle from bokeh.models import Plot, DatetimeAxis, ColumnDataSource, PanTool, WheelZoomTool from bokeh.resources import INLINE # 数据 N = 200 x = linspace(-2 * pi, 2 * pi, N) y = sin(x)*exp(-x) # 创建一组时间数据, 以当前时间往后延伸 24 小时 times = (linspace(0, 24*3600, N) + time.time()) * 1000 source = ColumnDataSource(data=dict(x=x, y=y, times=times)) # 画布 plot = Plot(min_border=80, plot_width=800, plot_height=350, background_fill_color="#efefef") # 绘图 circle = Circle(x="times", y="y", fill_color="red", size=3, line_color=None, fill_alpha=0.5) plot.add_glyph(source, circle) # 设置时间轴 plot.add_layout(DatetimeAxis(), 'below') plot.add_layout(DatetimeAxis(), 'left') # 设置工具条 plot.add_tools(PanTool(), WheelZoomTool(zoom_on_axis=False, speed=1/5000.)) # 显示 show(plot)
运行结果如图 5 所示.
▲图 5 代码示例5运行结果
代码示例5采用 modes 接口进行图形绘制, 第 25 行为该图形增加平移工具并自定义滚轮缩放的速率. 读者仅需要了解采用这种方式进行绘图的基本流程即可.
关于作者: 屈希峰, 资深 Python 工程师, Bokeh 领域的实践者和布道者, 对 Bokeh 有深入的研究. 擅长 Flask,MongoDB,Sklearn 等技术, 实践经验丰富. 知乎多个专栏 (Python 中文社区, Python 程序员, 大数据分析挖掘) 作者, 专栏累计关注用户十余万人.
本文摘编自 《 Python 数据可视化: 基于 Bokeh 的可视化绘图 》 , 经出版方授权发布.
延伸阅读 《Python 数据可视化》
点击上图了解及购买
来源: http://www.tuicool.com/articles/yMzYRj2