数据可视化指的是通过可视化表示来探索数据。 它与数据分析紧密相关, 而数据分析指的是使用代码来探索数据集的规律和关联。 数据集可以是用一行代码就能表示的小型数字列表, 也可以是数千兆字节的数据。
漂亮地呈现数据并非仅仅关乎漂亮的图片。 通过以引人注目的简单方式呈现数据, 能让观看者明白其含义: 发现数据集中原本未知的规律和意义。
Python数据可视化的流行工具包括Matpplotlib,这是一个绘图库,我们可以使用这个库,根据数据绘出相应的图表。
Python并没有自动安装matplotlib这个库,如果想使用该库,就需要自己进行安装,
pip install matplotlib
通过该语句进行安装即可。
import matplotlib.pyplot as plt
squares = [1, 4, 9, 16, 25]
x = [1, 2, 3, 4, 5]
fig, ax = plt.subplots()
ax.plot(x, squares)
plt.show()
首先这里,我导入了matplotlib库的pyplot包,并起了一个plt的别名方便使用。
然后我们创建了一个squares和x两个列表,在其中存储了用来绘图使用的坐标数据,然后我们调用了subplots()函数。subplots()函数可以在一张图片中绘制一个或多个图表。变量fig表示一整张图片,变量ax表示图片中的各个图表。
注释:fig , ax = plt.subplots(nrows, ncols) subplots()函数具体使用方法,我们在subplots()函数中给出行数和列数,这样就可以分为相应张小图,其中ax是一个数组,具体的对每张子图的操作是,ax[0][0],a[0][1]…如此,subplots()函数中无输入,默认为1张子图。
接下来我们调用plot()函数,向其中传入两个参数x和squares两个列表,x作为x轴坐标出现,squares则作为y轴来绘制。并使用plt.show()来展示绘制后的图像
plot()函数的函数头
matplotlib.pyplot.plot(*args, scalex=True, scaley=True, data=None, **kwargs)
#调用格式说明
plot([x], y, [fmt], *, data=None, **kwargs)
plot([x], y, [fmt], [x2], y2, [fmt2], ..., **kwargs)
plot()方法一般是用来绘制线条的,包括直线、折线等,从上面的调用格式说明中可以看到,最简洁的调用方式是直接传入一个数组对象y,其他参数都是可选的。并且当之传入一个数据列表时,这个数据列表会被默认为是Y轴数据,而X轴数据则是由数据的下标组成。当我们同时传入两个数据列表的时候,第一个数据列表会被认为是X轴数据,第二个数据列表被作为Y轴数据。
plot()函数还有一些其他的使用参数,在接下来的使用中遇到会进行补充。
squares = [1, 4, 9, 16, 25]
x = [1, 2, 3, 4, 5]
fig, ax = plt.subplots()
#设置图表标题
ax.set_title("square of values", fontsize=24)
#设置x轴标签
ax.set_xlabel("value", fontsize=16)
#设置y轴标签
ax.set_ylabel("square", fontsize=16)
ax.plot(x, squares)
plt.show()
通过set_title()函数来设置图标的标题,通过set_xlabe()和set_ylabel()函数来设置x轴和y轴的名称。
无论是使用scatter()函数绘制一个点的散点图,还是一系列点的散点图,其基本的操作都是一致的。就是都需要向scatter()函数中传递x参数和y参数。
squares = [1, 4, 9, 16, 25]
x = [1, 2, 3, 4, 5]
plt.style.use('seaborn')
fig, ax = plt.subplots()
ax.scatter(x, squares, s=50)
ax.set_title("square of values")
ax.set_xlabel("value")
ax.set_ylabel("square")
plt.show()
这里我们调用scatter()函数,将x和squares作为数据列表传入,分别代表了x轴坐标值和y轴坐标值。并且给出了s=50(s是size 的缩写),这个s用来描述散点图每个点的大小。
所以绘图最基本的情况是什么呢,是数据,以及使用正确的函数进行绘图。
我们在更广泛的使用python绘图方法时,得到数据未必是早就编写好的,有些数据必然是计算得到的。
这里我们利用python绘制一个正弦函数图像和余弦函数图像,
import matplotlib.pyplot as plt
import numpy as np
import math
#正弦和余弦函数图像
x = np.arange(0, math.pi*2, 0.05)
sinx = np.sin(x)
cosx = np.cos(x)
fig, ax = plt.subplots()
ax.plot(x, sinx, color='red')
ax.plot(x, cosx, color='green')
#标题信息
ax.set_title("sin/cos wave", fontsize=14)
ax.set_ylabel("sin/cos value", fontsize=12)
ax.set_xlabel("x values", fontsize=12)
plt.show()
这里我们调用了另外一个数据处理上很常用的库numpy,对于矩阵类的数据非常实用。首先我们用numpy的arange()函数在(0,2pi)之间,每隔0.05取一个数字,组成一个列表,然后我们调用numpy的sin()和cos()函数来计算对应的sin值和cos值。并将两个数据列表给到plot中,绘制出图像。
有些时候我们希望能够对不同点或者不同的曲线用不同的颜色表示出来。不论是对于scatter()函数还是plot()函数我们都可以给出一个color=‘’的参数,来指定颜色。
还可使用RGB颜色模式自定义颜色。 要指定自定义颜色, 可传递参数c, 并将其设置为一个元组, 其中包含三个0~1的小数值, 分别表示红色、 绿色和蓝色的分量。值越接近0, 指定的颜色越深; 值越接近1, 指定的颜色越浅。这种方式下使用方式类似为color=(0.5, 1, 0.5)
颜色映射(colormap) 是一系列颜色, 从起始颜色渐变到结束颜色。 在可视化中, 颜色映射用于突出数据的规律。
#渐变色
x_values = np.arange(1, 200, 0.5)
y_values = [2*(x**2)+3*x+1 for x in x_values]
fig, ax = plt.subplots()
ax.scatter(x_values, y_values, c = x_values, cmap=plt.cm.Blues, s=10)
ax.set_title("2x^2+3x+1")
plt.show()
我们将参数c设置成了一个 值列表, 并使用参数cmap告诉pyplot使用哪个颜色映射。 这些代码将 值较小的点显示为浅蓝色, 并将值较大的点显示为深蓝色。
from random import choice
class RandomWalk:
"""一个生成随机漫步数据的类"""
def __init__(self, num_points=5000):
"""初始化随机漫步的属性 """
self.num_points = num_points;
#所有随机漫步都始于(0,0)
self.x_values = [0]
self.y_values = [0]
先随机定义一个RandomWalk类,在其初始化函数__init__()中我们给出随机漫步点的数量为5000,并且创建x_values和y_values两个列表来存储每次漫步的所得到的值。
def fill_walk(self):
""" 计算随机漫步所包含的所有点 """
direction = [-1, 1]
distance = [0, 1, 2, 3, 4]
#不断漫步,直到列表达到指定的长度
while len(self.x_values) < self.num_points:
# 决定前进方向以及沿这个方向前进的距离
x_direction = choice(direction)
x_distance = choice(distance)
x_step = x_direction * x_distance
y_direction = choice(direction)
y_distance = choice(distance)
y_step = y_direction * y_distance
# 拒绝原地踏步
if x_step == 0 and y_step == 0:
continue
# 计算下一个点的x值和y值
x = self.x_values[-1] + x_step
y = self.y_values[-1] + y_step
self.x_values.append(x)
self.y_values.append(y)
fill_walk()函数是随机漫步的核心,决定了下一次点位出现的值。最外层用一个while循环来确保能够采满足够的样本数。函数的前半段决定了x轴上移动方向和移动距离,y轴上的移动方向和移动距离。通过choice函数随机选取一个方向和距离。如果该次随机结果的x轴移动和y轴移动均为0,则表明这是一个无效移动,则重新采样。我们将随机的方向与距离在上一个坐标点的基础上做出移动得到本次的坐标位置。
x
(
i
)
=
x
(
i
−
1
)
+
x
_
s
t
e
p
y
(
i
)
=
y
(
i
−
1
)
+
y
_
s
t
e
p
注释:
choice()方法返回一个列表,元组或字符串的随机项。也就是我们向choice()函数中传入一个列表,choice()方法随机的返回这个列表中的某一项的值。
rw = RandomWalk()
rw.fill_walk()
#根据随机漫步点来绘制漫步图
# plt.style.use('classic')
fig, ax = plt.subplots()
ax.scatter(rw.x_values, rw.y_values, s=15)
plt.show()
我们使用RandomWalk()这个类来生成一个对象,并调用对象的fill_walk()方法实现数据的随机采样得到x_values和y_values,我们根据其结果得到相应的图像。
要让程序自动将图标保存到文件中,可以调用savefig()函数
plt.savefig('---.png', bbox_inches='tight')
第一个实参指定要以什么文件名保存图表, 这个文件将存储到代码文件所在的目录。 第二个实参指定将图表多余的空白区域裁剪掉。
通过设置点的颜色,我们能够将一些我们关注的数据突出出来,而不是让一些不重要的点分散了我们的注意力。
给点着色
使用颜色映射来给漫步中的各点进行着色。
rw = RandomWalk()
rw.fill_walk()
#根据随机漫步点来绘制漫步图
# plt.style.use('classic')
fig, ax = plt.subplots()
point_numbers = range(rw.num_points)
ax.scatter(rw.x_values, rw.y_values, s=15, c=point_numbers, cmap=plt.cm.Reds)
plt.show()
按照各个点的生成顺序,来进行颜色映射,先生成的点颜色较浅后生成的点颜色较深,这样就能清晰看出数据的走向。
重新绘制起点和终点
除了给随机漫步的各个点着色,以指出其先后顺序外。我们还可以特别标识出随机漫步的起点和终点。
而其中办法则比较简单就是重新对起点和重点两个坐标值的点重新以不同颜色进行绘制即可。
rw = RandomWalk()
rw.fill_walk()
#根据随机漫步点来绘制漫步图
fig, ax = plt.subplots()
point_numbers = range(rw.num_points)
ax.scatter(rw.x_values, rw.y_values, s=15, c=point_numbers, cmap=plt.cm.Reds)
ax.scatter(rw.x_values[0], rw.y_values[0], s=15, c='green', edgecolor='none')
ax.scatter(rw.x_values[-1], rw.x_values[-1], s=50, c='blue', edgecolor='none')
plt.show()
这里我们对初始点和终止点用其他颜色做了特殊标记,来达到效果。
隐藏坐标轴
我们可以通过get_xaxis().set_visible()和get_yaxis().set_visible()方法设置为False,将x轴和y轴隐藏。
rw = RandomWalk()
rw.fill_walk()
#根据随机漫步点来绘制漫步图
# plt.style.use('classic')
fig, ax = plt.subplots()
point_numbers = range(rw.num_points)
ax.scatter(rw.x_values, rw.y_values, s=15, c=point_numbers, cmap=plt.cm.Reds)
ax.scatter(rw.x_values[0], rw.y_values[0], s=15, c='green', edgecolor='none')
ax.scatter(rw.x_values[-1], rw.x_values[-1], s=50, c='blue', edgecolor='none')
ax.get_xaxis().set_visible(False)
plt.show()
这样我们就可以将x轴坐标隐藏起来。
调整尺寸以适合屏幕
图表适合屏幕大小时, 更能有效地将数据中的规律呈现出来。 为让绘图窗口更适合屏幕大小,我们可以给出初始化的图表尺寸大小。一种具体可行的方法:
matplotlib.pyplot.subplots(figsize(15,9)) 创建一个图表,这里已经向Matplotlib指出绘图窗口的尺寸,单位为英寸。
Matplotlib假定屏幕分辨率为100像素/英寸。 如果上述代码指定的图表尺寸不合适, 可根据需要调整数字。 如果知道当前系统的分辨率, 可通过参数dpi向plt.subplots()传递该分辨率, 以有效利用可用的屏幕空间, 如下所示:
fig, ax = plt.subplots(figsize=(10,6),dpi=128)
在这里编写一个骰子类:
from random import randint
class Die:
"""表示一个骰子的类 """
def __init__(self, num_sides=6):
"""骰子默认为6面"""
self.num_sides = num_sides
def roll(self):
"""返回一个位于1和骰子面数之间的随机值"""
return randint(1, self.num_sides)
注释:randint()函数既包括左面的值,也包括号右面的值,即randint(1,6)是在[1,6]这个闭空间上得到一个值。
我们可以通过n次摇骰子,来统计每个数字出现的频率,并根据频率来绘制一个直方图。
#保存每次的随机结果
results = []
for roll_num in range(100):
result = die.roll()
results.append(result)
#分析结果
frequencies = []
for value in range(1, die.num_sides+1):
frequency = results.count(value)
frequencies.append(frequency)
#对结果进行可视化
x_values = list(range(1, die.num_sides+1))
data = [Bar(x=x_values, y=frequencies)]
x_axis_config = {'title': '结果'}
y_axis_config = {'title': '结果的频率'}
my_layout = Layout(title='掷骰子 100次的频率结果', xaxis=x_axis_config,
yaxis=y_axis_config)
offline.plot({'data': data, 'layout': my_layout}, filename='d6.html')
Plotly类Bar()表示用于绘制条形图的数据集,需要一个存储x值的列表和一个存储y值的列表。这个类必须放在方括号内,因为数据集可能包含多个元素。
这里,真正用来绘图的函数就是offline.plot()函数,并向是以字典的形式传入了两个参数,一个是data参数,一个是my_layout参数。注释:这个函数需要一个包含数据和布局对象的字典, 还接受一个文件名, 指定要将图表保存到哪里。
#创建两个骰子
die1 = Die()
die2 = Die()
results = []
for roll_num in range(1000):
result = die1.roll() + die2.roll()
results.append(result)
frequencies = []
max_results = die1.num_sides + die2.num_sides
x_values = list(range(2, max_results + 1))
for x_value in x_values:
frequency = results.count(x_value)
frequencies.append(frequency)
#可视化结果
data = [Bar(x=x_values, y=frequencies)]
x_axis_config = {'title': '结果', 'dtick': 1}
y_axis_config = {'title': '结果的频率'}
my_layout = Layout(title='同时投掷两个骰子的结果频率',
xaxis=x_axis_config,
yaxis=y_axis_config)
offline.plot({'data': data, 'layout': my_layout}, filename='d6_d6.html')
这里创建字典的时候,写入了一个dtick键,这项设置指定了x轴显示的刻度间距。这里绘制的直方图包含的条形更多,Plotly默认只显示某些刻度值, 而设’dtick’: 1让Plotly显示每个刻度值。
有很多知识没有进行详细说明,可以等实际应用的时候再细说。