Python 数据可视化:高级制图案例剖析

Plotly 的内容非常多,不过,本着“弱水三千、只取一瓢饮”的原则,本文仅详细介绍一些基本知识,并借着这些知识向读者说明掌握 Plotly 制图的基本方法,特别是本达人课中反复强调过的方法——阅读文档。理解和使用这些方法,才是将来在项目实践中所向无敌的保证。

本课会再选几个示例展示一些高级的制图方法。

4.4.1 地理信息可视化

地理信息可视化是数据可视化中一个非常重要的分支。前面若干课的工具都能实现地理信息可视化,但是此前并没有介绍,因为还要安装很多别的东西,比较麻烦。其实 Plotly 提供了比较简单的实现方式,因为它整合了 Mapbox。

Mapbox,官方网站:www.mapbox.com,是一家向移动端和 Web 应用提供地图数据的服务商。

首先,要到 Mapbox 官方网站注册,然后取得 token;接下来就能做地理信息可视化了。

import plotly
import plotly.graph_objs as go

mapbox_access_token = "your_mapbox_access_token"

data = [go.Scattermapbox(lat = ['31.3'],
                         lon = ['120.7'],
                         mode = 'markers',
                         marker = dict(size = 20, colo r= 'red'),
                         text=['Soochow'],
                        )]
layout = go.Layout(autosize = True, 
                   hovermode = 'closest',
                   mapbox = dict(accesstoken = mapbox_access_token,
                                 bearing = 0,
                                 center = dict(lat = 31.3, lon = 120.7),
                                 pitch = 0,
                                 zoom=10
                                ),
                  )

fig = dict(data=data, layout=layout)
plotly.offline.plot(fig, filename='Soochow')

enter image description here

这里的截图仅是部分界面,看到图中的红点了吧,那个就是上面的程序中要在地图上标记的点。下面就看看是如何实现这种效果的。

跟前面各节绘制的图示一样,地理信息的图示在 Plotly 中也是一种 Trace 对象,它由 plotly.graph_objs.Scattermapbox 生成。

go.Scattermapbox(arg=None, connectgaps=None, customdata=None, customdatasrc=None, fill=None, fillcolor=None, hoverinfo=None, hoverinfosrc=None, hoverlabel=None, hovertext=None, hovertextsrc=None, ids=None, idssrc=None, lat=None, latsrc=None, legendgroup=None, line=None, lon=None, lonsrc=None, marker=None, mode=None, name=None, opacity=None, selected=None, selectedpoints=None, showlegend=None, stream=None, subplot=None, text=None, textfont=None, textposition=None, textsrc=None, uid=None, unselected=None, visible=None, **kwargs)

在本例中,使用了部分参数,具体如下。

  • lat = ['31.3']:所标记地点的纬度,以北纬为正数。
  • lon = ['120.7']:所标记地点的经度,以东经为正数。注意,lat 和 lon 两个参数的值都是列表,也就意味着还可以标记多个地点,只是本例中只标记了一个地点。
  • mode='markers':所标记地点在图上显示符号。
  • marker=dict(size=20,color='red'):对标记符号的大小、颜色等属性的设置。
  • text=['Soochow']:标记点的文本显示。当鼠标移动到该点时会显示此列表中的元素。

只有 Trace 对象,最终还不能得到图示结果。Trace 对象仅是地理信息,其背景图应该是地图,这就要在 go.Layout 中指定要读入的地图了。在以往的示例中,虽然也多次应用它,但是所使用的参数与本示例有差别,毕竟这里要用地图作为布局了。

  • autosize = True:确定图示自动适应页面大小。
  • hovermode:设置鼠标悬停的交互操作,通常与之配套操作的还有参数 clickmode。默认值为 'closest',意即鼠标靠近标记对象实现交互操作。
  • mapbox:这是实现地图作为背景的关键参数。它的值是以字典形式提供的跟地图有关的属性映射。
    • accesstoken:前文已经提到过的 Mapbox,此键的值就是在 Mapbox 上注册后获得的 token。
    • bearing:默认值为 0。用于设置地图上的方位角。
    • center:以 {'lon': number, 'lat': number} 的形式设置最终图示中心的经纬度位置。
    • pitch:设置观察地图的角度(以度为单位),即俯视角度。默认值为 0 度,表示垂直于地图表面观察。
    • zoom:所显示的地图的层级,数量越大,显示的范围越小。若为 0,则显示的是世界地图;本例中使用了 zoom=10,显示了我朝的“街道”和“镇”这一级的地图。当然,因为在网页中呈现的地图是具有交互性的,还可以通过扩大、缩小操作,实现呈现地图范围的变化。

在上述基础上,再用江苏省各城市数据,标记出各个城市的位置。

import pandas as pd

df = pd.read_csv("/Users/qiwsir/Documents/Codes/DataSet/jiangsu/city_population.csv")

mapbox_token = "your_mapbox_access_token"

lat = df.latd    # 经度(Longitude) 纬度(Latitude)
lon = df.longd
locations_name = df.name   # 城市名称

data = [
    go.Scattermapbox(
        lat = lat,
        lon = lon,
        mode = "markers",
        marker = dict(size=17, 
                      color='rgb(255, 0, 0)', 
                      opacity=0.7),  
        text = locations_name,
        hoverinfo = 'text',
    ),
    go.Scattermapbox(
        lat = lat,
        lon = lon,
        mode = "markers",
        marker = dict(size=8, 
                      color='rgb(242, 177, 172)', 
                      opacity=0.7),
        text = locations_name,
        hoverinfo = 'text'
    )
]

layout = go.Layout(
    title = "The City of Jiangsu",
    autosize = True,
    hovermode = "closest",
    showlegend = False,
    mapbox = dict(accesstoken=mapbox_token, 
                  bearing=0, 
                  center=dict(lat=31,lon=120),
                  pitch=0,
                  zoom=5,
                  style='light'),
)

fig = dict(data=data, layout=layout)
plotly.offline.plot(fig, filename="jiangsu_city_map")

输出结果局部效果:

enter image description here

4.4.2 金融数据可视化

金融领域对数据可视化有着非常迫切的需要,比如股票市场,常以多种可视化方式表示不同类别的数据,而这些数据通常都有一个重要的维度:时间——严格讲是时刻,只不过是不同单位罢了。

先看下面的示例(数据来源:https://github.com/qiwsir/DataSet/tree/master/appl)。

appl_df = pd.read_csv("/Users/qiwsir/Documents/Codes/DataSet/appl/appl.csv", 
                      index_col=['date'], parse_dates=['date'])
appl_df.head()

close volume open high low
date
2018-10-17 221.19 22692880 222.30 222.64 219.3400
2018-10-16 222.15 28802550 218.93 222.99 216.7627
2018-10-15 217.36 30280450 221.16 221.83 217.2700
2018-10-12 222.11 39494770 220.42 222.88 216.8400
2018-10-11 214.45 52902320 214.52 219.50 212.3200

读入数据的同时将“date”列指定为 DataFrame 的索引,并转化为日期类型。在输出结果中可以看到该数据的各个特征,且索引是按照日期“从大到小”排列的。

data = [go.Scatter(x=appl_df.index, y=appl_df['high'])]

plotly.offline.init_notebook_mode(connected=True)
plotly.offline.iplot(data)

输出结果:

enter image description here

这是用 go.Scatter 绘制的折线图,但是 Plotly 在处理 X 轴数据的时候很聪明,并没有按照 appl_df 中索引顺序直接在坐标系绘图(按照时间“从大到小”),而是自动进行翻转,按照时间“从小到大”的自然顺序绘制了每日的股票交易最高价折线图。为了观察到时间跨度更小的某个范围的价格变化,可以利用交互功能中的“放大”操作工具。

从 appl_df 的数据集中可知,股票数据中还有 close、open、low 等交易数值。要把这些也在图中表示出来,可以创建相应的 Trace 对象——这是以前讲过的方法。Plotly 中提供了专门用户绘制股票交易数据的类(也是 Trace 对象)。

trace = go.Ohlc(
    x = appl_df.index,
    open = appl_df.open,
    high = appl_df.high,
    low = appl_df.low,
    close = appl_df.close,
)

plotly.offline.iplot([trace])

输出结果:

enter image description here

这里使用了一个新的 Trace 类 go.Ohlc,其作用就是绘制股票的开盘价(open)、最高价(high)、最低价(low)和收盘价(close)——简称“ohlc”。

注意观察图示:

  • 图示中的线不是折线(貌似是因为数据量比较大的缘故)——后续会换一种数据研究图线。
  • 在 X 轴下面有专门的时间控件,通过它可以选择显示任意时间间隔内的统计图。而且,这个时间空间是自动生成的。

为了便于研究图线,取少量数据,还是绘制 OHLC 图。

df30 = appl_df.head(30)

trace = go.Ohlc(x = df30.index,
                open = df30.open,
                high = df30.high,
                low = df30.low,
                close = df30.close,
               )

plotly.offline.iplot([trace])

输出结果:

还有 54% 的精彩内容
©著作权归作者所有,转载或内容合作请联系作者
支付 ¥3.99 继续阅读
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,100评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,308评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,718评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,275评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,376评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,454评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,464评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,248评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,686评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,974评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,150评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,817评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,484评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,140评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,374评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,012评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,041评论 2 351

推荐阅读更多精彩内容