本次笔记内容
- 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()
注意:
- 如果用jupyter lab, 需要安装一些jupyter lab及其相关支持,follow官方的步骤:
-
超级详细的reference: 每个attribue都是什么意思
比方说go.Scatter(mode=...)
中有几个mode选项,分别有什么效果,都非常详细。真的太详细了,我喜极而泣T_T
- plotly本质上并不是为publish服务的,也不是统计分析友好型的可视化工具。但是interactive的模式能帮助我们更好的了解数据背后的东西(以及更加好看和酷炫)。就分析报告的出具,为发表paper准备的标准化制图而言,可能还是R的
ggplot2
,ggpubr
更加方便顺手一些。对于数据量大,层次丰富,研究目的不那么明确的数据,plotly可能更加便于发现问题。当然还是要根据需求选择工具。 - plotly express,拉到最后看plotly自带调色板
- 虽然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
之外的,可以在函数内实现的方法。(当然可能是文档看少了) - 一开始我对express是嫌弃的,因为
px.XXX()
中的参数都需要出现在input data的column names里面,不能在一个函数里解决所有问题,觉得十分麻烦。后来我反思了一下,觉得我是被R的ggplot2盖楼式画图给惯坏了。如果对于自己要画什么图非常明确,且input数据可以全部规整到一个dataframe里,那用express是非常方便的。 - 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 - plotly express 小贴士
px.box(df, x='...', y = '...', color = '...',
category_orders = dict(X_content = ['A','B','C']))
# 用于将X轴自由sort