本文首发于“生信补给站”公众号 https://mp.weixin.qq.com/s/HI92_O9uUiFgo_Gl_H6EXw
0引言
本文是 Python 系列的第三篇
- Python 入门篇 (上)
- Python 入门篇 (下)
- 数组计算之 NumPy (上)
- 数组计算之 NumPy (下)
- 科学计算之 SciPy
- 数据结构之 Pandas
- 基本可视化之 Matplotlib
- 统计可视化之 Seaborn
- 交互可视化之 Bokeh
- 炫酷可视化之 PyEcharts
- 机器学习之 Sklearn
- 深度学习之 TensorFlow
- 深度学习之 Keras
- 深度学习之 PyTorch
- 深度学习之 MXnet
Numpy 是 Python 专门处理高维数组 (high dimensional array) 的计算的包,每次使用它遇到问题都会它的官网 (www.numpy.org). 去找答案。 在使用 numpy 之前,需要引进它,语法如下:
import numpy
这样你就可以用 numpy 里面所有的内置方法 (build-in methods) 了,比如求和与均值。
numpy.sum()numpy.mean()
但是每次写 numpy 字数有点多,通常我们给 numpy 起个别名 np,用以下语法,这样所有出现 numpy 的地方都可以用 np 替代。
import numpy as np
为什么要专门学习数组呢?看下面「numpy 数组」和「列表」之间的计算效率对比:两个大小都是 1000000,把每个元素翻倍,运行 10 次用 %time 记时。
my_arr = np.arange(1000000)my_list = list(range(1000000))
%time for _ in range(10): my_arr2 = my_arr * 2
Wall time: 48.9 ms
%time for _ in range(10): my_list2 = [x * 2 for x in my_list]
Wall time: 1.33 s
我们发现「numpy 数组」效率是「列表」效率的 27 (1.33*1000/48.9) 倍左右。如果元素全是数值型变量 (numerical variable),那么 numpy 数组明显是个很好的数据结构。
学习 numpy 还是遵循的 Python 里「万物皆对象」的原则,既然把数组当对象,我们就按着数组的创建、数组的存载、数组的获取、数组的变形、和数组的计算来盘一盘 NumPy,目录如下:
有些读者可能会说,NumPy 都什么好学的,数组都弄不懂的人还能干什么,那我来问你个问题,知道「转置操作」吧,那么下面这个二维数组转置后是什么?
arr = np.array([[1,2,3],[4,5,6]])arr
array([[1, 2, 3], [4, 5, 6]])
太简单了,是 [[1,4], [2,5], [3,6]],来看看是不是。
arr.T
array([[1, 4], [2, 5], [3, 6]])
答对了,你牛,再看一道转置的题
arr = np.arange(16).reshape((2, 2, 4))arr
array([[[ 0, 1, 2, 3], [ 4, 5, 6, 7]], [[ 8, 9, 10, 11], [12, 13, 14, 15]]])
等等,现在有三维,转置通常不是转两个维度吗?转三个维度也可以?当然,比如把第 1, 2, 3 维度转置到第 2, 1, 3 维度,可以用 transpose 函数。
arr.transpose(1,0,2)
array([[[ 0, 1, 2, 3], [ 8, 9, 10, 11]], [[ 4, 5, 6, 7], [12, 13, 14, 15]]])
如果不知道上面答案怎么来的,我觉得你还是有必要看看本帖的。由于篇幅原因,NumPy 系列也分两贴,上贴讲前三节的内容,下帖讲后两节的内容。
1数组的创建
1.1 初次印象
数组 (array) 是相同类型的元素 (element) 的集合所组成数据结构 (data structure)。numpy 数组中的元素用的最多是「数值型」元素,平时我们说的一维、二维、三维数组长下面这个样子 (对应着线、面、体)。四维数组很难被可视化。
注意一个关键字 axis,中文叫「轴」,一个数组是多少维度就有多少根轴。由于 Python 计数都是从 0 开始的,那么
- 第 1 维度 = axis 0
- 第 2 维度 = axis 1
- 第 3 维度 = axis 2
但这些数组只可能在平面上打印出来,那么它们 (高于二维的数组) 的表现形式稍微有些不同。
分析上图各个数组的在不同维度上的元素:
- 一维数组:轴 0 有 3 个元素
- 二维数组:轴 0 有 2 个元素,轴 1 有 3 个元素
- 三维数组:轴 0 有 2 个元素 (2 块),轴 1 有 2 个元素,轴 2 有 3 个元素
- 四维数组:轴 0 有 2 个元素 (2 块),轴 1 有 2 个元素 (2 块),轴 2 有 2 个元素,轴 3 有 3 个元素
2.1 创建数组
带着上面这个对轴的认识,接下来我们用代码来创建 numpy 数组,有三种方式:
- 按步就班的 np.array() 用在列表和元组上
- 定隔定点的 np.arange() 和 np.linspace()
- 一步登天的 np.ones(), np.zeros(), np.eye() 和 np.random.random()
按步就班法
给了「列表」和「元组」原材料,用 np.array() 包装一下便得到 numpy 数组。
l = [3.5, 5, 2, 8, 4.2]np.array(l)
array([3.5, 5. , 2. , 8. , 4.2])
t = (3.5, 5, 2, 8, 4.2)np.array(t)
array([3.5, 5. , 2. , 8. , 4.2])
注意,numpy 数组的输出都带有 array() 的字样,里面的元素用「中括号 []」框住。
定隔定点法
更常见的两种创建 numpy 数组方法:
- 定隔的 arange:固定元素大小间隔
- 定点的 linspace:固定元素个数
先看 arange 例子:
print( np.arange(8) )print( np.arange(2,8) )print( np.arange(2,8,2))
[0 1 2 3 4 5 6 7] [2 3 4 5 6 7] [2 4 6]
函数 arange 的参数为起点 , 终点 , 间隔
arange(start , stop , step)
其中 stop 必须要有,start 和step 没有的话默认为 1。对着这个规则看看上面各种情况的输出。
注:用函数 print 打印 numpy 数组就没有 array() 的字样了,只用其内容,而且元素之间的「逗号」也没有了。
再看 linspace 的例子:
print( np.linspace(2,6,3) )print( np.linspace(3,8,11) )
[2. 4. 6.] [3. 3.5 4. 4.5 5. 5.5 6. 6.5 7. 7.5 8. ]
函数 linspace 的参数为起点 , 终点 , 点数
linspace (start , stop , num)
其中 start 和 stop 必须要有,num 没有的话默认为 50。对着这个规则看看上面各种情况的输出。
一步登天法
NumPy 还提供一次性
- 用 zeros() 创建全是 0 的 n 维数组
- 用 ones() 创建全是 1 的 n 维数组
- 用 random() 创建随机 n 维数组
- 用 eye() 创建对角矩阵 (二维数组)
对于前三种,由于输出是 n 为数组,它们的参数是一个「标量」或「元组类型的形状」,下面三个例子一看就懂了:
print( np.zeros(5) ) # 标量5代表形状(5,)print( np.ones((2,3)) )print( np.random.random((2,3,4)) )
[0. 0. 0. 0. 0.] [[1. 1. 1.] [1. 1. 1.]] [[[0.15684866 0.33684519 0.85095027 0.67827412] [0.58041935 0.12639616 0.33509142 0.99561644] [0.59581471 0.92043399 0.56731046 0.76811703]] [[0.74276133 0.85278489 0.32392871 0.40553182] [0.7718898 0.35496469 0.20061144 0.00351225] [0.49957334 0.48449498 0.62835324 0.29610557]]]
对于函数 eye(),它的参数就是一个标量,控制矩阵的行数或列数:
np.eye(4)
array([[1., 0., 0., 0.], [0., 1., 0., 0.], [0., 0., 1., 0.], [0., 0., 0., 1.]])
此外还可以设定 eye() 里面的参数 k
- 默认设置 k = 0 代表 1 落在对角线上
- k = 1 代表 1 落在对角线右上方
- k = -1 代表 1 落在对角线左下方
np.eye(4, k=1)
array([[0., 1., 0., 0.], [0., 0., 1., 0.], [0., 0., 0., 1.], [0., 0., 0., 0.]])