本次筆記內容
- plotly基本用法
- 基本Scatter示例:
go.Scatter(),按連續(xù)型/分類型變量著色- 基本Scatter示例:
px(),按連續(xù)型/分類型變量著色- 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(),按連續(xù)型變量著色
import plotly.express as px
import plotly.graph_objects as go
import plotly
tips = px.data.tips() # 用px里的示例數(shù)據
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決定圖上出現(xiàn)點,線,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(),按連續(xù)型變量著色
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,一定要是出現(xiàn)在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,是出現(xiàn)在tips這個dataframe中的column
fig.show()

colorscale
可以選擇build-in的colorscale,也可以自己定義。在數(shù)據分布很極端的情況下,均勻的build-in color可能不太適用。
(不過build-in顏色盤已經很美了,能用盡量用)
# 通過colorscale自定義顏色區(qū)間對應關系,即0-65%的值會根據rgb(231,231,230) --- rgb(0,25,225)這個區(qū)間來著色。
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這個數(shù)據集
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服務的,也不是統(tǒng)計分析友好型的可視化工具。但是interactive的模式能幫助我們更好的了解數(shù)據背后的東西(以及更加好看和酷炫)。就分析報告的出具,為發(fā)表paper準備的標準化制圖而言,可能還是R的
ggplot2,ggpubr更加方便順手一些。對于數(shù)據量大,層次豐富,研究目的不那么明確的數(shù)據,plotly可能更加便于發(fā)現(xiàn)問題。當然還是要根據需求選擇工具。 - plotly express,拉到最后看plotly自帶調色板
- 雖然plotly express和R的ggplot2驚人相似,但是express似乎并沒有把所有可調節(jié)的東西納入函數(shù)里。不像ggplot2的萬物皆可調。比如ggplot2可以通過
+theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1...))來調節(jié)X軸數(shù)字字體大小,距離軸的距離,傾斜角度等。plotly我暫時沒找到除了update_trace, update_layout之外的,可以在函數(shù)內實現(xiàn)的方法。(當然可能是文檔看少了) - 一開始我對express是嫌棄的,因為
px.XXX()中的參數(shù)都需要出現(xiàn)在input data的column names里面,不能在一個函數(shù)里解決所有問題,覺得十分麻煩。后來我反思了一下,覺得我是被R的ggplot2蓋樓式畫圖給慣壞了。如果對于自己要畫什么圖非常明確,且input數(shù)據可以全部規(guī)整到一個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

