python画图:Plotly学习笔记

本次笔记内容

  • plotly基本用法
  • 基本Scatter示例:go.Scatter(),按连续型/分类型变量着色
  • 基本Scatter示例:px(),按连续型/分类型变量着色
  • colorscale
  • subplots和facet
  • 各种layout:
    lengend字号size, 图标大小,hoverlabel大小;
    坐标轴字号大小,倾斜(不是斜体,是倾斜角度);
    网格线的隐藏;
    将x轴放在图上方,y轴放在图右边;
  • 注意

plotly基本用法

每一个trace就像一个独立的图层,互不干扰。data=[trace1, trace2...]将这些图层叠加在一起。
layout定义了data提供的信息之外的东西,比如plot title, 坐标轴的设置

import plotly
import plotly.graph_objects as go
trace1 = go.Scatter(...)
trace2 = go.Scatter(...)
layout1 = go.Layout(...)
fig = go.Figure(data=[trace1,trace2],
                layout=layout1)
fig.show() # 直接plot出来

# or 保存为.html格式的文件
plotly.offline.plot(dict(data=[trace1,trace2]), filename = 'XXX.html')

基本Scatter示例:go.Scatter(),按连续型变量着色

import plotly.express as px
import plotly.graph_objects as go
import plotly

tips = px.data.tips() # 用px里的示例数据
tips.head() #看一下
total_bill  tip sex smoker  day time    size
0   16.99   1.01    Female  No  Sun Dinner  2
1   10.34   1.66    Male    No  Sun Dinner  3
2   21.01   3.50    Male    No  Sun Dinner  3
3   23.68   3.31    Male    No  Sun Dinner  2
4   24.59   3.61    Female  No  Sun Dinner  4

trace_tip = go.Scatter(x=tips.total_bill.tolist(),
                       y=tips.tip.tolist(),
                       mode='markers+text',
                       # mode决定图上出现点,线,text等的组合形式
                       name = 'trace_tip',
                       marker=dict(color=tips['size'].tolist(), #  上色类别
                                   colorscale='Viridis',  # 指定颜色
                                   showscale=True,
                                   size=[i*10 for i in tips['size'].tolist()]),  #点大小
                       # showlegend=True,
                       text=tips['sex'].tolist(),
                       textposition='bottom center',
                       textfont=dict(size=18,color='LightSeaGreen'))
                       

# plotly.offline.plot(dict(data=[trace_tip]),filename='plot.html')
fig = go.Figure(data=[trace_tip]) 
# 如果在这个基础上接着画,那就[trace_tip1, trace_tip2...]
fig.show()

基本Scatter实例:go.Scatter(),按分类型变量着色

set(tips.day.tolist()) # {'Fri', 'Sat', 'Sun', 'Thur'}
# 这个set里每个类别,都要建立一个trace,4个trace叠在一起,才能交互式的点击选择各个类别
color_day_dict = dict(zip(set(tips.day.tolist()),
                          plotly.colors.colorbrewer.Set1))
# 设置一个颜色的对应关系

trace0 = [] #...还要写for,真麻烦啊=_=
for i in set(tips.day.tolist()):
    tips_temp = tips.loc[tips['day']==i,:] #记得要Slice一下input data
    trace0.append(go.Scatter(x=tips_temp.total_bill.tolist(),
                             y=tips_temp.tip.tolist(),
                             mode='markers',
                             name = i,
                             marker=dict(color=color_day_dict[i],
                                         size=10)))
fig = go.Figure(data=trace0)
fig.show() 

基本Scatter示例:px(),按连续型变量着色

tips['size10'] = tips['size']*10

fig = px.scatter(tips,x='total_bill',y='tip',size='size10',color='size',size_max=40,
                 color_continuous_scale=px.colors.sequential.Viridis,text='sex')
# 对于text的颜色大小位置,在update_trace里设置
fig.update_traces(textposition='bottom center',
                  textfont=dict(size=18,
                                color='LightSeaGreen'))

fig.write_html('plot.html')  # 保存为html格式
# fig.show()

基本Scatter示例:px(),按分类型变量着色

tips['size_fixed'] = 10 
# 在px中不能指定size=10,一定要是出现在input dataframe中的列才行

fig = px.scatter(tips,x='total_bill',
                 y='tip',color='day',
                 color_discrete_sequence=plotly.colors.colorbrewer.Set1)   
                 # color_discrete_sequence直接指定颜色set,不能指定颜色和类别的对应关系

fig = px.scatter(tips,x='total_bill',
                 y='tip',color='day',
                 color_discrete_map=color_day_dict,
                 # 用字典指定颜色和类别的对应关系 
                 size='size_fixed')  # size_fixed,是出现在tips这个dataframe中的column
fig.show()

colorscale

可以选择build-in的colorscale,也可以自己定义。在数据分布很极端的情况下,均匀的build-in color可能不太适用。
(不过build-in颜色盘已经很美了,能用尽量用)

# 通过colorscale自定义颜色区间对应关系,即0-65%的值会根据rgb(231,231,230) --- rgb(0,25,225)这个区间来着色。
trace_tip = go.Scatter(x=tips.total_bill.tolist(),
                       y=tips.tip.tolist(),
                       mode='markers',
                       marker=dict(color=tips['total_bill'].tolist(), #  上色类别
                                   showscale=True,
                                   size=10,
                                   colorscale=[[0,'rgb(231,231,230)'],
                                               [0.65,'rgb(0,25,225)'], # 当然你也可以做成均匀的颜色分布
                                               [0.75,'rgb(0,152,255)'],
                                               [0.85,'rgb(44,255,150)'],
                                               [0.95,'rgb(255,234,0)'],
                                               [1,'rgb(255,0,0)']],
                                   colorbar=dict(title='you_define'))  # colorbar上的title
                       )
                       
fig = go.Figure(data=[trace_tip]) 
fig.update_layout(autosize=False, height=600,width=800)
# 设置图片大小
fig.show()

参考https://plot.ly/python/colorscales/

subplots和facet

plotly express暂时(2020年)没有subplots, 可以使用facet分面做出subplots的效果。那似乎是不能把来源不同的图拼起来的。plotly.graph_objects可以整个subplots出来,将不同来源的plots拼在一起,还可以设置它们的位置。

# 比方说
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots

px.histogram(df,x='value',color='XXX',
             color_discrete_sequence=px.colors.qualitative.Set1,
             facet_col='variable', facet_col_wrap=4) # 用variable来分面,排到4个图就换一行
# 也就是说用于facet的变量必须也在df这个input dataframe里
fig = make_subplots(1,3)  # 1 row, 3 cols
fig.add_trace(go.Scatter(....))  # 用个for来add_trace更合适

各种layout

# 还是tips这个数据集
color_day_dict = dict(zip(set(tips.day.tolist()),plotly.colors.colorbrewer.Set1))

trace0 = []
for i in set(tips.day.tolist()):
    tips_temp = tips.loc[tips['day']==i,:]
    trace0.append(go.Scatter(x=tips_temp.total_bill.tolist(),
                             y=tips_temp.tip.tolist(),
                             mode='markers',
                             name = i,
                             marker=dict(color=color_day_dict[i],
                                         size=10)))

fig = go.Figure(data=trace0)

fig.update_layout(height=500, width=800, #设置图大小
                  font=dict(size=20),  # 字体大小
                  legend={'font':dict(size=22),  # legend字体大小 
                          'itemsizing': 'constant',}, # legend图标大小
                  hoverlabel=dict(font=dict(size=20))) #hoverlabel大小

fig.update_xaxes(tickangle=45)  # 设置X轴字符倾斜45度
fig['layout']['yaxis']['showgrid'] = False  # Y轴不显示网格
fig['layout']['yaxis']['side'] = 'right'  #将Y轴放置在右边

fig['layout']['xaxis']['showgrid'] = False  # 设置X轴不显示网格
fig['layout']['xaxis']['side'] = 'top'  # 将X轴放置在顶部

fig.show()

注意:

  1. 如果用jupyter lab, 需要安装一些jupyter lab及其相关支持,follow官方的步骤
  2. 超级详细的reference: 每个attribue都是什么意思
    比方说go.Scatter(mode=...)中有几个mode选项,分别有什么效果,都非常详细。真的太详细了,我喜极而泣T_T
  3. plotly本质上并不是为publish服务的,也不是统计分析友好型的可视化工具。但是interactive的模式能帮助我们更好的了解数据背后的东西(以及更加好看和酷炫)。就分析报告的出具,为发表paper准备的标准化制图而言,可能还是R的ggplot2, ggpubr更加方便顺手一些。对于数据量大,层次丰富,研究目的不那么明确的数据,plotly可能更加便于发现问题。当然还是要根据需求选择工具。
  4. plotly express,拉到最后看plotly自带调色板
  5. 虽然plotly express和R的ggplot2惊人相似,但是express似乎并没有把所有可调节的东西纳入函数里。不像ggplot2的万物皆可调。比如ggplot2可以通过+theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1...))来调节X轴数字字体大小,距离轴的距离,倾斜角度等。plotly我暂时没找到除了update_trace, update_layout之外的,可以在函数内实现的方法。(当然可能是文档看少了)
  6. 一开始我对express是嫌弃的,因为px.XXX()中的参数都需要出现在input data的column names里面,不能在一个函数里解决所有问题,觉得十分麻烦。后来我反思了一下,觉得我是被R的ggplot2盖楼式画图给惯坏了。如果对于自己要画什么图非常明确,且input数据可以全部规整到一个dataframe里,那用express是非常方便的。
  7. figure label: https://plot.ly/python/figure-labels/
    axis label: https://plot.ly/python/axes/#set-axis-label-rotation-and-font
    hover text: https://plot.ly/python/hover-text-and-formatting/
    resize hover info box: https://community.plot.ly/t/re-size-hover-info-box/955
    hover info box: https://github.com/plotly/plotly.js/issues/102
  8. plotly express 小贴士
px.box(df, x='...', y = '...', color = '...', 
       category_orders = dict(X_content = ['A','B','C']))
      # 用于将X轴自由sort
  1. 友情链接:
    plotly绘图说明
    plotly 4.0自来水公司通告(可视化python模块推荐)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266

推荐阅读更多精彩内容