能够创建既易于理解又足够精细的图表,是成为优秀数据科学家的关键。通过可视化,您可以讲述数据背后的故事。它能突出数据中的关系,并展现仅用数字无法传达、但人眼可见的信息。但您知道比静态可视化更适合数据分析的是什么吗?交互式可视化!
不幸的是,对于新手来说,这看起来可能是件艰巨的任务。Python 和 R 都提供了大量工具和技巧来帮助您完成这项工作。在本教程中,我们将向您介绍 Altair 。借助 Altair,您只需几行代码、用很短的时间,就能创建有意义、优雅且高效的可视化。那就开始吧!
什么是 Altair?
Altair 是一个用于统计可视化的 Python 库。它具有声明式特性(我们稍后会解释这个概念)。它基于 Vega 和 Vega-Lite ,这两者都是可视化语法(grammar of graphics),允许您用 JSON 格式 描述可视化的外观和交互行为。
命令式 vs. 声明式 API
如前所述,Python 已经有一系列用于数据可视化的优秀工具和库,其中许多还支持交互式可视化。那么 Altair 的独特之处在哪里?
答案在于它相对于其他命令式 API 的声明式特性 。
在命令式 API 中,您需要把注意力放在“如何做”而不是“想要做什么”上。您必须更多地考虑生成可视化所需的代码,并手动指定绘图步骤——坐标轴范围、大小、旋转、图例等。
作为数据科学家,Altair 能让您将时间和精力更多地放在数据本身——理解、分析和可视化——而不是实现这些所需的代码上。这意味着您可以定义数据以及期望看到的输出(最终可视化应呈现的样子),Altair 会自动为您完成必要的处理。
安装
在本教程中,我们将使用 Vega datasets 中的示例数据集。要安装 Altair 以及 Vega 数据集,请在控制台中输入以下命令:
$ pip install altair vega_datasets
技术支持
如果您使用的是 conda 包管理器,对应命令为:
$ conda install - c conda- forge altair vega_datasets
技术支持
之后,您就可以在 Jupyter Notebook 中导入 Altair 开始使用。若想进一步了解 Jupyter Notebook,请务必查看 DataCamp 的Jupyter Notebook 终极指南 。
数据
现在我们已经安装了 Altair 和 Vega 数据集,是时候加载一些数据了。先从以下导入开始:
import pandas as pd
import altair as alt
技术支持
为什么要导入 Pandas?
因为 Altair 的数据是围绕 Pandas DataFrame 构建的,这意味着您可以像处理 Pandas 的 DataFrame 一样在 Altair 中操作数据。
尽管 Altair 在内部以 Pandas DataFrame 的格式存储数据,但有多种方式可以输入数据:
作为 Pandas DataFrame
作为 Data 或相关对象(如 UrlData、InlineData、NamedData)
作为指向 JSON 或 CSV 文本文件的 URL 字符串
作为支持 geo_interface 的对象(例如,Geopandas 的 GeoDataFrame、Shapely 几何对象、GeoJSON 对象)
电影数据集
本教程将使用 Vega 数据集中的电影数据集(Movies Dataset) 。这一类与电影相关的数据集在数据科学社区中很有名,尤其是在推荐引擎的语境下。不过,我们将在这里仅通过 Altair 的可视化来进行数据分析。
该数据集包含与电影相关的信息,例如片名、在美国和全球的票房、制作成本、类型、IMDB 和 Rotten Tomatoes 的评分等。我们不会使用所有列,而是只用其中一部分,来学习 Altair 作为可视化工具的用法。
让我们继续,获取数据集并做一些简单分析,以便更好地理解它。
from vega_datasets import data as vega_data
movies_df = pd. read_json( vega_data. movies. url)
print ( "movies_df is of the type: " , type ( movies_df) )
print ( "movies_df: " , movies_df. shape)
技术支持
movies_df is of the type: < class 'pandas.core.frame.DataFrame' >
movies_df : ( 3201 , 16 )
技术支持
如您所见,movies_df 实际上是一个 pandas 的 DataFrame,其中包含 3201 行(电影)和 16 个特征列。让我们看看数据框中的内容。
movies_df. head( 5 )
技术支持
Title US_Gross Worldwide_Gross US_DVD_Sales Production_Budget Release_Date MPAA_Rating Running_Time_min Distributor Source Major_Genre Creative_Type Director Rotten_Tomatoes_Rating IMDB_Rating IMDB_Votes 0 The Land Girls 146083.0 146083.0 NaN 8000000.0 Jun 12 1998 R NaN Gramercy None None None None NaN 6.1 1071.0 1 First Love, Last Rites 10876.0 10876.0 NaN 300000.0 Aug 07 1998 R NaN Strand None Drama None None NaN 6.9 207.0 2 I Married a Strange Person 203134.0 203134.0 NaN 250000.0 Aug 28 1998 None NaN Lionsgate None Comedy None None NaN 6.8 865.0 3 Let's Talk About Sex 373615.0 373615.0 NaN 300000.0 Sep 11 1998 None NaN Fine Line None Comedy None None 13.0 NaN NaN 4 Slam 1009819.0 1087521.0 NaN 1000000.0 Oct 09 1998 R NaN Trimark Original Screenplay Drama Contemporary Fiction None 62.0 3.4 165.0
列名为:
movies_df. columns
技术支持
Index ( [ 'Title' , 'US_Gross' , 'Worldwide_Gross' , 'US_DVD_Sales' ,
'Production_Budget' , 'Release_Date' , 'MPAA_Rating' , 'Running_Time_min' ,
'Distributor' , 'Source' , 'Major_Genre' , 'Creative_Type' , 'Director' ,
'Rotten_Tomatoes_Rating' , 'IMDB_Rating' , 'IMDB_Votes' ] ,
dtype= 'object' )
技术支持
接下来我们将使用 pandas 的 to_datetime 函数把 Release_Date 列转换为真正的日期,然后从中提取年份。稍后我们会在可视化中使用这个新创建的列。
def extract_year ( value) :
return pd. to_datetime( value, format = '%b %d %Y' ) . year
movies_df[ "Year" ] = movies_df[ "Release_Date" ] . apply ( extract_year)
技术支持
现在如果您再次查看列名,会看到新增了一个 Year 列,其中包含对应电影的年份。
movies_df. columns
技术支持
Index ( [ 'Title' , 'US_Gross' , 'Worldwide_Gross' , 'US_DVD_Sales' ,
'Production_Budget' , 'Release_Date' , 'MPAA_Rating' , 'Running_Time_min' ,
'Distributor' , 'Source' , 'Major_Genre' , 'Creative_Type' , 'Director' ,
'Rotten_Tomatoes_Rating' , 'IMDB_Rating' , 'IMDB_Votes' , 'Year' ] ,
dtype= 'object' )
技术支持
现在我们来创建一些图表。但在此之前,请先运行这段代码:
alt. renderers. enable( 'notebook' )
技术支持
RendererRegistry. enable ( 'notebook' )
技术支持
上述代码让 Altair 能够在 Jupyter Notebook 中内联渲染,这样我们就能看到绘制的图形。如果遇到问题,请查看 Altair 的故障排查页面 。
初步浏览数据后,看看电影制作投入(Production_Budget)与电影实际票房(Worldwide_Gross)之间的关系会很有趣。我们将分别把它们绘制在 X 轴和 Y 轴上。
不过,这个数据集相对较大——考虑到我们主要目的是练习 Altair,因此暂时只用一小部分数据。让我们先看看数据集中某一年的电影数量,并选择一个年份来聚焦。
movies_df[ "Year" ] . value_counts( )
技术支持
2006 220
2005 210
2002 208
2004 192
2000 188
...
1943 1
2015 1
2027 1
2037 1
1928 1
Name : Year, Length : 91 , dtype : int64
技术支持
我们把焦点放在 2000 年,并创建一个新的数据框 movies_2000,只包含该年的数据。它应包含 188 行(电影)。
movies_2000 = movies_df[ movies_df[ "Year" ] == 2000 ]
movies_2000. shape
技术支持
( 188 , 17 )
技术支持
现在我们来制作第一个可视化。为此,先更深入了解一下 Altair 的格式。
图表(Charts)
Chart 是 Altair 的基本对象,它只接受一个参数——dataframe。定义图表的方式如下:
alt. Chart ( DataFrame)
技术支持
但图表本身除了指定要使用的数据外,不会做太多事情;接下来您需要告诉它要对数据做什么。这时就要用到 marks 。
标记(Marks)
mark 属性用于指定数据在图中如何呈现。Altair 提供了以下基本标记属性:
对于本例中的 mark 属性,我们希望把 DataFrame 中的每个值都标记为图中的一个点(圆)。因此,我们将这样写:
alt. Chart ( DataFrame) . mark_point ( ) 技术支持
编码(Encodings)
在确定了数据以及呈现方式之后,我们还需要指定呈现的位置,也就是设置位置、大小、颜色等。这就要使用 encodings 。因此,我们有:
alt. Chart ( DataFrame) . mark_point ( ) . encode ( )
技术支持
把这些放在一起,并补充细节,来完成我们的第一个可视化:
alt. Chart( movies_2000) . mark_point( ) . encode(
alt. X( 'Production_Budget' ) ,
alt. Y( 'Worldwide_Gross' )
)
技术支持
< vega. vegalite. VegaLite at 0x11709a1d0 >
技术支持
是不是很棒?我们几乎没做什么——只是熟悉了一些术语并把它们组合起来。现在我们有了一张图,可以看到 2000 年电影的投入与票房之间的关系。
让我们把这张图做得更有趣些。与其让所有点的圆大小一样,不如让它们的大小与对应的 US_Gross 成正比。为此,我们引入 Size 特性。圆越大,代表其在美国的票房越高。我们还将把圆填充上颜色,而不仅仅是描边;为此,我们在 mark_point() 中添加一个参数。
alt. Chart( movies_2000) . mark_point( filled= True ) . encode(
alt. X( 'Production_Budget' ) ,
alt. Y( 'Worldwide_Gross' ) ,
alt. Size( 'US_Gross' )
)
技术支持
< vega. vegalite. VegaLite at 0x117cce790 >
技术支持
现在,我们仅用四行代码就绘制了每部电影的预算与票房。还缺什么?颜色!
但我们不会为了加颜色而随便上色!我们将引入数据集中另一项信息 Major_Genre,让每种电影类型都有自己的颜色(使用 Color ),并通过 OpacityValue 加一点透明度。
alt. Chart( movies_2000) . mark_point( filled= True ) . encode(
alt. X( 'Production_Budget' ) ,
alt. Y( 'Worldwide_Gross' ) ,
alt. Size( 'US_Gross' ) ,
alt. Color( 'Major_Genre' ) ,
alt. OpacityValue( 0.7 )
)
技术支持
< vega. vegalite. VegaLite at 0x118e3ff50 >
技术支持
这已经不错了,但还可以更好!如果我们能在图上移动,并查看每个点所代表电影的详细信息就更棒了。Tooltip 正好能做到这一点……
alt. Chart( movies_2000) . mark_point( filled= True ) . encode(
alt. X( 'Production_Budget' ) ,
alt. Y( 'Worldwide_Gross' ) ,
alt. Size( 'US_Gross' ) ,
alt. Color( 'Major_Genre' ) ,
alt. OpacityValue( 0.7 ) ,
tooltip = [ alt. Tooltip( 'Title' ) ,
alt. Tooltip( 'Production_Budget' ) ,
alt. Tooltip( 'Worldwide_Gross' ) ,
alt. Tooltip( 'US_Gross' )
]
)
技术支持
< vega. vegalite. VegaLite at 0x118e3ff90 >
技术支持
是不是很酷?不过先等等,我们还能做更多。还记得我们一开始为什么要用 Altair 吗?就是为了能够制作交互式可视化。tooltip 已经在悬停时带来了一些交互效果。不过,我们再加上一个简单的 interactive() 功能……
alt. Chart( movies_2000) . mark_point( filled= True ) . encode(
alt. X( 'Production_Budget' ) ,
alt. Y( 'Worldwide_Gross' ) ,
alt. Size( 'US_Gross' ) ,
alt. Color( 'Major_Genre' ) ,
alt. OpacityValue( 0.7 ) ,
tooltip = [ alt. Tooltip( 'Title' ) ,
alt. Tooltip( 'Production_Budget' ) ,
alt. Tooltip( 'Worldwide_Gross' ) ,
alt. Tooltip( 'US_Gross' )
]
) . interactive( )
技术支持
< vega. vegalite. VegaLite at 0x118e3c750 >
技术支持
仅仅添加这一行代码,就可以在特定区域进行缩放——坐标轴范围会自动调整,便于您专注于感兴趣的区域。当然,还有更多高级的交互功能可以加入。我们来看看其中一个……
我们终于有了一张很酷的图来展示数据。现在把所有数据点都放到图里吧。不过等等,把所有数据点都堆在一张图中是否会太多?我们还希望按之前创建的 Year 值来区分。为此,我们将使用一个高级的 selection 属性。
select_year = alt. selection_single(
name= 'Select' , fields= [ 'Year' ] , init= { 'Year' : 1928 } ,
bind= alt. binding_range( min = 1928 , max = 2046 , step= 10 )
)
alt. Chart( movies_df) . mark_point( filled= True ) . encode(
alt. X( 'Production_Budget' ) ,
alt. Y( 'Worldwide_Gross' ) ,
alt. Size( 'US_Gross' ) ,
alt. Color( 'Major_Genre' ) ,
alt. OpacityValue( 0.7 ) ,
tooltip = [ alt. Tooltip( 'Title:N' ) ,
alt. Tooltip( 'Production_Budget:Q' ) ,
alt. Tooltip( 'Worldwide_Gross:Q' ) ,
alt. Tooltip( 'US_Gross:Q' )
]
) . add_selection( select_year) . transform_filter( select_year)
技术支持
< vega. vegalite. VegaLite at 0x117cd4cd0 >
技术支持
我们使用 add_selection 将 select_year 作为单一选择功能引入图表,然后通过 transform_filter() 将该选择实际应用到图上。
您是否注意到代码中的另一个新增内容?Tooltip 中的 “Q” 和 “N”。它们用于指定数据类型:N-名义型(分类数据)、Q-定量型(数值数据)、O-有序型(有序数据)、T-时间型(时间点或时间区间)。
查看数据集中最早和最新的年份。
print ( "The oldest year is: " , movies_df[ "Year" ] . min ( ) )
print ( "The latest year is: " , movies_df[ "Year" ] . max ( ) )
技术支持
The oldest year is: 1928
The latest year is: 2046
技术支持
如您所见,当拖动“Select_Year”时,在 1928 — 1967 年之间没有太多电影;2018 年之后也没有记录,更不用说到 2046 年了。我们可以使用 binding_range() 来指定年份范围及步长。
在真实项目中,这类发现很重要,可能指向数据采集阶段或流程中某处存在错误。您需要有效地处理这些错误。这是数据预处理中的重要步骤。可参阅使用 pandas 进行数据准备 以了解这些关键步骤的入门内容。
让我们调整年份范围,至此,我们的最终可视化已经就绪……
select_year = alt. selection_single(
name= 'Select' , fields= [ 'Year' ] , init= { 'Year' : 1968 } ,
bind= alt. binding_range( min = 1968 , max = 2008 , step= 10 )
)
alt. Chart( movies_df) . mark_point( filled= True ) . encode(
alt. X( 'Production_Budget' ) ,
alt. Y( 'Worldwide_Gross' ) ,
alt. Size( 'US_Gross' ) ,
alt. Color( 'Major_Genre' ) ,
alt. OpacityValue( 0.7 ) ,
tooltip = [ alt. Tooltip( 'Title:N' ) ,
alt. Tooltip( 'Production_Budget:Q' ) ,
alt. Tooltip( 'Worldwide_Gross:Q' ) ,
alt. Tooltip( 'US_Gross:Q' )
]
) . add_selection( select_year) . transform_filter( select_year)
技术支持
< vega. vegalite. VegaLite at 0x1180cda10 >
技术支持
在本教程中,您初步了解了 Altair。您看到了如何用几行代码创建漂亮、可交互的图表,更有效地讲述数据中的故事。本文希望展示 Altair 的强大与潜力。想进一步了解 Altair,请访问其官方网站 。
能够创建既易于理解又足够精细的图表,是成为优秀数据科学家的关键。通过可视化,您可以讲述数据背后的故事。它能突出数据中的关系,并展现仅用数字无法传达、但人眼可见的信息。但您知道比静态可视化更适合数据分析的是什么吗?交互式可视化!
不幸的是,对于新手来说,这看起来可能是件艰巨的任务。Python 和 R 都提供了大量工具和技巧来帮助您完成这项工作。在本教程中,我们将向您介绍 Altair。借助 Altair,您只需几行代码、用很短的时间,就能创建有意义、优雅且高效的可视化。那就开始吧!
什么是 Altair?
Altair 是一个用于统计可视化的 Python 库。它具有声明式特性(我们稍后会解释这个概念)。它基于 Vega 和 Vega-Lite,这两者都是可视化语法(grammar of graphics),允许您用 JSON 格式描述可视化的外观和交互行为。
命令式 vs. 声明式 API
如前所述,Python 已经有一系列用于数据可视化的优秀工具和库,其中许多还支持交互式可视化。那么 Altair 的独特之处在哪里?
答案在于它相对于其他命令式 API 的声明式特性。
在命令式 API 中,您需要把注意力放在“如何做”而不是“想要做什么”上。您必须更多地考虑生成可视化所需的代码,并手动指定绘图步骤——坐标轴范围、大小、旋转、图例等。
作为数据科学家,Altair 能让您将时间和精力更多地放在数据本身——理解、分析和可视化——而不是实现这些所需的代码上。这意味着您可以定义数据以及期望看到的输出(最终可视化应呈现的样子),Altair 会自动为您完成必要的处理。
安装
在本教程中,我们将使用 Vega datasets 中的示例数据集。要安装 Altair 以及 Vega 数据集,请在控制台中输入以下命令:
如果您使用的是 conda 包管理器,对应命令为:
之后,您就可以在 Jupyter Notebook 中导入 Altair 开始使用。若想进一步了解 Jupyter Notebook,请务必查看 DataCamp 的Jupyter Notebook 终极指南。
数据
现在我们已经安装了 Altair 和 Vega 数据集,是时候加载一些数据了。先从以下导入开始:
为什么要导入 Pandas?
因为 Altair 的数据是围绕 Pandas DataFrame 构建的,这意味着您可以像处理 Pandas 的 DataFrame 一样在 Altair 中操作数据。
尽管 Altair 在内部以 Pandas DataFrame 的格式存储数据,但有多种方式可以输入数据:
电影数据集
本教程将使用 Vega 数据集中的电影数据集(Movies Dataset)。这一类与电影相关的数据集在数据科学社区中很有名,尤其是在推荐引擎的语境下。不过,我们将在这里仅通过 Altair 的可视化来进行数据分析。
该数据集包含与电影相关的信息,例如片名、在美国和全球的票房、制作成本、类型、IMDB 和 Rotten Tomatoes 的评分等。我们不会使用所有列,而是只用其中一部分,来学习 Altair 作为可视化工具的用法。
让我们继续,获取数据集并做一些简单分析,以便更好地理解它。
如您所见,
movies_df实际上是一个 pandas 的 DataFrame,其中包含 3201 行(电影)和 16 个特征列。让我们看看数据框中的内容。列名为:
接下来我们将使用 pandas 的
to_datetime函数把Release_Date列转换为真正的日期,然后从中提取年份。稍后我们会在可视化中使用这个新创建的列。现在如果您再次查看列名,会看到新增了一个
Year列,其中包含对应电影的年份。现在我们来创建一些图表。但在此之前,请先运行这段代码:
上述代码让 Altair 能够在 Jupyter Notebook 中内联渲染,这样我们就能看到绘制的图形。如果遇到问题,请查看 Altair 的故障排查页面。
初步浏览数据后,看看电影制作投入(
Production_Budget)与电影实际票房(Worldwide_Gross)之间的关系会很有趣。我们将分别把它们绘制在 X 轴和 Y 轴上。不过,这个数据集相对较大——考虑到我们主要目的是练习 Altair,因此暂时只用一小部分数据。让我们先看看数据集中某一年的电影数量,并选择一个年份来聚焦。
我们把焦点放在 2000 年,并创建一个新的数据框
movies_2000,只包含该年的数据。它应包含 188 行(电影)。现在我们来制作第一个可视化。为此,先更深入了解一下 Altair 的格式。
图表(Charts)
Chart 是 Altair 的基本对象,它只接受一个参数——dataframe。定义图表的方式如下:
但图表本身除了指定要使用的数据外,不会做太多事情;接下来您需要告诉它要对数据做什么。这时就要用到 marks。
标记(Marks)
mark 属性用于指定数据在图中如何呈现。Altair 提供了以下基本标记属性:
对于本例中的 mark 属性,我们希望把 DataFrame 中的每个值都标记为图中的一个点(圆)。因此,我们将这样写:
编码(Encodings)
在确定了数据以及呈现方式之后,我们还需要指定呈现的位置,也就是设置位置、大小、颜色等。这就要使用 encodings。因此,我们有:
把这些放在一起,并补充细节,来完成我们的第一个可视化:
是不是很棒?我们几乎没做什么——只是熟悉了一些术语并把它们组合起来。现在我们有了一张图,可以看到 2000 年电影的投入与票房之间的关系。
让我们把这张图做得更有趣些。与其让所有点的圆大小一样,不如让它们的大小与对应的
US_Gross成正比。为此,我们引入Size特性。圆越大,代表其在美国的票房越高。我们还将把圆填充上颜色,而不仅仅是描边;为此,我们在mark_point()中添加一个参数。现在,我们仅用四行代码就绘制了每部电影的预算与票房。还缺什么?颜色!
但我们不会为了加颜色而随便上色!我们将引入数据集中另一项信息
Major_Genre,让每种电影类型都有自己的颜色(使用 Color),并通过 OpacityValue 加一点透明度。这已经不错了,但还可以更好!如果我们能在图上移动,并查看每个点所代表电影的详细信息就更棒了。Tooltip 正好能做到这一点……
是不是很酷?不过先等等,我们还能做更多。还记得我们一开始为什么要用 Altair 吗?就是为了能够制作交互式可视化。tooltip 已经在悬停时带来了一些交互效果。不过,我们再加上一个简单的
interactive()功能……仅仅添加这一行代码,就可以在特定区域进行缩放——坐标轴范围会自动调整,便于您专注于感兴趣的区域。当然,还有更多高级的交互功能可以加入。我们来看看其中一个……
我们终于有了一张很酷的图来展示数据。现在把所有数据点都放到图里吧。不过等等,把所有数据点都堆在一张图中是否会太多?我们还希望按之前创建的
Year值来区分。为此,我们将使用一个高级的 selection 属性。我们使用
add_selection将select_year作为单一选择功能引入图表,然后通过transform_filter()将该选择实际应用到图上。您是否注意到代码中的另一个新增内容?Tooltip 中的 “Q” 和 “N”。它们用于指定数据类型:N-名义型(分类数据)、Q-定量型(数值数据)、O-有序型(有序数据)、T-时间型(时间点或时间区间)。
查看数据集中最早和最新的年份。
如您所见,当拖动“Select_Year”时,在 1928 — 1967 年之间没有太多电影;2018 年之后也没有记录,更不用说到 2046 年了。我们可以使用
binding_range()来指定年份范围及步长。在真实项目中,这类发现很重要,可能指向数据采集阶段或流程中某处存在错误。您需要有效地处理这些错误。这是数据预处理中的重要步骤。可参阅使用 pandas 进行数据准备以了解这些关键步骤的入门内容。
让我们调整年份范围,至此,我们的最终可视化已经就绪……
在本教程中,您初步了解了 Altair。您看到了如何用几行代码创建漂亮、可交互的图表,更有效地讲述数据中的故事。本文希望展示 Altair 的强大与潜力。想进一步了解 Altair,请访问其官方网站。