plotly绘图说明

(可以不看的废话)

从上篇博客开始就一直在忙,忙了好几个月的文章以后,最近终于是在一个deadline之前把文章投了出去,所以也就可以重新回归写博客的日子了。在新年之前,再看看能不能写一两篇的博客吧。当然看的人可能也不是很多就是。
关于今天的这篇博客,主要还是来讲一下我现在超级超级超级喜爱和用的也很得心应手的python的一个画图的包--plotly。

更新预告(flag): 可能会写一些关于speciation的东西。

plotly介绍

plotly是一个开源的python的库,本质上它应该是一个收费的企业级的软件,官网在plotly,它对自己公司的定位即

Modern Analytics Apps for the Enterprise

所以其实是它们的公司想必除了开发plotly以外还是想做一些分析的平台的工作的,应该是偏向于统计分析的部分,当然这不是我们需要关注的地方。回到plotly本身,plotly其实主要是一个基于d3.js开发的一个js的库,而除了js的开发以外,它也对不同的编程语言开发了多种多样的库和工具包。例如R、matlab、python。由于它的核心代码其实js,其它的工具包和库其实仅仅是作为一个相应的编程软件对js的一个API,所以我们就不详细的讨论它的源代码了 (毕竟我也看不太懂。。。),而在plotly.py中,相关的内容也藏的比较深,结构比较复杂,我也不想过于深入的去讨论它的源码。

除了对plotly的背景介绍外,plotly能做的事情当然是重中之重的介绍点。基于js的绘图库最大的特点就是可交互。最原始的output结果是html格式的,所以输出的结果就是一个使用plotly.js进行绘制的一个网页,当然如果是需要它生成一个静态的图的话也是没什么问题的,它同样也支持直接生成pdf,png之类的。

plotly的资料

plotly这个软件在国内的使用率似乎并不高,所以很多中文的相关资料都十分的匮乏,所以资料方面也不是很多,这里就只放一个plotly的官网以及一个Stack Overflow的专区的链接好了。

官网链接
stack overflow tagged plotly

plotly的起始(哲学)

由于我使用plotly也有一段时间了,加上如果我从基础开始讲一个库的使用其实也十分的没有意思,还不如让你们直接去看官网的教程(毕竟我自己就是这么开始的),所以我在这里从着重讲一些高度概括的,一些更为核心的东西。不要求初学者一看就能懂,但是可以在听说了这些哲学以后,在学习和掌握plotly中更为得心应手,我也觉得这才是一个博客的意义所在,而不是照搬照抄,那完全只是一堆冗余知识的堆叠。

  1. 层/踪迹(trace)的思想

plotly的设计上相较于matplotlib这些库,思想上更为接近photoshopillustrator。所以对于接触过这些的人来说也更为便于学习和理解。意思就是说,在画一张图时,基本单位应该是一层,这一层原则上应该是同类的对象(例如scatter, bar, box, heatmap等),初学者都可以把这些认为是一些对象(高级玩家可以自定义对象,因为像heatmap就是一堆bar的堆叠嘛。)

  1. data与layout分离

除了上一个中说的层的思想,层都是在data内部的。然后就是说layout和data都是分离的,这个其实很好理解,因为像matplotlib之类的绘图库其实也差不多,所以这个也不多加讲解。

  1. 基于dict (json)的数据结构

在上述的plotly的介绍中其实讲到了一个很重要的一点,也就是plotly的核心是一个js的库,那么与库交流时,最常见的是一种叫json的数据结构,json的数据结构在python中不是一种常规的数据结构,但是最为相近的也就是dict,所以plotly.py在设计时,也就将一张图的数据,定位在dict上。
那么plotly的这种思想有什么特点呢?在后面具体的例子中大家应该会有更深的体会,这里只简单的说。dict类似的数据结构,非常方便大家记忆和查找相关的属性。像最为基础的python的一个绘图库matplotlib,我用不惯的原因很大程度上就是因为它的互相引用和数据结构过于复杂弯曲,一个figure有axes,axes又可以绕回figure,所以不是一个单向的纯粹的层级结构。plotly的设计则十分的简洁明了。

  1. 子图(subfigure)和坐标轴(axes)及其标签(ticklabels)是相互独立的

在绘图时,除开了以上几点,最需要细心的地方也是最容易出问题的地方就是子图或者坐标轴这些问题了。其中坐标轴的标签也是劝退大部分人的地方,plotly的设计我也不确定是好是坏,但是它将每一个子图和坐标轴割裂开了,通过layout中的一些名称进行绑定,你可以使坐标轴绑定多个子图,也可以让子图自由的伸展、排布成不同的布局。同时,标签这些也是很容易的去设置,只要你了解不论是类别变量的标签(ticktext)还是数值变量的标签(ticktext)其实本质都是基于数值变量的标签(tickvalues),前两个是看到的,最后一个大部分时候是隐藏的

  1. 交互动画的开关机制

上面讲的一些其实都是跟交互没太大关系的,最终当然也能实现交互的结果,不过那些更多的是由于本身就自带的缩放(scale/zoom)的功能了。plotly中,所有的交互,例如button、slider和play都是在layout中的,这一点一定程度上是为了适应js的代码吧。因为plotly的基本逻辑是这样的,你把所有你需要绘制的东西全部一次性的放在一个figure内部,然后通过layout中的updatemeanus内的开关进行调控。而这些开关其实都直接对应到了js的一些function,然后通过这些函数实现点击(click)button/拖动slider时,隐藏某些traces,显示某些traces这样子的功能以达到交互(interactive)的功能。

plotly的哲学基本上以上的几点,在了解和知道这些的基础上,我觉得可以更好的去理解和使用这个绘图的库。

plotly的基本使用(结合上述提到的所谓plotly哲学的一些demo)

trace和dict

import plotly
import plotly.graph_objs as go

import numpy as np

N = 1000
random_x = np.random.randn(N)
random_y = np.random.randn(N)

# Create a trace
trace1 = go.Scatter(
    x = random_x,
    y = random_y,
    mode = 'markers'
)
random_y2= np.random.randn(N)

trace2 = go.Bar(x = random_x,y = random_y2)
data = [trace,trace2]

plotly.offline.plot(dict(data=[trace,trace2]))
demo1

最终它可以输出这样的一个图,其实理论上说这个图(毫无意义),也很,但其实我只是为了说明bar 图和scatter图的共存,在plotly中,他们两个属于两个互不干扰的trace,并且,每次初始化一个trace时,除了直接使用go.Scatter或者go.Bar以外,内容物真的只需要通过类似于dict的方式就可以指定。如上的代码。

subplot、interactive和dict

import plotly
import plotly.graph_objs as go
import plotly.figure_factory as ff
import numpy as np
from sklearn.datasets import fetch_california_housing
from sklearn.preprocessing import *
dataset = fetch_california_housing()
X_full, y_full = dataset.data, dataset.target

X = X_full[:, [0, 5]]

distributions = dict([
    ('Unscaled data', X),
    ('Data after standard scaling',
        StandardScaler().fit_transform(X)),
    ('Data after min-max scaling',
        MinMaxScaler().fit_transform(X)),
    ('Data after max-abs scaling',
        MaxAbsScaler().fit_transform(X)),
    ('Data after robust scaling',
        RobustScaler(quantile_range=(25, 75)).fit_transform(X)),
    ('Data after power transformation (Yeo-Johnson)',
     PowerTransformer(method='yeo-johnson').fit_transform(X)),
    ('Data after power transformation (Box-Cox)',
     PowerTransformer(method='box-cox').fit_transform(X)),
    ('Data after quantile transformation (gaussian pdf)',
        QuantileTransformer(output_distribution='normal')
        .fit_transform(X)),
    ('Data after quantile transformation (uniform pdf)',
        QuantileTransformer(output_distribution='uniform')
        .fit_transform(X)),
    ('Data after sample-wise L2 normalizing',
        Normalizer().fit_transform(X)),
])

y = minmax_scale(y_full)
# scale the output between 0 and 1 for the colorbar

# 
fig = plotly.tools.make_subplots(rows=2,cols=2,specs=[[{},None],[{},{}]],shared_xaxes=True,shared_yaxes=True)
#This is the format of your plot grid:
#[ (1,1) x1,y1 ]      (empty)    
#[ (2,1) x2,y2 ]  [ (2,2) x3,y3 ]
# 初始化了一个如上的一个figure布局,以便进行绘图

traces = []
for scaler,scaled_X in list(distributions.items())[:1]:
# 只画第一个的话,如下
    _fig1 = ff.create_distplot([scaled_X[:,0]], ['a'],show_hist=False,show_rug=False)
    _fig2 = ff.create_distplot([scaled_X[:,1]],['a'],show_hist=False,show_rug=False)
    trace = go.Scatter(x=scaled_X[:,0],y=scaled_X[:,1],mode='markers',marker=dict(color=y),yaxis='y2',xaxis='x2',name=scaler,legendgroup=scaler)
    fig.append_trace(go.Scatter(x=_fig1.data[0]['x'],y=_fig1.data[0]['y'],mode='lines',name='upper left',legendgroup=scaler),1,1)
    fig.append_trace(go.Scatter(x=_fig2.data[0]['y'],y=_fig2.data[0]['x'],mode='lines',name='down right',legendgroup=scaler),2,2)
    fig.append_trace(trace,2,1)

fig.layout.xaxis1.domain = [0,0.8]
fig.layout.xaxis2.domain = [0,0.8]
fig.layout.xaxis3.domain = [0.85,1.0]
fig.layout.yaxis1.domain = [0.85,1.0]
fig.layout.yaxis2.domain = [0,0.8]
fig.layout.yaxis3.domain = [0,0.8]
fig.layout.width = 1000
fig.layout.height = 1000
plotly.offline.plot(fig)

上面的代码画出来是这样的。


demo2

由于是交互的,我觉得大家最好还是自己试一试会体会更深。(当然我要是放在jupyter notebook上也就更好了,但是我有点懒。。。)

那么我们上面的代码仅仅只画了一个,那怎么能行呢!对吧。接下来我们在上面的代码的基础上,再加一些东西,使它更有意思起来。

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

推荐阅读更多精彩内容

  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,097评论 1 32
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,094评论 4 62
  • 这是我在校园网上看到曾经一位学姐留诗,感觉很美。但是后来又特意咨询了学中文的,说,对仗不工整blabla... 但...
    司徒小歪阅读 526评论 0 1