专栏首页华章科技沿用70多年的经典数据可视化方法,如何用Python实现?

沿用70多年的经典数据可视化方法,如何用Python实现?

导读:什么是时间序列?用来展示什么样的数据关系?怎样用Python实现?本文将为你解答。

作者:屈希峰,资深Python工程师,知乎多个专栏作者

来源:大数据DT(ID:hzdashuju)

01 概述

时间序列(Time series)是指将某种现象某一个统计指标在不同时间上的各个数值,按时间先后顺序排列而形成的序列。时间序列法是一种定量预测方法,也称简单外延法,在统计学中作为一种常用的预测手段被广泛应用。

时间序列分析在第二次世界大战前应用于经济预测。“二战”中和“二战”后,在军事科学、空间科学、气象预报和工业自动化等领域的应用更加广泛。

时间序列分析(Time Series Analysis)是一种动态数据处理的统计方法。该方法基于随机过程理论和数理统计学方法,研究随机数据序列所遵从的统计规律,用于解决实际问题。时间序列构成要素是现象所属的时间和反映现象发展水平的指标数值,如下图所示。

▲时间序列

时间序列中的每个观察值大小,是影响变化的各种不同因素在同一时刻发生作用的综合结果。从这些影响因素发生作用的大小和方向变化的时间特性来看,这些因素造成的时间序列数据的变动分为如下4种类型。

  1. 趋势性:某个变量随着时间进展或自变量变化,呈现出一种比较缓慢而长期的持续上升、下降、停留的同性质变动趋向,但变动幅度可能不相等。
  2. 周期性:某因素由于外部影响随着自然季节的交替出现高峰与低谷的规律。
  3. 随机性:个别为随机变动,整体呈统计规律。
  4. 综合性:实际变化情况是几种变动的叠加或组合。预测时设法过滤除去不规则变动,突出反映趋势性和周期性变动。

02 实例

时间序列代码示例如下所示。

  • 代码示例①
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  
window = np.ones(window_size)/float(window_size)  
aapl_avg = np.convolve(aapl, window, '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 代码示例①运行结果

代码示例①第8行np.convolve用来计算离散点的移动平均值;第10行在画布中预定义x轴的数据类型为datetime;第12行绘制离散的点(散点图);第13行绘制曲线。第15~22行是关于图例、坐标轴的一些自定义属性,将在后文进行详述。

  • 代码示例②
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 代码示例②运行结果

代码示例②第11行在画布中预定义x轴的数据类型为datetime;第41、43行绘制两条时间序列曲线。第31行采用JavaScript函数对y轴数据进行标准化处理,如果对JavaScript函数不熟悉,可以在Pandas中对原始数据进行预处理,然后直接进行调用。

  • 代码示例③
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)")  
10.   
# 绘图  
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 代码示例③运行结果

代码示例③在时间序列曲线的基础上增加了箱形标记,深色区域为需要突出显示的数据,读者仅需要知道这种标记展示方式,后文会详述箱形标记方法。

  • 代码示例④
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  
window = np.ones(window_size)/float(window_size)  
aapl_avg = np.convolve(aapl, window, '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 代码示例④运行结果

代码示例④采用网格布局显示两张时间序列曲线,可以对某一曲线进行横向比较。

  • 代码示例⑤
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 代码示例⑤运行结果

代码示例⑤采用modes接口进行图形绘制,第25行为该图形增加平移工具并自定义滚轮缩放的速率。读者仅需要了解采用这种方式进行绘图的基本流程即可。

关于作者:屈希峰,资深Python工程师,Bokeh领域的实践者和布道者,对Bokeh有深入的研究。擅长Flask、MongoDB、Sklearn等技术,实践经验丰富。知乎多个专栏(Python中文社区、Python程序员、大数据分析挖掘)作者,专栏累计关注用户十余万人。

本文摘编自《Python数据可视化:基于Bokeh的可视化绘图》,经出版方授权发布。

延伸阅读《Python数据可视化》

本文分享自微信公众号 - 大数据(hzdashuju),作者:屈希峰

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-01-15

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 别人家的AI忙着探索未来,他们已经用AI在解决历史难题

    今年4月,英特尔公司与中国文物保护基金会建立合作,宣布采用人工智能技术以及无人机技术实施对于箭扣长城的修缮和保护。

    华章科技
  • 阿里智能餐厅落地!刷脸就吃,擦嘴就走!

    这两天,马云爸爸又出尽了风头。租房免押金、宣布成立达摩院、计划三年内向基础科学研发投资超过 1000 亿元……

    华章科技
  • 什么是折线图?怎样用Python绘制?怎么用?终于有人讲明白了

    导读:数据分析时经常用到的折线图,你真的懂了吗?可以用来呈现哪些数据关系?在数据分析过程中可以解决哪些问题?怎样用Python绘制折线图?本文逐一为你解答。

    华章科技
  • leetcode 860 —柠檬水找零(简单题)

    每位顾客只买一杯柠檬水,然后向你付 5 美元、10 美元或 20 美元。你必须给每个顾客正确找零,也就是说净交易是每位顾客向你支付 5 美元。

    ACM算法日常
  • 春节充电系列:李宏毅2017机器学习课程学习笔记24之结构化学习-Structured SVM(part 2)

    【导读】我们在上一节的内容中已经为大家介绍了台大李宏毅老师的机器学习课程的Structured learning-Structured SVM(part 2),...

    WZEARW
  • 什么是单点登录?单点登录的三种实现方式

    单点登录SSO(Single Sign On)说得简单点就是在一个多系统共存的环境下,用户在一处登录后,就不用在其他系统中登录,也就是用户的一次登录能得到其他所...

    三哥
  • 基于情感词典、k-NN、Bayes、最大熵、SVM的情感分析比较及优缺点

    机器学习AI算法工程
  • 用上索引就一定比全表扫描快?

    在外 5 分钟,全身都能湿透的季节终于还是到来了。作为行政的小C,原本在空调下吹着风,贴着各处提交来的发票,倒也不算太糟糕。

    Lenis
  • SpringBoot当中如何整合静态html(模拟SpringMVC)

    整合静态html(模拟SpringMVC): 1)在上一个项目中,在src/main目录下,添加resources/static/index.html:(参考目...

    马克java社区
  • 时间序列分析这件小事(二)--自回归

    说到时间序列,那么就必须提起自回归了。什么是自回归呢,就是说未来的一个时点可以用之前的时点来进行回归预测,还是那一串数字,但是时间状态不同了,存在不同阶的时滞。

    钱塘小甲子

扫码关注云+社区

领取腾讯云代金券