数组 (ndarray)介绍
这个数组我感觉更像是矩阵,官方文档说它是一个多维数组对象(ndarray)。
NumPy provides an N-dimensional array type, the ndarray, which describes a collection of “items” of the same type. The items can be indexed using for example N integers.
Array 的数据结构:
ndarray 是一个通用的同构数据多维容器,数组中的所有元素类型都必须是相同的。每个数组都有一个 shape 和一个 dtype,分别表示数组的维度和元素的数据类型。
创建数组
直接用 np.array()函数将其他序列转换成 ndarray 数组
输入数据可以是列表、元组、数组等序列类型
|
|
array([1, 2, 3, 4])
|
|
array([1, 2, 3, 4])
|
|
1
1
i:\python364\lib\site-packages\ipykernel_launcher.py:1: VisibleDeprecationWarning: rank
is deprecated; use the ndim
attribute or function instead. To find the rank of a matrix see numpy.linalg.matrix_rank
.
“““Entry point for launching an IPython kernel.
numpy.ndarray
- rank 表示数组的维数
|
|
(4,)
这表示是一维向量,但未指定是行向量还是列向量
- 可以用 reshape 函数指定
|
|
(1, 4)
|
|
(4, 1)
|
|
[[1 2]
[3 4]]
(2, 2)
- NumPy 的数组索引是从 0 开始的
|
|
[[1 2][3 4]]
4
[[ 1 2][88 4]]
还可以用这些函数新建数组
- ones 创建元素为全 1 的数组
- zeros 创建元素为全 0 的数组
- full 还可以用 full 函数实现
- eye/identity 创建单位矩阵
- empty 创建新数组,只分配内存,但不填充值
- ones_like 以另一个数组为参数,根据其形状和数据类型创建元素全 1 的数组,类似的有 zeros_like、empty_like
- random 创建元素值为(0,1)范围的随机值矩阵
|
|
array([[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]])
|
|
array([[0., 0., 0.],
[0., 0., 0.]])
|
|
array([[1, 1, 1, 1],
[1, 1, 1, 1],
[1, 1, 1, 1]])
|
|
array([[1., 0., 0., 0., 0.],
[0., 1., 0., 0., 0.],
[0., 0., 1., 0., 0.],
[0., 0., 0., 1., 0.],
[0., 0., 0., 0., 1.]])
|
|
array([[6.17021380e-042, 8.98497795e-067, 8.32380315e-071],
[1.22082702e+165, 3.97948961e-315, 1.89124308e+219]])
|
|
array([[1., 1., 1.],
[1., 1., 1.]])
|
|
array([[0., 0., 0.],
[0., 0., 0.]])
|
|
array([[5.97915591e-305, 6.01020264e-305, 5.98054658e-305],
[5.98037274e-305, 5.99198485e-305, 5.98252833e-305],
[5.96785670e-305, 2.15228723e-280, 5.98586589e-305]])
|
|
array([[1., 0., 0., 0.],
[0., 1., 0., 0.],
[0., 0., 1., 0.],
[0., 0., 0., 1.]])
eye identity 都可以创建单位矩阵,除了参数不同之外,二者有何区别?
|
|
array([[0.99217117, 0.26712817, 0.27010174],
[0.30047328, 0.46375106, 0.37945124]])
索引 和切片
数组的索引是从 0 开始的,二维数组的索引如下图:
数组切片是原始数组的视图,也就是说对切片的所有操作都是会影响原数组,视图数据并不是原始数据的拷贝,如果要得到切片的副本,需要显示地进行复制,如 a[2:3].copy()
|
|
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
|
|
5
|
|
5
|
|
|
|
[[8 9]]
(1, 2)
|
|
[8 9]
(2,)
结果还是有点不同,索引后的数组不小心的话会出现降维的情况
在 MATLAB 中叫增量运算符,这里有点类似
- 再看看花式索引(用整数数组进行索引)
和切片不同,它是复制数据到新数组
|
|
[[ 0 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]]
|
|
array([0, 1, 2])
|
|
array([1, 5, 9])
|
|
array([ 4, 21, 31, 13])
|
|
array([[ 4, 9, 7],
[20, 22, 23],
[28, 30, 31]])
- 还可以使用 np.ix 函数生成索引器
|
|
array([[ 4, 9, 7],
[20, 22, 23],
[28, 30, 31]])
|
|
array([[ 0, 16, 2, 6],
[ 4, 17, 9, 7],
[ 8, 27, 13, 11],
[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23],
[24, 25, 26, 27],
[28, 29, 30, 31]])
|
|
array([[ 0, 19, 2, 6],
[ 4, 20, 9, 7],
[ 8, 30, 13, 11],
[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23],
[24, 25, 26, 27],
[28, 29, 30, 31]])
|
|
array([[ 0, 22, 2, 6],
[ 4, 20, 12, 7],
[ 8, 33, 13, 11],
[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23],
[24, 25, 26, 27],
[28, 29, 30, 31]])
|
|
array([[ 0, 22, 2, 9],
[ 4, 20, 12, 7],
[ 8, 36, 16, 11],
[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23],
[24, 25, 26, 27],
[28, 29, 30, 31]])
- 再来看看布尔型索引
|
|
array([[False, True, False, False],
[False, True, True, False],
[False, True, True, True],
[ True, True, True, True],
[ True, True, True, True],
[ True, True, True, True],
[ True, True, True, True],
[ True, True, True, True]])
|
|
array([22, 20, 12, 36, 16, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25, 26, 27, 28, 29, 30, 31])
|
|
array([22, 20, 12, 36, 16, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25, 26, 27, 28, 29, 30, 31])
ndarray 的数据类型
可以将整个数组理解成是一整块内存,而 dtype 说明了这块内存的数据类型是什么。
在考虑需要控制数据在内存或磁盘中的存储方式时,了解 dtype 就有必要了
|
|
dtype(‘float64’)
|
|
dtype(‘int32’)
|
|
array([1, 0], dtype=int64)
|
|
array([1, 0], dtype=int64)
- 还可以用 astype 函数转换数据类型
|
|
array([1, 0], dtype=int64)
运算
标量运算
大小相等的数组之间的算术运算,都是元素之间对应相加减乘除,运算单位是数组,批量运算。这点和 MATLAB 也很相似。
- 加减乘除
|
|
array([[ 8, 10, 12],
[14, 16, 6]])
|
|
array([[ 8, 10, 12],
[14, 16, 6]])
|
|
array([[-6, -6, -6],
[-6, -6, 6]])
|
|
array([[-6, -6, -6],
[-6, -6, 6]])
|
|
array([[ 7, 16, 27],
[40, 55, 0]])
|
|
array([[ 7, 16, 27],
[40, 55, 0]])
|
|
i:\python364\lib\site-packages\ipykernel_launcher.py:1: RuntimeWarning: divide by zero encountered in true_divide
“““Entry point for launching an IPython kernel.
array([[0.14285714, 0.25 , 0.33333333],
[0.4 , 0.45454545, inf]])
|
|
i:\python364\lib\site-packages\ipykernel_launcher.py:1: RuntimeWarning: divide by zero encountered in true_divide
“““Entry point for launching an IPython kernel.
array([[0.14285714, 0.25 , 0.33333333],
[0.4 , 0.45454545, inf]])
|
|
array([[1. , 0.5 , 0.33333333],
[0.25 , 0.2 , 0.16666667]])
|
|
array([[1. , 1.41421356, 1.73205081],
[2. , 2.23606798, 2.44948974]])
除零会有警告
矩阵运算
|
|
array([[ 32, 35, 42],
[ 68, 80, 102]])
|
|
array([[ 32, 35, 42],
[ 68, 80, 102]])
|
|
[[1 2 3][4 5 6]]
array([[1, 4],
[2, 5],
[3, 6]])
|
|
array([[1, 4],
[2, 5],
[3, 6]])
|
|
array([[14, 32],
[32, 77]])
常用函数
- sqrt()
|
|
array([[1. , 1.41421356, 1.73205081],
[2. , 2.23606798, 2.44948974]])
- power()
|
|
array([[ 1, 8, 27],
[ 64, 125, 216]], dtype=int32)
|
|
array([[1, 2, 3],
[4, 5, 6]])
- sum()
|
|
21
|
|
array([5, 7, 9])
|
|
array([ 6, 15])
|
|
3.5
- mean()
|
|
array([2.5, 3.5, 4.5])
|
|
array([2., 5.])
- uniform()
|
|
0.7807819763980599
|
|
61.458442560252266
|
|
array([[59.88385648, 50.59647127, 60.02660835],
[55.62225737, 54.49158301, 68.14669151]])
- tile
|
|
array([[1, 2, 3],
[4, 5, 6]])
|
|
array([[1, 2, 3, 1, 2, 3, 1, 2, 3],
[4, 5, 6, 4, 5, 6, 4, 5, 6]])
|
|
array([[1, 2, 3],
[4, 5, 6],
[1, 2, 3],
[4, 5, 6],
[1, 2, 3],
[4, 5, 6]])
|
|
array([[1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3],
[4, 5, 6, 4, 5, 6, 4, 5, 6, 4, 5, 6],
[1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3],
[4, 5, 6, 4, 5, 6, 4, 5, 6, 4, 5, 6],
[1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3],
[4, 5, 6, 4, 5, 6, 4, 5, 6, 4, 5, 6]])
- argsort()
|
|
array([[1, 0, 2],
[2, 1, 0]], dtype=int32)
|
|
array([[0, 0, 1],
[1, 1, 0]], dtype=int32)
广播
不同大小数组之间的运算叫广播
|
|
如果要实现 a 的每一行的元素都加上 b,可以这么做:
|
|
array([[ 9, 10, 11], [ 12, 13, 15], [ 16, 63, 96], [ 11, 62, 107]])
|
|
array([[ 25, 26, 27],
[ 28, 29, 31],
[ 32, 79, 112],
[ 27, 78, 123]])
不同维数的数组可以直接操作
这就是 numpy 数组的广播特性