本文是 Introduction to Data Science 的一部分
你们就照着文档念吧,谁照着念能念的过你们啊,活爹
快速开始
实际上这玩意就是一个 Python 版的 Matlab 绘图库
对于有 Matlab 经验的人来说基本就是换个地方写一样的东西
接下来的每一个代码块都默认附加在上一个代码块的后面
导入
1 2 3 4 5 6 7 8
| %matplotlib inline
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
|
其中,inline
会嵌入静态图片,notebook
会嵌入交互式图片
尝试
1 2 3 4 5 6 7
| x = np.linspace(0, 10, 200)
plt.plot(x, np.sin(x)) plt.plot(x, np.cos(x))
plt.show()
|
保存
1 2 3 4 5 6 7 8
| fig = plt.figure()
plt.plot(x, np.sin(x), '-')
fig.savefig('my_figure.svg')
fig.canvas.get_supported_filetypes()
|
两种绘图方式
MATLAB 风格
对于一般的绘图来说,这种方式更加直观简单
1 2 3 4 5 6 7 8 9 10
| plt.figure()
plt.subplot(2, 1, 1)
plt.plot(x, np.sin(x))
plt.subplot(2, 1, 2)
plt.plot(x, np.cos(x))
|
创建子图:subplot(rows: 子图行数, columns: 子图列数, subplot_number: 子图序号)
绘制图形:plot(x: x 轴数据, y: y 轴数据, …)
面向对象风格
对于复杂的绘图来说,这种方式更加灵活
1 2 3 4 5 6
| fig, ax = plt.subplots(2)
ax[0].plot(x, np.sin(x))
ax[1].plot(x, np.cos(x))
|
subplots 会返回一个包含所有子图的数组
基本图形
线图
1 2 3 4
| plt.plot(range(1, 10))
plt.plot(range(10, 1, -1), np.arange(1, 10))
|
plot(y: y 轴数据, …)
x 会自动使用 0 到 len(y) - 1 的整数
使用 OOP
1 2 3 4 5 6 7 8 9 10
| fig = plt.figure()
ax = plt.axes()
x = np.linspace(0, 5, 20)
ax.plot(x, np.sin(x))
ax.plot(x, np.cos(x))
|
linspace(start: 起始值, stop: 结束值, num: 生成的数据个数)
该函数会返回一个包含 num 个元素的等差数列
多次调用 plot 会在同一张图上绘制多个图形
plot
1 2 3 4 5 6 7 8 9 10 11 12
| plot( x: x 轴数据, y: y 轴数据, linestyle: 线条风格, linewidth: 线宽, color: 颜色, marker: 为线图添加散点,指定点的形状, markersize: 点大小, markeredgecolor: 点边框颜色, label: 图例标签, alpha: 透明度 )
|
颜色
plot 会自动循环使用颜色,但是也可以手动指定
1 2 3 4 5 6 7 8 9 10
| plt.plot(x, 2*x+1, color = "g")
plt.plot(x, 2*x+2, color = "0.6")
plt.plot(x, 2*x+3, color = "#FFEE22")
plt.plot(x, 2*x+4, color = (0.8, 0.7, 0.1))
plt.plot(x, 2*x+5, color = "chartreuse")
|
线条风格
plot(…, linestyle: 线条风格)
使用名称
1 2 3 4 5 6 7 8
| plt.plot(x, 2*x, linestyle = "solid")
plt.plot(x, 2*x+1, linestyle = "dashed")
plt.plot(x, 2*x+2, linestyle = "dotted")
plt.plot(x, 2*x+3, linestyle = "dashdot")
|
使用符号
1 2 3 4 5 6 7 8
| plt.plot(x, 2*x, linestyle = "-")
plt.plot(x, 2*x+1, linestyle = "--")
plt.plot(x, 2*x+2, linestyle = ":")
plt.plot(x, 2*x+3, linestyle = "-.")
|
我们还可以把颜色和线条风格合并在一起
1 2 3 4
| plt.plot(x, 2*x, "g--")
plt.plot(x, 2*x+1, ":b")
|
图例
虽然 plot 提供了 label 参数,但需要 legend() 才能显示
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 31 32 33 34
| x = range(0, 10) y = np.cos(x)
plt.plot( x, y, linestyle = '-.', linewidth = 1, color = 'blue', marker = 'o', markersize = 10, markeredgecolor = 'r', label = 'Cos', alpha = 0.5 )
y2 = np.sin(x)
plt.plot( x, y2, linestyle = '--', linewidth = 1, color = 'red', marker = 'x', markersize = 10, markeredgecolor = 'b', label = 'Sin', alpha = 0.5 )
plt.legend()
|
标题标签
1 2 3 4 5 6
| x = np.linspace(0, 10, 200) plt.plot(np.sin(x))
plt.title('Sine Curve') plt.xlabel('Radian') plt.ylabel('Magnitude')
|
范围
1 2 3 4 5 6
| plt.plot(np.sin(x))
plt.xlim(50, 175)
plt.ylim(-0.5, 1)
|
如果将参数反转,可以实现坐标轴的翻转
1 2 3 4 5 6
| plt.plot(np.sin(x))
plt.xlim(175, 50)
plt.ylim(1, -0.5)
|
axis
我们还可以通过 axis: [xmin, xmax, ymin, ymax]
函数一次性设置
1 2 3 4 5
| plt.plot(np.sin(x))
plt.axis([175, 50, -0.5, 1])
|
它还支持自动调整
axis('tight')
会自动调整到数据的最小范围
axis('equal')
会使 x 和 y 与屏幕宽高比一致
axis('scaled')
会使 x 和 y 的单位长度相等,不会调整到数据的最小范围
axis('square')
会使 x 和 y 的单位长度相等,并且调整到数据的最小范围
axis('off')
会关闭坐标轴
可以使用 plt.axis?
查看更多信息
散点图
今天做 quiz 的时候居然在一个非常简单的问题上选错了,不能再摆了
散点图在观察数据分布的时候非常有用
1 2 3
| x = range(1, 11)
plt.plot(x, x, "o")
|
还可以使用 scatter
函数,其提供了更多可以自定义的特性
形状
Matplotlib 支持很多点的形状
1 2 3 4 5 6 7 8 9 10
| rand = np.random.RandomState(42)
for marker in ['o', '.', ',', 'x', '+', 'v', '^', '<', '>', 's', 'd']: plt.plot(rand.rand(5), rand.rand(5), marker, label = "marker = '{}'".format(marker))
plt.legend()
plt.xlim(0, 1.8)
|
透明度
点太多会重叠,不便于观察
1 2 3 4 5
| x = rand.rand(200) y = rand.rand(200)
plt.scatter(x, y, alpha = 0.5)
|
颜色与大小
1 2 3 4 5 6 7 8 9 10
| x = rand.rand(100) y = rand.rand(100)
colors = rand.rand(100) sizes = 1000 * rand.rand(100)
plt.scatter(x, y, c = colors, s = sizes, alpha = 0.5)
plt.colorbar()
|
条形图
PPT 专用图形
1 2 3 4
| x = range(1, 6) y = [1, 4, 6, 8, 4]
plt.bar(x, y)
|
还可以是水平的
分组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| member = ['A', 'B', 'C', 'D'] jan = [30, 40, 50, 60] feb = [35, 45, 55, 65] mar = [40, 50, 60, 70]
width = 0.2
plt.bar(range(4), jan, width = width, label = 'Jan') plt.bar(np.arange(4) + width, feb, width = width, label = 'Feb') plt.bar(np.arange(4) + width * 2, mar, width = width, label = 'Mar')
plt.legend()
plt.xticks(np.arange(4) + width, member)
plt.ylabel('Revenue')
plt.grid()
plt.show()
|
堆叠
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| plt.bar(np.arange(4), jan, label = 'Jan') plt.bar(np.arange(4), feb, bottom = jan, label = 'Feb') plt.bar(np.arange(4), mar, bottom = np.array(jan) + np.array(feb), label = 'Mar')
plt.legend()
plt.xticks(np.arange(4), member)
plt.ylabel('Revenue')
plt.grid()
plt.show()
|
bottom 让数据在上一个数据的基础上偏移
np.array 便于元素级别(向量化)运算
直方图
1 2 3 4 5 6 7 8 9
| x1 = np.random.normal(0, 0.4, 1000) x2 = np.random.normal(-3, 1, 1000) x3 = np.random.normal(2, 2, 1000)
kwargs = dict(histtype='stepfilled', alpha=0.5, density=True, bins=40)
plt.hist(x1, **kwargs) plt.hist(x2, **kwargs) plt.hist(x3, **kwargs)
|
参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| plt.hist( x: 数据, bins: 柱数, range: 上下边界, density: 频数转换成频率, weights: 每个数据的权重, cumulative: 计算累计频数或频率, bottom: 基准线, histtype: 柱状图类型 _bar_ / barstacked / step / stepfilled, align: 边界对齐方式 left / _mid_ / right, orientation: 方向 _vertical_ / horizontal, rwidth: 柱宽, log: 是否对 y 轴取对数, color: 颜色, label: 图例标签, stacked: 有多个数据时是否堆叠 默认水平 )
|
二维数据
二维直方图在两个维度进行切分,来查看数据的分布
1 2 3 4 5
| x = np.random.randn(1000) y = np.random.randn(1000)
plt.hist2d(x, y, bins=30, cmap='Blues') plt.colorbar()
|
饼图