数据可视化指的是通过可视化表示来探索数据。它与数据分析紧密相关,而数据分析指的是使用代码来探索数据集的规律和关联。数据集可以是用一行代码就能表示的小型数字列表,也可以是数千兆字节的数据。
漂亮地呈现数据并非仅仅关乎漂亮的图片。通过以引人注目的简单方式呈现数据,能让观看者明白其含义:发现数据集中原本未知的规律和意义。
所幸即便没有超级计算机,你也能够可视化复杂的数据。鉴于Python的高效性,使用它在笔记本电脑上就能快速地探索由数百万个数据点组成的数据集。数据点并非必须是数。利用本书前半部分介绍的基本知识,也可对非数值数据进行分析。
在基因研究、天气研究、政治经济分析等众多领域,人们常常使用Python来完成数据密集型工作。数据科学家使用Python编写了一系列优秀的可视化和分析工具,其中很多可供你使用。最流行的工具之一是Matplotlib,它是一个数学绘图库,我们将使用它来制作简单的图表,如折线图和散点图。然后,我们将基于随机漫步概念生成一个更有趣的数据集——根据一系列随机决策生成的图表。
我们使用Plotly包,它生成的图表非常适合在数字设备上显示。Plotly生成的图表可根据显示设备的尺寸自动调整大小,还具备众多交互特性,如在用户将鼠标指向图表的不同部分时突出数据集的特定方面。本章将使用Plotly来分析掷骰子的结果。
首先使用Matplotlib来生成几个图表,为此需要使用pip来安装它。pip是一个可用于下载并安装Python包的模块。请在终端提示符下执行如下命令:
$ python -m pip install --user matplotlib
这个命令让Python运行模块pip,并将matplotlib包添加到当前用户的Python安装中。在你的系统中,如果运行程序或启动终端会话时使用的命令不是python,而是python3,应使用类似于下面的命令:
$ python3 -m pip install --user matplotlib
下面使用Matplotlib绘制一个简单的折线图,再对其进行定制,以实现信息更丰富的数据可视化效果。我们将使用平方数序列1、4、9、16和25来绘制这个图表。只需提供如下的数,Matplotlib将完成其他工作:mpl_squares.py
import matplotlib.pyplot as plt
squares = [1, 4, 9, 16, 25]
❶ fig, ax = plt.subplots()
ax.plot(squares)
plt.show()
首先导入模块pyplot,并为其指定别名plt,以免反复输入pyplot。(在线示例大多这样做,这里也不例外。)模块pyplot包含很多用于生成图表的函数。
我们创建了一个名为squares的列表,在其中存储要用来制作图表的数据。然后,采取了另一种常见的Matplotlib做法——调用函数subplots()(见❶)。这个函数可在一张图片中绘制一个或多个图表。变量fig表示整张图片。变量ax表示图片中的各个图表,大多数情况下要使用它。
接下来调用方法plot(),它尝试根据给定的数据以有意义的方式绘制图表。函数plt.show()打开Matplotlib查看器并显示绘制的图表,如图15-1所示。在查看器中,你可缩放和导航图形,还可单击磁盘图标将图表保存起来。
如图15-1所示的图形表明数是越来越大的,但标签文字太小、线条太细,难以看清楚。所幸Matplotlib让你能够调整可视化的各个方面。下面通过一些定制来改善这个图表的可读性,如下所示:mpl_squares.py
import matplotlib.pyplot as plt
squares = [1, 4, 9, 16, 25]
fig, ax = plt.subplots()
❶ ax.plot(squares, linewidth=3)
# 设置图表标题并给坐标轴加上标签1。
❷ ax.set_title("平方数", fontsize=24)
❸ ax.set_xlabel("值", fontsize=14)
ax.set_ylabel("值的平方", fontsize=14)
# 设置刻度标记的大小。
❹ ax.tick_params(axis='both', labelsize=14)
plt.show()
参数linewidth(见❶)决定了plot()绘制的线条粗细。方法set_title()(见❷)给图表指定标题。在上述代码中,出现多次的参数fontsize指定图表中各种文字的大小。
方法set_xlabel()和set_ylabel()让你能够为每条轴设置标题(见❸)。方法tick_params()设置刻度的样式(见❹),其中指定的实参将影响[插图]轴和[插图]轴上的刻度(axes=‘both’),并将刻度标记的字号设置为14(labelsize=14)。
最终的图表阅读起来容易得多,如图15-2所示:标签文字更大,线条也更粗了。通常,需要尝试不同的值,才能确定什么样的设置生成的图表最合适。
图形更容易看清后,我们发现没有正确地绘制数据:折线图的终点指出4.0的平方为25!下面来修复这个问题。
向plot()提供一系列数时,它假设第一个数据点对应的[插图]坐标值为0,但这里第一个点对应的[插图]值为1。为改变这种默认行为,可向plot()同时提供输入值和输出值:
mpl_squares.py
import matplotlib.pyplot as plt
input_values = [1, 2, 3, 4, 5]
squares = [1, 4, 9, 16, 25]
fig, ax = plt.subplots()
ax.plot(input_values, squares, linewidth=3)
# 设置图表标题并给坐标轴加上标签。
--snip--
现在plot()将正确地绘制数据,因为同时提供了输入值和输出值,plot()无须对输出值的生成方式做出假设。最终的图形是正确的,如图
使用plot()时可指定各种实参,还可使用众多函数对图形进行定制。本章后面处理更有趣的数据集时,将继续探索这些定制函数。
Matplotlib提供了很多已经定义好的样式,它们使用的背景色、网格线、线条粗细、字体、字号等设置很不错,让你无须做太多定制就可生成引人瞩目的可视化效果。要获悉在你的系统中可使用哪些样式,可在终端会话中执行如下命令:
>>> import matplotlib.pyplot as plt
>>> plt.style.available
['seaborn-dark', 'seaborn-darkgrid', 'seaborn-ticks', 'fivethirtyeight',
--snip--
可在生成图表的代码前添加如下代码行:mpl_squares.py
import matplotlib.pyplot as plt
input_values = [1, 2, 3, 4, 5]
squares = [1, 4, 9, 16, 25]
plt.style.use('seaborn')
fig, ax = plt.subplots()
--snip--
这些代码生成的图表如图所示。可供使用的内置样式有很多,请尝试使用它们,找出你喜欢的。
有时候,绘制散点图并设置各个数据点的样式很有用。例如,你可能想以一种颜色显示较小的值,用另一种颜色显示较大的值。绘制大型数据集时,还可对每个点都设置同样的样式,再使用不同的样式选项重新绘制某些点以示突出。
要绘制单个点,可使用方法scatter()。向它传递一对[插图]坐标和[插图]坐标,它将在指定位置绘制一个点:
catter_squares.py
import matplotlib.pyplot as plt
plt.style.use('seaborn')
fig, ax = plt.subplots()
ax.scatter(2, 4)
plt.show()
下面来设置图表的样式,使其更有趣。我们将添加标题,给坐标轴加上标签,并且确保所有文本都大到能够看清:
import matplotlib.pyplot as plt
plt.style.use('seaborn')
fig, ax = plt.subplots()
❶ ax.scatter(2, 4, s=200)
# 设置图表标题并给坐标轴加上标签。
ax.set_title("平方数", fontsize=24)
ax.set_xlabel("值", fontsize=14)
ax.set_ylabel("值的平方", fontsize=14)
# 设置刻度标记的大小。
ax.tick_params(axis='both', which='major', labelsize=14)
plt.show()
在❶处,调用scatter()并使用参数s设置绘制图形时使用的点的尺寸。如果此时运行scatter_squares.py,将在图表中央看到一个点,如图
要绘制一系列的点,可向scatter()传递两个分别包含[插图]值和[插图]值的列表,如下所示:scatter_squares.py
import matplotlib.pyplot as plt
x_values = [1, 2, 3, 4, 5]
y_values = [1, 4, 9, 16, 25]
plt.style.use('seaborn')
fig, ax = plt.subplots()
ax.scatter(x_values, y_values, s=100)
# 设置图表标题并给坐标轴指定标签。
--snip--
列表x_values包含要计算平方值的数,列表y_values包含前述数的平方值。将这些列表传递给scatter()时,Matplotlib依次从每个列表中读取一个值来绘制一个点。要绘制的点的坐标分别为(1, 1)、(2, 4)、(3, 9)、(4, 16)和(5, 25),最终的结果如图所示。
手工计算列表要包含的值可能效率低下,需要绘制的点很多时尤其如此。我们不必手工计算包含点坐标的列表,可以用Python循环来完成。下面是绘制1000个点的代码:scatter_squares.py
import matplotlib.pyplot as plt
❶ x_values = range(1, 1001)
y_values = [x**2 for x in x_values]
plt.style.use('seaborn')
fig, ax = plt.subplots()
❷ ax.scatter(x_values, y_values, s=10)
# 设置图表标题并给坐标轴加上标签。
--snip--
# 设置每个坐标轴的取值范围。
❸ ax.axis([0, 1100, 0, 1100000])
plt.show()
首先创建了一个包含[插图]值的列表,其中包含数1~1000(见❶)。接下来,是一个生成[插图]值的列表解析,它遍历[插图]值(for xin x_values),计算其平方值(x**2),并将结果存储到列表y_values中。然后,将输入列表和输出列表传递给scatter()(见❷)。这个数据集较大,因此将点设置得较小。
在❸处,使用方法axis()指定了每个坐标轴的取值范围。方法axis()要求提供4个值:[插图]和[插图]坐标轴的最小值和最大值。这里将[插图]坐标轴的取值范围设置为0~1100,并将[插图]坐标轴的取值范围设置为0~1 100 000。结果如图所示。
要修改数据点的颜色,可向scatter()传递参数c,并将其设置为要使用的颜色的名称(放在引号内),如下所示:
ax.scatter(x_values, y_values, c='red', s=10)
还可使用RGB颜色模式自定义颜色。要指定自定义颜色,可传递参数c,并将其设置为一个元组,其中包含三个0~1的小数值,分别表示红色、绿色和蓝色的分量。例如,下面的代码行创建一个由淡绿色点组成的散点图:
ax.scatter(x_values, y_values, c=(0, 0.8, 0), s=10)
值越接近0,指定的颜色越深;值越接近1,指定的颜色越浅。
颜色映射(colormap)是一系列颜色,从起始颜色渐变到结束颜色。在可视化中,颜色映射用于突出数据的规律。例如,你可能用较浅的颜色来显示较小的值,并使用较深的颜色来显示较大的值。
模块pyplot内置了一组颜色映射。要使用这些颜色映射,需要告诉pyplot该如何设置数据集中每个点的颜色。下面演示了如何根据每个点的[插图]值来设置其颜色:
scatter_squares.py
import matplotlib.pyplot as plt
x_values = range(1, 1001)
y_values = [x**2 for x in x_values]
ax.scatter(x_values, y_values, c=y_values, cmap=plt.cm.Blues, s=10)
# 设置图表标题并给坐标轴加上标签。
--snip--
我们将参数c设置成了一个[插图]值列表,并使用参数cmap告诉pyplot使用哪个颜色映射。这些代码将[插图]值较小的点显示为浅蓝色,并将[插图]值较大的点显示为深蓝色,结果如图所示。
要让程序自动将图表保存到文件中,可将调用plt.show()替换为调用plt.savefig():
plt.savefig('squares_plot.png', bbox_inches='tight')
第一个实参指定要以什么文件名保存图表,这个文件将存储到scatter_squares.py所在的目录。第二个实参指定将图表多余的空白区域裁剪掉。如果要保留图表周围多余的空白区域,只需省略这个实参即可。