客至汲泉烹茶, 抚琴听者知音

python简单进阶之数据可视化:Plotly Express使用教程

这是简单进阶教程系列第三篇,本系列文章主要介绍那些可以很快上手的进阶库。

说起数据可视化,大多数人第一反应是matplotlib,我以前也尝试过。但是,一方面是matplotlib设置稍微有点复杂,另一方面是它有点丑(也可能是我不会调),思来想去还不如直接用excel作图呢,于是一直也没有python作过图。但是后来发现了这样一款神器Plotly Express,不仅设置简单,刚好和我比较熟练的DataFrame联系起来了。而且颜值巨高,那还说什么,学起来。

先看看它的颜值有多高:

https://pan.yanshu.work/article/pic.html

安装导入

pip install plotly_express # 安装
import plotly.express as px # 导入

IDE中无法显示图像?

Plotly貌似只能在Jupyter中直接显示,而在代码编辑器中,如Spyder,无法直接显示。一个间接的解决方案是利用浏览器显示,下面是一个示例。(来源于http://liyangbit.com/pythonvisualization/Plotly-Express-IDE/

import plotly.express as px
import plotly
plotly.offline.init_notebook_mode(connected=True)

iris = px.data.iris()
iris_plot = px.scatter(iris, x='sepal_width', y='sepal_length',
           color='species', marginal_y='histogram',
          marginal_x='box', trendline='ols')

plotly.offline.plot(iris_plot)

Plotly生成的图像居然是可交互式的,太完美了。

使用方法

散点图

import plotly.express as px
df = px.data.iris()
fig = px.scatter(df, x="sepal_width", y="sepal_length")
fig.show() # Jupyter中有用

按种类上色

fig = px.scatter(df, x="sepal_width", y="sepal_length", color="species")

在散点图上添加频率分布直方图,散点图右添加rug图

fig = px.scatter(df, x="sepal_width", y="sepal_length", color="species", marginal_y="rug", marginal_x="histogram")

添加趋势线

fig = px.scatter(df, x="sepal_width", y="sepal_length", color="species",trendline="ols")

给每个点添加一个范围

df["e"] = df["sepal_width"]/100
fig = px.scatter(df, x="sepal_width", y="sepal_length", color="species", error_x="e", error_y="e")

其中error_x是x方向的范围,error_y是y方向的范围

多重分类散点图

import plotly.express as px
df = px.data.tips()
fig = px.scatter(df, x="total_bill", y="tip", facet_row="time", facet_col="day", color="smoker", trendline="ols",
          category_orders={"day": ["Thur", "Fri", "Sat", "Sun"], "time": ["Lunch", "Dinner"]})

横向按周几分,纵向按时间分,category_orders可以不加,但是没有这个参数,它就会按默认的顺序排列

气泡图

本质上和散点图一样,加上size='col_name'即可生成

df = px.data.gapminder()

fig = px.scatter(df.query("year==2007"), x="gdpPercap", y="lifeExp", size="pop", color="continent",
           hover_name="country", log_x=True, size_max=60)

就是按照2007年数据,气泡大小与人口有关(size="pop"),气泡显示标题为国家名(color="continent"),对x轴取对数,气泡最大60

动态气泡图

df = px.data.gapminder()
fig = px.scatter(df, x="gdpPercap", y="lifeExp", animation_frame="year", animation_group="country",
           size="pop", color="continent", hover_name="country", facet_col="continent",
           log_x=True, size_max=45, range_x=[100,100000], range_y=[25,90])

最重要的参数就是animation_frame="year",它表示按年份绘制动态气泡图,至于animation_group,说实话我不知它有啥用,删掉好像也没有影响

下面图其实是动图,但我懒得录制gif了……

矩阵散点图

矩阵散点图

df = px.data.iris()
fig = px.scatter_matrix(df)

简单来说就是把df中所有变量(列名)按照不同方式进行组合然后作散点图

矩阵散点图选定几个变量

fig = px.scatter_matrix(df, dimensions=["sepal_width", "sepal_length", "petal_width", "petal_length"], color="species")

有时候我只想看其中几个变量的相关关系

三元散点图

df = px.data.election()
fig = px.scatter_ternary(df, a="Joly", b="Coderre", c="Bergeron", color="winner", size="total", hover_name="district",
                   size_max=15, color_discrete_map = {"Joly": "blue", "Bergeron": "green", "Coderre":"red"} )

3D散点图

df = px.data.election()
fig = px.scatter_3d(df, x="Joly", y="Coderre", z="Bergeron", color="winner", size="total", hover_name="district",
                  symbol="result", color_discrete_map = {"Joly": "blue", "Bergeron": "green", "Coderre":"red"})

symbol="result"指的是按结果设置不同的图例形状

雷达散点图

df = px.data.wind()
fig = px.scatter_polar(df, r="frequency", theta="direction", color="strength", symbol="strength")

平行图

平行坐标图

平行坐标图主要分析多维变量之间的关系

df = px.data.iris()
fig = px.parallel_coordinates(df, color="species_id", labels={"species_id": "Species",
                  "sepal_width": "Sepal Width", "sepal_length": "Sepal Length",
                  "petal_width": "Petal Width", "petal_length": "Petal Length", },
                    color_continuous_scale=px.colors.diverging.Tealrose, color_continuous_midpoint=2)

label是个字典,主要是把变量名改成容易理解的标签,可以去掉,那么图上显示的就是变量名。

color_continuous_scale貌似是指色域范围,感觉没有必要掌握,color_continuous_midpoint也一样。(这两参数都是可以去掉的)

平行类别图

df = px.data.tips()
fig = px.parallel_categories(df, color="size", color_continuous_scale=px.colors.sequential.Inferno)

折线图

df = px.data.gapminder()
fig = px.line(df, x="year", y="lifeExp", color="continent", line_group="country", hover_name="country",
        line_shape="spline", render_mode="svg")

line_group参数去掉后,线的密集程度明显增加了。

line_shape="spline"大概是折线的样式,

render_mode="svg"这次必须带这个参数

三元折线图

df = px.data.election()
fig = px.line_ternary(df, a="Joly", b="Coderre", c="Bergeron", color="winner", line_dash="winner")

line_dash="winner",使折线变成不同样式(实线、虚线等)

3D折线图

df = px.data.election()
fig = px.line_3d(df, x="Joly", y="Coderre", z="Bergeron", color="winner", line_dash="winner")

雷达折线图

df = px.data.wind()
fig = px.line_polar(df, r="frequency", theta="direction", color="strength", line_close=True)

line_close=True指的是折线是否首尾相接

面积图

df = px.data.gapminder()
fig = px.area(df, x="year", y="pop", color="continent", line_group="country")

等高线图

df = px.data.iris()
fig = px.density_contour(df, x="sepal_width", y="sepal_length")

热力图

df = px.data.iris()
fig = px.density_heatmap(df, x="sepal_width", y="sepal_length")

条形图

df = px.data.tips()
fig = px.bar(df, x="sex", y="total_bill", color="smoker", barmode="group")

barmode="group"指的是是否按照smoker分开展示。用图说明吧,下面第一张图是带参数的,第二张图是不带参数的。

雷达条形图

df = px.data.wind()
fig = px.bar_polar(df, r="frequency", theta="direction", color="strength", template="plotly_dark")

直方图

df = px.data.tips()
fig = px.histogram(df, x="total_bill", y="tip", color="sex", marginal="rug", hover_data=df.columns)

hover_data=df.columns展示相应数据的所有信息,必须与marginal连用才有效

类似地,可以添加barmode="group"参数以分开展示

带状图

df = px.data.tips()
fig = px.strip(df, x="total_bill", y="time", orientation="h", color="smoker")

orientation="h",水平方向绘图

箱型图

df = px.data.tips()
fig = px.box(df, x="day", y="total_bill", color="smoker", notched=True)

notched=True是下面的形状,如果notched=False,那么就完全变成蜡烛图了。

小提琴图

df = px.data.tips()
fig = px.violin(df, y="tip", x="smoker", color="sex", box=True, points="all", hover_data=df.columns)

box=True为是否展示里面的小箱子,points="all"为是否展示小提琴旁边的点,hover_data=df.columns为是否详细展示所有数据点信息

地图

用Poltly Express制作地图,可以离线用的只有世界地图,其他类型的地图需要申请token(大概是在这里申请的:https://www.mapbox.com/)。或者自己制作,可以在github上找如“China geojson”类型的json数据。等我以后尝试一下看怎么做

给个例子:

df = px.data.gapminder()
fig = px.choropleth(df, locations="iso_alpha", color="lifeExp", hover_name="country", animation_frame="year", range_color=[20,80])

总结

基本用法px.pic_type(df,x='col_name',y='col_name')

注意:三元图(三元折线图、三元散点图),x,y变成a,b,c了

3D图是xyz

雷达图是r,theta

图片种类:

  • scatter,散点图
  • scatter_matrix,矩阵散点图
  • scatter_ternary,三元散点图
  • scatter_3d,3D散点图
  • scatter_polar,雷达散点图
  • line,折线图
  • line_ternary,三元折线图
  • line_3d,3D折线图
  • line_polar,雷达折线图
  • area,面积图
  • density_contour,等高线图
  • density_heatmap,热力图
  • bar,条形图
  • bar_polar,雷达条形图
  • histogram,直方图
  • strip,带状图
  • violin,小提琴图
  • box,箱形图

通用参数

  • template="plotly_dark",图片模板
  • color="col_name" 按某一列的种类进行着色
  • color_discrete_map = {"col_name": "blue", "col_name": "green", "col_name":"red"},设定不同的颜色
  • symbol="col_name"按某一列的种类设置不同的形状
  • marginal_x="pic_type"在图片上方添加一个同样数据做出来的其他类型图
  • marginal_y="pic_type"在图片右方添加一个同样数据做出来的其他类型图
  • labels=dict把变量名改成标签
  • facet_row="col_name"横向分成小图
  • facet_col="col_name"纵向分成小图
  • category_orders=dict小图按顺序排列(可选)
  • color_continuous_scale=px.colors.sequential.Viridiscolor_continuous_midpoint=2都是颜色参数,不要也可
  • range_x=[100,100000]x轴范围,y轴类似
  • hover="col_name",元素标题(比如设置为country,那么折线图中每一条线的标题即国家名,气泡图中每个气泡的标题是国家名)
  • render_mode="webgl"不知道是个啥东西,有些好像必须带这个参数比如折线图第一个案例

散点图参数

  • trendline="ols"趋势线
  • error_x='col_name'是给点加上x方向的范围
  • error_y='col_name'是给点加上y方向的范围

气泡图参数(其实还是scatter)

  • size="col_name",气泡大小影响因素
  • log_x=True,对x轴取对数
  • size=60,气泡最大大小
  • animation_frame="col_name"动态气泡图按指定参数动(比如年份)(加上这个参数就能动了)

矩阵散点图参数

  • dimensions=list 选定的参数列表

折线图参数

  • line_group="col_name"
  • line_shape="spline"
  • render_mode
  • line_dash="col_name"最好和color的值一样,使折线变成不同样式(如虚线)(包括三元折线图)

面积图参数

  • line_group="col_name"

条形图、直方图参数

  • barmode="group",是否分开展示?
  • marginal="pic_type"在图片上方添加一个同样数据做出来的其他类型图
  • hover_data=df.columns展示相应数据所有信息

带状图参数

  • orientation="h",水平方向绘图

箱型图参数

  • notched=True

小提琴图

  • box=True为是否展示里面的小箱子
  • points="all"为是否展示小提琴旁边的点
  • hover_data=df.columns为是否详细展示所有数据点信息

图片保存

保存为html

fig.write_html("file.html")
fig.write_html("file.html",include_plotlyjs='cdn') # 意味着你生成的html中引用了官方的CDN资源,这样会减小html大小,但同时也使其离线不可用。

保存为静态图片

首先你需要安装orca,官方说可以pip或conda安装

conda install -c plotly plotly-orca

但是我并没有成功,因此只能下载二进制文件安装了。

首先在https://github.com/plotly/orca/releases找到适合你系统的版本,我的是windows,因此就下载windows-release.zip。(其他系统参考https://github.com/plotly/orca

然后解压缩,点击exe文件安装。

安装完毕后桌面会出现orca的快捷图标,右键打开属性菜单,复制起始位置的路径,然后添加该路径到系统变量。

打开cmd,输入orca --help,若能正常输出则说明安装成功。

接着重启编辑器,就可以成功生成图片啦。

fig.write_image("fig1.png") # 生成png格式
fig.write_image("fig1.jpeg") # 生成jpeg格式
fig.write_image("ifig1.webp") # 生成webp格式
fig.write_image("fig1.svg") # 生成svg格式
fig.write_image("fig1.pdf") # 生成pdf格式
fig.write_image("fig1.eps") # 这个好像还需要再安装poppler,算了算了
png,jpg,webp都好模糊啊,还不如我在html上截图呢……

报错解决

ImportError: cannot import name 'factorial'

原因:Plotly_Express依赖了scipy这个库的一个misc模块,但是由于最新版本的scipy中,scipy.misc 已经迁移到 scipy.special 里面了,所以提示无法找到

解决方案:

一、scipy降级成1.2.1

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple scipy==1.2.1

二、按照提示的路径,把scipy.misc都改成 scipy.special

比如我的路径是C:\Users\51445\Anaconda3\Lib\site-packages\statsmodels,只要把这个文件夹拖到VScode中然后批量替换即可

添加新评论