使用Altair进行探索性数据可视化
Altair是一个专为Python编写的可视化软件包,它能让数据科学家更多地关注数据本身和其内在的联系。
Altair由华盛顿大学的数据科学家Jake Vanderplas编写,目前在GitHub上已经收获超过3000星。
最近,Medium上一位小姐姐Parul Pandey分享了Altair的入门教程,希望对从事数据科学的用户有帮助。
使用教程
Parul以汽车数据为例,将一个汽车数据集“cars”载入到Altair中。
cars中包含汽车的生产年份、耗油量、原产国等9个方面的数据,后面将对这些内容进行可视化处理。
安装和导入Altair软件包
除了安装Altair和它的依赖软件外,还需要安装其他前端工具,比如Jupyter Notebook、JupyterLab、Colab等等。
Parul小姐姐推荐安装JupyterLab:
$ pip install -U altair vega_datasets jupyterlab
需要注意的是,由于Altair的教程文档中还包含vega_datasets
数据集,因此也需要一并安装上。
接着在终端中输入:jupyter lab,就能在你的浏览器中自动打开它啦。
在代码开头别忘了导入Altair:
import altair as alt
导入数据
from vega_datasets import data
cars = data.cars()
cars.head()
完成以上准备工作,我们就可以开始绘图了
开始绘制图表
Altair中的基本对象是Chart
,它将数据框作为单个参数。你可以这样定义它:
chart = alt.Chart(cars)
Chart有三个基本方法:数据(data)、标记(mark)和编码(encode),使用它们的格式如下:
alt.Chart(data).mark_point().encode(
encoding_1='column_1',
encoding_2='column_2',
# etc.
)
数据顾名思义,直接导入cars数据集即可。标记和编码则决定着绘制图表的样式,下面着重介绍这两部分。
标记可以让用户在图中以不同形状来表示数据点,比如使用实心点、空心圆、方块等等。
如果我们只调用这个方法,那么所有的数据点都将重叠在一起:
alt.Chart(cars).mark_point()
这显然是没有意义的,还需要有编码来指定图像的具体内容。常用的编码有:
x: x轴数值
y: y轴数值
color: 标记点颜色
opacity: 标记点的透明度
shape: 标记点的形状
size: 标记点的大小
row: 按行分列图片
column: 按列分列图片
以汽车的耗油量为例,把所有汽车的数据绘制成一个一维散点图,指定x轴为耗油量:
alt.Chart(cars).mark_point().encode(x='Miles_per_Gallon')
但是使用mark_point()会让所有标记点混杂在一起,为了让图像更清晰,可以替换成棒状标记点mark_tick():
alt.Chart(cars).mark_tick().encode(x='Miles_per_Gallon')
以耗油量为X轴、马力为Y轴,绘制所有汽车的分布,就得到一张二维图像:
alt.Chart(cars).mark_line().encode(x='Miles_per_Gallon',y='Horsepower')
给图表上色
前面我们已经学会了绘制二维图像,如果能给不同组的数据分配不同的颜色,就相当于给数据增加了第三个维度。
alt.Chart(cars).mark_point().encode(x='Miles_per_Gallon',y='Horsepower',color='Origin')
上面的图中,第三个维度“原产国”是一个离散变量。
使用颜色刻度表,我们还能实现对连续变量的上色,比如在上图中加入“加速度”维度,颜色越深表示加速度越大:
alt.Chart(cars).mark_point().encode(x='Miles_per_Gallon',y='Horsepower',color='Acceleration')
数据的分类与汇总
上面的例子中,我们使用的主要是散点图。实际上,Altair还能方便地对数据进行分类和汇总,绘制统计直方图。
相比其他绘图工具,Altair的特点在于不需要调用其他函数,而是直接在数轴上进行修改。
例如统计不同油耗区间的汽车数量,对X轴使用alt.X(),指定数据和间隔大小,对Y轴使用count()统计数量。
alt.Chart(cars).mark_bar().encode(x=alt.X('Miles_per_Gallon', bin=alt.Bin(maxbins=30)),y='count()')
为了分别表示出不同原产国汽车的油耗分布,前文提到的上色方法也能直方图中使用,这样就构成一幅分段的统计直方图:
alt.Chart(cars).mark_bar().encode(x=alt.X('Miles_per_Gallon', bin=alt.Bin(maxbins=30)),y='count()',color='Origin')
如果你觉得上图还不够直观,那么可以用column将汽车按不同原产国分列成3张直方图:
alt.Chart(cars).mark_bar().encode(x=alt.X('Miles_per_Gallon', bin=alt.Bin(maxbins=30)),y='count()',color='Origin',column='Origin')
交互
Altair的一个非常重要的功能是,只需部署interactive()模块即可轻松实现交互。
共有三种基本类型的选择:
间隔选择: alt.selection_interval()
单选: alt.selection_single()
多选: alt.selection_multi()
除了绘制基本图像,Altair强大之处在于用户可以与图像进行交互,包括平移、缩放、选中某一块数据等操作。
在绘制图片的代码后面,调用interactive()模块,就能实现平移、缩放:
alt.Chart(cars).mark_point().encode(
x='Horsepower:Q',
y='Miles_per_Gallon:Q',
color='Origin',
tooltip='Name'
).interactive()
Altair还为创建交互式图像提供了一个selection的API:
interval = alt.selection_interval()
alt.Chart(cars).mark_point().encode(
x='Miles_per_Gallon',
y='Horsepower',
color='Origin'
).properties(
selection=interval
)
interval = alt.selection_interval()
alt.Chart(cars).mark_point().encode(
x='Miles_per_Gallon',
y='Horsepower',
color=alt.condition(interval, 'Origin', alt.value('lightgray'))
).properties(
selection=interval
)
在选择功能上,我们能做出一些更酷炫的高级功能,例如对选中的数据点进行统计,生成实时的直方图。
interval = alt.selection_interval()
base = alt.Chart(cars).mark_point().encode(
y='Horsepower',
color=alt.condition(interval, 'Origin', alt.value('lightgray')),
tooltip='Name'
).properties(
selection=interval
)
base.encode(x='Miles_per_Gallon') | base.encode(x='Acceleration')
interval = alt.selection_interval()
base = alt.Chart(cars).mark_point().encode(
y='Horsepower',
color=alt.condition(interval, 'Origin', alt.value('lightgray')),
tooltip='Name'
).properties(
selection=interval
)
hist = alt.Chart(cars).mark_bar().encode(
x='count()',
y='Origin',
color='Origin'
).properties(
width=800,
height=80
).transform_filter(
interval
)
scatter = base.encode(x='Miles_per_Gallon') | base.encode(x='Acceleration')
scatter & hist
叠加多个图层
如果把前面的汽车耗油量按年度计算出平均值:
alt.Chart(cars).mark_line().encode(
x='Year',
y='mean(Miles_per_Gallon)',
)
在统计学上,我们还能定义平均值的置信区间,为了让图表更好看,可以分别列出三个不同产地汽车的耗油量平均值置信区间:
alt.Chart(cars).mark_area(opacity=0.3).encode(
x=alt.X('Year', timeUnit='year'),
y=alt.Y('ci0(Miles_per_Gallon)', axis=alt.Axis(title='Miles per Gallon')),
y2='ci1(Miles_per_Gallon)',
color='Origin'
).properties(
width=800
)
最后我们可以用图层API将平均值和置信区间两幅图叠加起来:
spread = alt.Chart(cars).mark_area(opacity=0.3).encode(
x=alt.X('Year', timeUnit='year'),
y=alt.Y('ci0(Miles_per_Gallon)', axis=alt.Axis(title='Miles per Gallon')),
y2='ci1(Miles_per_Gallon)',
color='Origin'
).properties(
width=800
)
lines = alt.Chart(cars).mark_line().encode(
x=alt.X('Year', timeUnit='year'),
y='mean(Miles_per_Gallon)',
color='Origin'
).properties(
width=800
)
spread + lines