机器学习基础6--python画图库matplotlib(中)

上一篇讲了matplot画图的基本要素,这篇讲matplot几个基础图的画图操作。

折线图Polyline

画折线图的方法是pyplot.plot(),返回 matplotlib.lines.Line2D 对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import matplotlib.pyplot as plt
import numpy as np

x= np.linspace(0, 2, 100)

# label的值可以作为图例默认的值展示

plt.plot(x, x, label='linear')
plt.plot(x, x**2, label='quadratic')
plt.plot(x, x**3, label='cubic')

plt.xlabel('x label')
plt.ylabel('y label')

plt.title("Simple Plot")
plt.legend()
plt.show()

进一步的,我们可以在一张图上绘制多个子图(即一张Figure上绘制多个Axes),此时我们借助的是pyplot.subplot()方法
这里我们画一个余弦函数,一个自定义函数,然后上下分布。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import matplotlib.pyplot as plt
import numpy as np

def f(t):
return np.exp(-t) * np.cos(2 * np.pi * t)


t1 = np.arange(0.0, 5.0, 0.1)
t2 = np.arange(0.0, 5.0, 0.02)

plt.subplot(211) # the same as plt.subplot(2, 1, 1)
plt.plot(t1, f(t1), 'bo', t2, f(t2), 'k')

plt.subplot(212)
plt.plot(t2, np.cos(2 * np.pi * t2), 'r--')

plt.show()

散点图Scatter

画散点图的方法是pyplot.scatter(),返回 matplotlib.collections.PathCollection 对象,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import matplotlib.pyplot as plt
import numpy as np

n = 1024 # data size
X = np.random.normal(0, 1, n) # 每一个点的X值,平均数是0,方差是1
Y = np.random.normal(0, 1, n) # 每一个点的Y值
T = np.arctan2(Y, X) # for color value

# 散点图
# s size,数字越大,点的面积就越大
# c color 颜色,有多种表达方式。
# aplha 透明度 0(完全透明)到1之间
plt.scatter(X, Y, s=75, c=T, alpha=0.5)

plt.xlim(-1.5, 1.5)
plt.xticks(()) # ignore xticks
plt.ylim(-1.5, 1.5)
plt.yticks(()) # ignore yticks

plt.show()

其中关于颜色的设置这部分,我们先看下官方注释里面的表达方式:
# - A single color format string.
# - A sequence of color specifications of length n.
# - A sequence of n numbers to be mapped to colors using cmap and
# norm.
# - A 2-D array in which the rows are RGB or RGBA.

颜色的表达方式

字符串表示法

A single color format string.
字符串表示的颜色,比如说红色可以用’red’或者’r’表示

1
plt.scatter(X, Y, s=75, c='r', alpha=0.5)

字符串序列表示法

A sequence of color specifications of length n.
用一个长度为n的颜色序列

1
2
T = ['red'] * 512 + ['blue'] * 512
plt.scatter(X, Y, s=75, c=T, alpha=0.5)

cmap表示法

具体可以参考这篇文章 画图离不开色彩–说说matplot的cmap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import matplotlib.pyplot as plt
import numpy as np

n = 1024 # data size
X = np.random.normal(0, 1, n) # 每一个点的X值,平均数是0,方差是1
Y = np.random.normal(0, 1, n) # 每一个点的Y值

# 这里我们每个点的颜色和该点的X值+Y值的和相关
color = X + Y

# 使用名为Spectral的cmap
cmap = plt.get_cmap('Spectral')
# cmap = plt.cm.Spectral #也可以这么写
# 利用normlize来标准化颜色的值
norm = plt.Normalize(vmin=-3, vmax=3)

# 散点图
plt.scatter(X, Y, s=75, alpha=0.5, c=color, cmap=cmap, norm=norm)

plt.xlim(-1.5, 1.5)
plt.xticks(()) # ignore xticks
plt.ylim(-1.5, 1.5)
plt.yticks(()) # ignore yticks

plt.show()

RGB,RGBA二维数组表示法

很简单,和字符串表达方式类似,RGB或RGBA的表达方式可以表示的颜色更多。

1
2
T = ['#42A5F5'] * 512 + ['#FF5252'] * 512
plt.scatter(X, Y, s=75, c=T)

特别的,如果所有点都是同一个颜色:

1
2
T = ['#42A5F5']
plt.scatter(X, Y, s=75, c=T)

柱状图Bar

画柱状图的方法是 pyplot.bar(),返回 matplot.container.BarContainer 对象

1
2
3
4
5
6
7
8
9
import matplotlib.pyplot as plt
import numpy as np

n = 12
X = np.arange(n)
Y1 = (1 - X / float(n)) * np.random.uniform(0.5, 1.0, n)
# facecolor柱子的填充色,edgecolor柱子的边缘色
plt.bar(X, +Y1, facecolor='#9999ff', edgecolor='red')
plt.show()

更进一步,我们将两个柱状图上下叠放在一起,并标注上具体的数值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import matplotlib.pyplot as plt
import numpy as np

n = 12
X = np.arange(n)
Y1 = (1 - X / float(n)) * np.random.uniform(0.5, 1.0, n)
Y2 = (1 - X / float(n)) * np.random.uniform(0.5, 1.0, n)

# 柱状图
plt.bar(X, +Y1, facecolor='#9999ff', edgecolor='white')
plt.bar(X, -Y2, facecolor='#ff9999', edgecolor='white')

plt.xlim(-.5, n)
plt.xticks(())
plt.ylim(-1.25, 1.25)
plt.yticks(())

# 添加文字
for x, y in zip(X, Y1):
# ha: horizontal alignment
# va: vertical alignment
plt.text(x, y + 0.05, '%.2f' % y, ha='center', va='bottom')

for x, y in zip(X, Y2):
# ha: horizontal alignment
# va: vertical alignment
plt.text(x, -y - 0.05, '%.2f' % y, ha='center', va='top')

plt.show()

直方图Histogram

画柱状图的方法是 pyplot.hist(),返回 matplotlib.patches.Patch 对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import matplotlib.pyplot as plt
import numpy as np

np.random.seed(19680801)

mu1, sigma1 = 100, 15
mu2, sigma2 = 80, 15
x1 = mu1 + sigma1 * np.random.randn(10000)
x2 = mu2 + sigma2 * np.random.randn(10000)

# the histogram of the data
# 50:将数据分成50组
# facecolor:颜色;alpha:透明度
# density:是密度而不是具体数值
n1, bins1, patches1 = plt.hist(x1, 50, density=True, facecolor='g', alpha=1)
n2, bins2, patches2 = plt.hist(x2, 50, density=True, facecolor='r', alpha=0.2)

# n:概率值;bins:具体数值;patches:直方图对象。

plt.xlabel('Smarts')
plt.ylabel('Probability')
plt.title('Histogram of IQ')

plt.text(110, .025, r'$\mu=100,\ \sigma=15$')
plt.text(50, .025, r'$\mu=80,\ \sigma=15$')

# 设置x,y轴的具体范围
plt.axis([40, 160, 0, 0.03])
plt.grid(True)
plt.show()

饼状图Pie

画饼状图的方法是 pyplot.pie(),返回 matplotlib.patches.Wedge 对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import matplotlib.pyplot as plt

plt.figure(figsize=(6, 9))
labels = [u'TypeA', u'TypeB', u'TypeC', u'TypeD'] # 定义标签
values = [46, 253, 321, 66] # 每块值
colors = ['red', 'yellowgreen', 'lightskyblue', 'yellow'] # 每块颜色定义
explode = (0, 0, 0, 0) # 将某一块分割出来,值越大分割出的间隙越大
patches, text1, text2 = plt.pie(values,
explode=explode,
labels=labels,
colors=colors,
autopct='%.2f%%', # 数值保留固定小数位
shadow=False, # 无阴影设置
startangle=90, # 逆时针起始角度设置
pctdistance=0.6) # 数值距圆心半径倍数距离
# patches饼图的返回值,texts1饼图外label的文本,texts2饼图内部的文本
# x,y轴刻度设置一致,保证饼图为圆形
plt.axis('equal')
plt.show()

调整饼的偏离值

首先我们看explode参数,explode接受一个长度=值数量的数组,数组中的值的含义:

1
2
# 正值表示向外偏离
explode = (0.3, 0, 0, 0)

1
2
# 副值表示向外偏离
explode = (-0.3, 0, 0, 0)

标注字符串的格式化

autopct参数可以接受None(默认),字符串或者函数。如果是一个字符串,则按照fmt%pct的方式格式化。

1
2
# 表示%分数表示,并保留两位小数
autopct='%.2f%%'

如果是函数的话,可以这样写:

1
2
3
4
5
6
7
8
9
10
11
# 返回值是一个函数,该函数接受一个值,返回一个字符串
def make_autopct(values):
def my_autopct(pct):
total = sum(values)
val = int(round(pct * total / 100.0))
return '{p:.2f}% \n ({v:d})'.format(p=pct, v=val)

return my_autopct

# 用的时候这样
autopct=make_autopct(values)

等高线图Contours

画等高线用的是plt.contour(),返回 matplot.contour.QuadContourSet 对象

首先我们需要了解,等高线图的数据和前面散点图和柱状图的二维数据结构不一样,多了一个维度:高度。也就是说,等高线图的数据集是由(x,y,h)这个三维点构成。

生成数据集:

1
2
3
4
5
6
7
8
9
10
11
12
13
import matplotlib.pyplot as plt
import numpy as np

# 根据x,y生成高度值
def f(x, y):
# the height function
return (1 - x / 2 + x ** 5 + y ** 3) * np.exp(-x ** 2 - y ** 2)

n = 256
x = np.linspace(-3, 3, n)
y = np.linspace(-3, 3, n)
# 通过meshgrid()方法得到坐标矩阵
X, Y = np.meshgrid(x, y)

等高线间区域填充

1
2
3
# plt.contourf()函数进行颜色填充, 
plt.contourf(X, Y, f(X, Y), 8, alpha=.75, cmap=plt.cm.hot)
plt.show()

画等高线

1
2
# 绘制等高线
C = plt.contour(X, Y, f(X, Y), 8, colors='black', linewidth=.5)

等高线的标注

1
2
#inline表示Label画在线内
plt.clabel(C, inline=True, fontsize=10)

三维图

绘制三维坐标轴空间

首先需要导入mpl_toolkits.mplot3d包中的Axes3D

1
2
3
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

创建Figure对象,并用Axes3D画三维坐标轴

1
2
fig = plt.figure()
ax = Axes3D(fig)

3D散点图

同样的,我们可以在三维坐标系中画散点图,区别只是数据有三个维度

1
2
3
data = np.random.randint(0, 255, size=[40, 40, 40])
x, y, z = data[0], data[1], data[2]
ax.scatter(x[:10], y[:10], z[:10], c='r')

3D平面图

画三维平面图用到的是Axes3D.plot_surface()方法,该方法创建 mpl_toolkits_mlplot3d_art3d.Poly3DCollection 对象

1
2
3
4
5
6
7
8
X = np.arange(-4, 4, 0.25)
Y = np.arange(-4, 4, 0.25)
X, Y = np.meshgrid(X, Y) # x-y 平面的网格
R = np.sqrt(X ** 2 + Y ** 2)
# height value
Z = np.sin(R)
# # rstride代表行的跨度,cstride代表列的跨度
ax.plot_surface(X, Y, Z, rstride=5, cstride=5, cmap=plt.get_cmap('rainbow'))

将跨度改成1,再看效果

1
ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=plt.get_cmap('rainbow'))

zdir可选择的值有x,y,z,选择z相当于投影到XY平面,同样的,选择x相当于投影到YZ平面,选择y相当于投影到XZ平面。

1
ax.contourf(X, Y, Z, zdir='z', offset=-2, cmap=plt.get_cmap('rainbow'))