可视化分类分布
数据以多种非数值形式存在。数据可以是音乐片段,也可以是地图上的位置。它们还可以是将个体归入其中的类别。以下是一些“分类”变量的例子。
- 个体是冰淇淋纸盒,变量是纸盒中的口味。
- 个体是职业篮球运动员,变量是球员所在的球队。
- 个体是年份,变量是当年最卖座电影的流派。
- 个体是调查受访者,变量是他们从“完全不满意”、“比较满意”和“非常满意”中选择的答案。
from datascience import *
import matplotlib
path_data = '../../../assets/data/'
matplotlib.use('Agg')
%matplotlib inline
import matplotlib.pyplot as plots
plots.style.use('fivethirtyeight')
import numpy as np
np.set_printoptions(threshold=50)
表格 icecream 包含30盒冰淇淋的数据。
icecream = Table().with_columns(
'Flavor', make_array('Chocolate', 'Strawberry', 'Vanilla'),
'Number of Cartons', make_array(16, 5, 9)
)
icecream
Flavor | Number of Cartons
Chocolate | 16
Strawberry | 5
Vanilla | 9分类变量“口味”的“取值”是巧克力、草莓和香草。
每个纸盒恰好具有三种口味之一。在“分布”中,每个个体恰好属于一个类别,因此恰好有一个取值。于是我们得到了口味的分布。
表格显示了每种口味的纸盒数量。我们称之为“分布表”。分布表展示了变量的所有取值以及每个取值的频数。
条形图
条形图是一种常见的可视化分类分布的方式。它为每个类别显示一个条形。条形之间的间距相等,宽度也相等。每个条形的长度与对应类别的频数成比例。
我们将绘制水平条形图,因为这样更容易标注条形。因此,Table的方法名为 barh。它接受两个参数:第一个是类别的列标签,第二个是频数的列标签。
icecream.barh('Flavor', 'Number of Cartons')
A bar chart has 'Number of Cartons' on the x-axis and 'Flavor' on the y-axis. The flavors are 'Chocolate' with a bar measuring at 16, 'Strawberry' with a bar measuring at 5, and 'Vanilla' with a bar measuring at 9.如果表格仅包含一列类别和一列频数,就像 icecream 那样,方法调用更加简单。你只需指定包含类别的列,barh 会自动将另一列的值作为频数使用。
icecream.barh('Flavor')
The same bar chart is shown as above with 'Number of Cartons' and 'Flavor' on the axes.条形图的设计要点
除了纯粹的视觉差异外,条形图与前面章节中看到的两种图形之间还有一个重要的根本区别。那两种图形分别是散点图和折线图,它们都展示两个定量变量——两个轴上的变量都是定量的。相比之下,条形图的一个轴上是类别,另一个轴上是数值。
这对图表有如下影响。首先,每个条形的宽度以及连续条形之间的间距完全由绘制图表的人或所使用的程序决定。Python 为我们做了这些选择。如果你手工绘制条形图,你完全可以做出完全不同的选择,只要所有条形宽度相同且间距一致,仍然可以得到完全正确的条形图。
最重要的是,条形可以按任意顺序排列。类别“巧克力”、“香草”和“草莓”没有通用的排序顺序,不像数字5、7和10那样。
这意味着我们可以通过按降序排列条形来绘制更易于解读的条形图。为此,我们首先按 Number of Cartons 降序重新排列 icecream 的行,然后绘制条形图。
icecream.sort('Number of Cartons', descending=True).barh('Flavor')
A bar chart with 'Number of Cartons' on the x-axis and 'Flavor' on the y-axis. The same information is presented as before, but now the order from top to bottom is 'Chocolate' at 16, 'Vanilla' at 9, and Strawberry' at 5.这个条形图包含的信息与之前完全相同,但更易于阅读。虽然对于只有三个条形的图表来说,这种改进并不显著,但当类别数量很大时,这种改进就变得非常重要。
分组分类数据
为了构建 icecream 表格,有人需要查看所有30盒冰淇淋并统计每种口味的数量。但如果我们的表格尚未包含频数,则需要在绘制条形图之前计算频数。以下是一个需要这样做的示例。
表格 top 包含了截至2017年美国有史以来最卖座的电影。第一列包含电影名称;星球大战:原力觉醒 排名第一,在美国的票房收入超过9亿美元。第二列包含制作该电影的工作室名称。第三列包含国内票房收入(美元),第四列包含按2016年票价计算的票房收入。第五列包含电影发行的年份。
列表中共有200部电影。以下是按通货膨胀调整后的票房收入排名的前十名。
top = Table.read_table(path_data + 'top_movies_2017.csv')
top
Title | Studio | Gross | Gross (Adjusted) | Year
Gone with the Wind | MGM | 198676459 | 1796176700 | 1939
Star Wars | Fox | 460998007 | 1583483200 | 1977
The Sound of Music | Fox | 158671368 | 1266072700 | 1965
E.T.: The Extra-Terrestrial | Universal | 435110554 | 1261085000 | 1982
Titanic | Paramount | 658672302 | 1204368000 | 1997
The Ten Commandments | Paramount | 65500000 | 1164590000 | 1956
Jaws | Universal | 260000000 | 1138620700 | 1975
Doctor Zhivago | MGM | 111721910 | 1103564200 | 1965
The Exorcist | Warner Brothers | 232906145 | 983226600 | 1973
Snow White and the Seven Dwarves | Disney | 184925486 | 969010000 | 1937
... (190 rows omitted)米高梅(MGM)、福克斯(Fox)、环球(Universal)和派拉蒙(Paramount)工作室在前十名中出现不止一次。如果查看所有200行,哪些工作室出现最频繁?
要找出答案,首先注意我们只需要一个包含电影和工作室的表格;其他信息是不必要的。
movies_and_studios = top.select('Title', 'Studio')
Table 方法 group 允许我们统计每个工作室在表格中出现的频率,它将每个工作室作为一个类别,并将所有行收集到这些新类别中。
group 方法以包含类别的列标签作为参数。它返回一个包含每个类别行数的计数表。
因此,group 创建了一个分布表,展示了个体(电影)如何在各个类别(工作室)之间分布。
group 方法按升序列出类别。由于我们的类别是工作室名称,因此以字符串形式表示,升序意味着按字母顺序。
计数列始终名为 count,但如果你愿意,可以使用 relabeled 进行更改。
studio_distribution = movies_and_studios.group('Studio')
studio_distribution
Studio | count
AVCO | 1
Buena Vista | 35
Columbia | 9
Disney | 11
Dreamworks | 3
Fox | 24
IFC | 1
Lionsgate | 3
MGM | 7
Metro | 1
... (13 rows omitted)该表显示共有23个不同的工作室,并提供了每个工作室发行的电影数量。计数总和为200,即电影的总数。
sum(studio_distribution.column('count'))
200现在我们可以使用这个表格,结合上面学到的绘图技巧,绘制一个条形图来显示哪些工作室在200部最卖座电影中出现最频繁。
studio_distribution.sort('count', descending=True).barh('Studio')
A bar chart with 'count' on the x-axis and 'Studio' on the y-axis. The bars are shown in descending order with Buena Vista being the largest at 35, followed by Warner Brothers just below 30, Paramount at 25, Fox just below 25, Universal just below Fox, Disney just above 10, and others.Buena Vista 和 Warner Brothers 是最常在 top 200 电影中出现的工作室。Warner Brothers 制作了哈利·波特系列电影,而 Buena Vista 制作了星球大战系列。
迈向定量变量
虽然年份是数值型的,但我们可以将发行年份视为分类变量并绘制其分布。也就是说,对于每一年,我们可以找出那一年发行了多少部电影,然后绘制该分布的条形图。
让我们这样做,并只查看分布中最前面的10个年份。
movies_and_years = top.select('Title', 'Year')
movies_and_years.group('Year').take(np.arange(10)).barh('Year')
A bar chart with 'count' on the x-axis and 'Year' on the y-axis. The years 1921, 1937, 1939, 1940, 1942, 1945, 1950, and 1952 have bars of length 1 and 1941 and 1946 have length 2.年份按递增顺序出现,因为 group 将类别从低到高排序。这在此处很重要,因为年份具有必须保持的时间顺序。但这个条形图有些令人不安。1921年和1937年的条形之间的距离与1937年和1939年的条形之间的距离完全一样。条形图没有显示1922年至1936年以及1938年这200部电影都没有发行。这种不一致和遗漏使得基于此可视化难以理解早期年份的分布。
分类变量的分布可以使用条形图显示。但如果变量不是分类的而是定量的,那么我们在创建可视化时必须考虑其取值之间的数值关系。这正是下一节的主题。