一、简介
Ploty(plotly.py)是一个交互式的开源绘图库,它支持40多种独特的图表类型,涵盖了各种统计,财务,地理,科学和三维用例。
plotly.py 构建在 Plotly JavaScript 库(plotly.js)之上,使 Python 用户可以创建基于 Web 的漂亮的交互式可视化效果,这些可视化效果可以显示在 Jupyter notebook 中,可以保存到独立的 HTML 文件中,也可以作为纯 Python – 使用 Dash 构建 Web 应用程序。
由于与 orca 图像导出实用程序进行了深度集成,plotly.py 还为非 Web 上下文提供了强大的支持,包括桌面编辑器(例如 QtConsole,Spyder,PyCharm)和静态文档发布(例如,将 notebook 导出为具有高质量矢量图像的 PDF)。
本文记录 Plotly 的基础图表绘制代码,更详细内容查看官方文档:Getting Started with Plotly in Python
二、基础
安装完 plotly,可以看到其目录下含有哪些 module。注意如果是较久之前安装的版本,需要执行 pip install plotly --upgrade
更新一下。4.0 后的版本改动较大,绘图的函数和参数等都有变化。本文最近一次更新是 v4.6.0。
plotly 主要有线上、离线、jupyter-notebook 几种绘图方式,分别用到了以上不同模块中的脚本。
这里存在一个问题,起初尝试的时候可以直接创建一个 plotly.graoh_objs._figure.Figure
对象。执行 figure.show()
便会自动启动一个 localhost 服务在浏览器显示所绘制的图表。但是后面再试又不行了,一直显示无法连接 localhost。可能是系统相应设置的问题,暂时忽略。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import plotly
import plotly.plotly as py
import plotly.graph_objs as go
plotly.tools.set_credentials_file(username='acount', api_key='generated_key')
'''在线绘图:需要获取 plotly 的 API,使用 plotly 提供的云服务'''
# 生成graph_objs对象
trace = go.Scatter(x=[0,1,2,3,4], y=[1,2,3,4,5])
py.plot(data, filename='test', auto_open=True)
'''离线绘图:输出 html 文件,可在浏览器打开交互式图表'''
plotly.offline.plot(
{'data': [go.Scatter(x=[0,1,2,3,4], y=[1,2,3,4,5])],
'layout': go.Layout(title='test figure')
},
auto_open=True
)
'''集成到 jupyter notebook:更改设置,plot 函数改为 iplot 函数.'''
plotly.offline.init_notebook_mode(connected=True)
plotly.offline.iplot(
# 内容同上
# ...
)
# 强烈不推荐使用 jupyter notebook,没有理由...
如果不使用 jupyter notebook,为解决绘图时不能实时更新图片的问题,可以利用 dash
建立本地服务。首先 pip install dash
,然后定义以下函数。在浏览器链接 localhost:8050
,每次绘图后调用函数,再刷新页面即可。
1
2
3
4
5
6
7
8
9
10
11
"""创建本地仪表板服务"""
import dash
import dash_core_components as dcc
import dash_html_components as html
def show_fig(fig):
app = dash.Dash()
app.layout = html.Div([dcc.Graph(figure=fig)])
app.run_server(debug=True, use_reloader=False)
下文主要使用 titanic 数据集
1
2
3
# 这里主要考虑数据集包含绘图需要的数据类型,绘制的图可能并没有实际意义
df = pd.read_csv('titanic.csv').drop(['name'], axis=1)
df.head()
survived | pclass | sex | age | sibsp | parch | ticket | fare | cabin | embarked |
---|---|---|---|---|---|---|---|---|---|
0 | 3 | male | 22 | 1 | 0 | A/5 21171 | 7.25 | nan | S |
1 | 1 | female | 38 | 1 | 0 | PC 17599 | 71.2833 | C85 | C |
1 | 3 | female | 26 | 0 | 0 | STON/O2. 3101282 | 7.925 | nan | S |
1 | 1 | female | 35 | 1 | 0 | 113803 | 53.1 | C123 | S |
0 | 3 | male | 35 | 0 | 0 | 373450 | 8.05 | nan | S |
三、绘图入门
散点图与折线图
使用 plotly.express 绘制散点图与折线图(4.0以上版本)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import plotly.express as px
# 先将数值型转换成离散的分类变量,用于分类
df.survived = df.survived.map({1:'yes', 0:'no'})
# 绘制散点图
fig1 = px.scatter(df, x='age', y='fare', color='survived', size='pclass')
# fig1.show() # 此处启动localhost服务,在浏览器显示图表
# 绘制折线图
x = np.linspace(-10, 10, 1000)
fig2 = px.line(
x=x, y=np.sin(x)*np.cos(10*x),
labels={'x': 't', 'y': 'sin(t)cos(10t)'},
title='高频调制波形示例'
)
# 由于前文说到的localhost服务出错,这里定义函数保存图片到本地
def save_fig(fig, name='output.html'):
html = fig.to_html()
with open(name, 'w') as f:
f.write(html)
print(f'成功输出网页:{name}')
# 输出图片,效果如下
save_fig(fig1, 'scatter.html')
save_fig(fig2, 'line.html')
使用 plotly.graph_objs 绘制散点图和折线图
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import plotly.graph_objs as go
# 数据
x = np.linspace(-10, 10, 1000)
y1 = np.sin(x)
y2 = np.sin(x)*np.cos(10*x)
y3 = np.cos(10*x)
# 使用 Figure 对象在画布上添加不同图形
fig = go.Figure()
fig.add_trace(
go.Scatter(x=x, y=y1, mode='markers', name='sin(x)')
)
fig.add_trace(
go.Scatter(x=x, y=y2, mode='lines+markers', name='sin(x)cos(10x)')
)
fig.add_trace(
go.Scatter(x=x, y=y3, mode='lines', name='cos(10x)')
)
# 调整细节
fig.update_traces(marker_size=3, line_width=1)
fig.update_layout(title='高频调制波波形示例', xaxis_zeroline=False)
save_fig(fig, 'line_scatter.html')
条形图
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 使用 plotly.express 绘制条形图
group_agg = df[['pclass', 'survived', 'age']].groupby('pclass').mean()
group_agg['pclass'] = group_agg.index
fig = px.bar(group_agg, x='pclass', y='survived', color='age')
save_fig(fig, 'barplot_with_color.html')
# 使用 plotly.graph_objs 绘制多个条形图
group_agg = df[['sex', 'pclass', 'survived']].groupby(['sex', 'pclass']).mean()
group_agg['pclass'] = [1,2,3,1,2,3]
female = group_agg.loc[('female', slice(None)), :]
male = group_agg.loc[('male', slice(None)), :]
fig = go.Figure(
data=[
go.Bar(
x=female.pclass,
y=female.survived,
name='female',
marker_color='rgb(240,90,55)'
),
go.Bar(
x=male.pclass,
y=male.survived,
name='male',
marker_color='rgb(100,200,200)'
)
]
)
save_fig(fig, 'group_barplot.html')
饼图
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 使用 plotly.express 绘制饼图
# 查看每个包厢区域的生还率
df.cabin = ['NULL' if type(c)==float else c[0] for c in df.cabin]
group_agg = df[['cabin', 'survived']].groupby('cabin').mean()
group_agg['cabin_header'] = group_agg.index
group_agg['cabin_header'][7] = 'None'
group_agg['passenger_count'] = df.groupby('cabin').count().survived
fig = px.pie(
group_agg,
values='passenger_count',
names='cabin_header',
title='Passenger Number & Survived Rate in Different Cabin Area',
hover_data=['survived'],
labels={'survived': 'Survived Rate'}
)
fig.update_traces(textposition='inside', textinfo='percent+label')
save_fig(fig, 'pieplot.html')