介绍
NumPy 是一个 Python 包。 它代表 “Numeric Python”。 它是一个由多维数组对象和用于处理数组的例程集合组成的库。
numpy手册
NumPy 用户指南
NumPy 参考资料
Scipy 讲座
numpy教程
安装与导入
pip install numpy
conda install numpy
为了跟课程匹配,怕有试验时的版本差异,课程中有要求numpy版本为1.13,
conda install numpy=1.13
使用前需要再py文件中导入库:
import numpy as np
Ndarry对象
NumPy 中定义的最重要的对象是称为 ndarray 的 N 维数组类型。 它描述相同类型的元素集合。 可以使用基于零的索引访问集合中的项目。
ndarray 中的每个元素在内存中使用相同大小的块。 ndarray 中的每个元素是数据类型对象的对象(称为 dtype )。
从 ndarray 对象提取的任何元素(通过切片)由一个数组标量类型的 Python 对象表示。 下图显示了 ndarray ,数据类型对象( dtype )和数组标量类型之间的关系。
ndarray 类的实例可以通过本教程后面描述的不同的数组创建例程来构造。 基本的 ndarray 是使用 NumPy 中的数组函数创建的,如下所示:
numpy.array
numpy.array(object, dtype=None, copy=True, order='K', subok=False, ndmin=0)
上面的构造器接受以下参数:
NumPy - Ndarray 对象
序号 | 参数及描述 |
---|---|
1. | object 一个数组或任何(嵌套)序列。 |
2. | dtype 数组的所需数据类型,可选。 |
3. | copy 可选,默认为 true ,对象是否被复制。 |
4. | order C (按行)、 F (按列)或 A (任意,默认)。 |
5. | subok 默认情况下,返回的数组被强制为基类数组。 如果为 true ,则返回子类。 |
6. | ndimin 指定返回数组的最小维数。 |
Examples
>>> np.array([1, 2, 3])
array([1, 2, 3])
>>> np.array([1, 2, 3.0])
array([ 1., 2., 3.])
>>> np.array([[1, 2], [3, 4]])
array([[1, 2],
[3, 4]])
#最小维度
>>> np.array([1, 2, 3], ndmin=2)
array([[1, 2, 3]])
#设置dtype
>>> np.array([1, 2, 3], dtype=complex)
array([ 1.+0.j, 2.+0.j, 3.+0.j])
#大于号小于号表示大小端存储,小于号是小端存储
>>> x = np.array([(1,2),(3,4)],dtype=[('a','<i4'),('b','<i4')])
>>> x['a']
array([1, 3])
>>> np.array(np.mat('1 2; 3 4'))
array([[1, 2],
[3, 4]])
>>> np.array(np.mat('1 2; 3 4'), subok=True)
matrix([[1, 2],
[3, 4]])
“”“
Numpy matrices必须是2维的,但是 numpy arrays (ndarrays) 可以是多维的(1D,2D,3D····ND). Matrix是Array的一个小的分支,包含于Array。所以matrix 拥有array的所有特性。
在numpy中matrix的主要优势是:相对简单的乘法运算符号。例如,a和b是两个matrices,那么a*b,就是矩阵积。
”“”
NumPy - 数据类型
首先可以学习下自定义数据类型。
arrays的每个项都必须是同一类型的,那么如果输入了不同类型的数据,就会转换成同一类型,类型具体如下:
Numpy- shape,zeros,ones,eye,full,diag,unique
首先来说简单的:
首先引入概念,秩,我们将一维数组称之为秩为 1 的数组。通常,N 维数组的秩为 N。因此,二维数组称为秩为 2 的数组。数组的另一个重要特性是形状。数组的形状是指每个维度的大小。例如,秩为 2 的数组的形状对应于数组的行数和列数。
zeros
用法:zeros(shape, dtype=float, order='C')
返回:返回来一个给定形状和类型的用0填充的数组;
注意np.zeros() 函数默认地创建一个 dtype 为 float64 的数组。
例子:
>>> np.zeros(5)
array([ 0., 0., 0., 0., 0.])
>>> np.zeros((5,), dtype=np.int)
array([0, 0, 0, 0, 0])
>>> np.zeros((2, 1))
array([[ 0.],
[ 0.]])
>>> s = (2,2)
>>> np.zeros(s)
array([[ 0., 0.],
[ 0., 0.]])
>>> np.zeros((2,), dtype=[('x', 'i4'), ('y', 'i4')]) # custom dtype
array([(0, 0), (0, 0)],
dtype=[('x', '<i4'), ('y', '<i4')])
ones
用法:ones(shape, dtype=None, order='C')
返回:返回来一个给定形状和类型的用1填充的数组;
跟zeros其实很像的,区别只是0换成了1而已,注意np.ones() 函数默认地创建一个 dtype 为 float64 的数组。
>>>np.ones(5)
array([ 1., 1., 1., 1., 1.])
>>> np.ones((5,), dtype=np.int)
array([1, 1, 1, 1, 1])
>>> np.ones((2, 1))
array([[ 1.],
[ 1.]])
>>> s = (2,2)
>>> np.ones(s)
array([[ 1., 1.],
[ 1., 1.]])
full
用法:full(shape, fill_value, dtype=None, order='C'):
返回:返回一个给定形状,类型和填充值的数组
# We create a 2 x 3 ndarray full of fives.
X = np.full((2,3), 5)
# We print X
print()
print('X = \n', X)
print()
# We print information about X
print('X has dimensions:', X.shape)
print('X is an object of type:', type(X))
print('The elements in X are of type:', X.dtype)
#输出
X =
[[5 5 5]
[5 5 5]]
X has dimensions: (2, 3)
X is an object of type: class 'numpy.ndarray'
The elements in X are of type: int64
eye
用法:eye(N, M=None, k=0, dtype=<class 'float'>)
N是行,M是列,k是对角线的位置,0的时候是正对角线,+1就是对角线向上移,-1就是对角线向下移
返回:返回一个类似单位矩阵的东西。
>>> np.eye(2, dtype=int)
array([[1, 0],
[0, 1]])
>>> np.eye(3, k=1)
array([[ 0., 1., 0.],
[ 0., 0., 1.],
[ 0., 0., 0.]])
diag
用法:diag(v, k=0)
v : array_like
If v
is a 2-D array, return a copy of its k
-th diagonal.
If v
is a 1-D array, return a 2-D array with v
on the k
-th
diagonal.
k : int, optional
Diagonal in question. The default is 0. Use k>0
for diagonals
above the main diagonal, and k<0
for diagonals below the main
diagonal.
v和k的理解看下面的例子,k和eye里的k作用其实是一样的。
返回:一个对角矩阵。对角矩阵是仅在主对角线上有值的方形矩阵。
np.diag() 函数会创建一个对应于对角矩阵的 ndarray
# Create a 4 x 4 diagonal matrix that contains the numbers 10,20,30, and 50
# on its main diagonal
X = np.diag([10,20,30,50])
# We print X
print()
print('X = \n', X)
print()
#输出:
X =
[[10 0 0 0]
[ 0 20 0 0]
[ 0 0 30 0]
[ 0 0 0 50]]
>>> x = np.arange(9).reshape((3,3))
>>> x
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
>>> np.diag(x)
array([0, 4, 8])
>>> np.diag(x, k=1)
array([1, 5])
>>> np.diag(x, k=-1)
array([3, 7])
>>> np.diag(np.diag(x))
array([[0, 0, 0],
[0, 4, 0],
[0, 0, 8]])
unique
可以理解为返回array的set值
从 ndarray 中提取唯一的元素。我们可以使用 np.unique() 函数查找 ndarray 中的唯一元素。np.unique(ndarray) 函数会返回给定 ndarray 中的 唯一元素
# Create 3 x 3 ndarray with repeated values
X = np.array([[1,2,3],[5,2,8],[1,2,3]])
# We print X
print('X = \n', X)
# We print the unique elements of X
print('The unique elements in X are:',np.unique(X))
#输出:
X =
[[1 2 3]
[5 2 8]
[1 2 3]]
The unique elements in X are: [1 2 3 5 8]
shape
shape函数功能是读取矩阵的长度,比如shape[0]就是读取矩阵第一维度的长度。
shape的输入参数可以是一个整数(表示维度),也可以是一个矩阵。
>>>a = np.array([[2,2,2],[3,3,3]])
>>> print(a)
[[ 2 2 2 ]
[ 3 3 3 ]]
>>> a.shape
(2, 3)
总结:采用np.array()创建时需要几个维度就要用几个[ ]括起来,这种创建方式要给定数据;采用np.ones()或np.zeros()创建分别产生全1或全0的数据,用a.shape会输出你创建时的输入,shape的返回值是一个元组,里面每个数字表示每一维的长度
Numpy- arrange,linspace,reshape/resize,random
arrange
其实跟我们常用的range很像啊
arange([start,] stop[, step,], dtype=None)
其中包含位于半开区间 [start, stop) 内并均匀分布的值。也就是说,均匀分布的数字将包括 start 数字,但是不包括 stop 数字,根据start与stop指定的范围以及step设定的步长,生成一个 ndarray。
step可以不是整数,但是精度上不是很好,所以需要引入linspace
>>> np.arange(3)
array([0, 1, 2])
>>> np.arange(3.0)
array([ 0., 1., 2.])
>>> np.arange(3,7)
array([3, 4, 5, 6])
>>> np.arange(3,7,2)
array([3, 5])
linspace
用法: linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None):
np.linspace(start, stop, N) 函数返回 N 个在闭区间 [start, stop] 内均匀分布的数字。即 start 和 stop 值都包括在内。此外注意,start, stop是必须参数。
endpoint是说是否包含stop的值,默认是包含的。
restep如果是true,返回(samples, step)。
>>> np.linspace(2.0, 3.0, num=5)
array([ 2. , 2.25, 2.5 , 2.75, 3. ])
>>> np.linspace(2.0, 3.0, num=5, endpoint=False)
array([ 2. , 2.2, 2.4, 2.6, 2.8])
>>> np.linspace(2.0, 3.0, num=5, retstep=True)
(array([ 2. , 2.25, 2.5 , 2.75, 3. ]), 0.25)
reshape/resize
用法:reshape(a, newshape, order='C')
resize使用方法也一样
newshape:新形状应与原始形状兼容。 如果是整数,那么结果将是该长度的一维数组。 一个形状尺寸可以是-1。 在这种情况下,该值是从数组长度和剩余维度推断出来的。
-1的用法
reshape和resize区别
- reshape:有返回值,所谓有返回值,即不对原始多维数组进行修改;
- resize:无返回值,所谓有返回值,即会对原始多维数组进行修改;
>>> a = np.arange(6).reshape((3, 2))
>>> a
array([[0, 1],
[2, 3],
[4, 5]])
>>> a = np.array([[1,2,3], [4,5,6]])
#变为一维数组
>>> np.reshape(a, 6)
array([1, 2, 3, 4, 5, 6])
>>> np.reshape(a, 6, order='F')
array([1, 4, 2, 5, 3, 6])
#不知道变成几列,但是行数固定为3行
>>> np.reshape(a, (3,-1)) # the unspecified value is inferred to be 2
array([[1, 2],
[3, 4],
[5, 6]])
>>> np.resize(a,(3,-1))
>>> print(a)
array([[1, 2],
[3, 4],
[5, 6]])
random
-
numpy.random.random() 生成随机浮点数,默认为生成一个随机的浮点数,范围是在0.0~1.0之间,也可以通过参数size设置返回数据的size;
注意是半开区间 [0.0, 1.0) 内的随机浮点数
# We create a 3 x 3 ndarray with random floats in the half-open interval [0.0, 1.0).
X = np.random.random((3,3))
# We print X
print()
print('X = \n', X)
print()
# We print information about X
print('X has dimensions:', X.shape)
print('X is an object of type:', type(X))
print('The elements in x are of type:', X.dtype)
#输出
X =
[[ 0.12379926 0.52943854 0.3443525 ]
[ 0.11169547 0.82123909 0.52864397]
[ 0.58244133 0.21980803 0.69026858]]
X has dimensions: (3, 3)
X is an object of type: class 'numpy.ndarray' The elements in X are of type: float64
- np.random.randint(start, stop, size = shape) 会创建一个具有给定形状的 ndarray,其中包含在半开区间 [start, stop) 内的随机整数。
# We create a 3 x 2 ndarray with random integers in the half-open interval [4, 15).
X = np.random.randint(4,15,size=(3,2))
# We print X
print()
print('X = \n', X)
print()
# We print information about X
print('X has dimensions:', X.shape)
print('X is an object of type:', type(X))
print('The elements in X are of type:', X.dtype)
#输出
X =
[[ 7 11]
[ 9 11]
[ 6 7]]
X has dimensions: (3, 2)
X is an object of type: class 'numpy.ndarray' The elements in X are of type: int64
- np.random.normal(mean, standard deviation, size=shape)会创建一个具有给定形状的 ndarray,其中包含从正态高斯分布(具有给定均值和标准差)中抽样的随机数字。我们来创建一个 1,000 x 1,000 ndarray,其中包含从正态分布(均值为 0,标准差为 0.1)中随机抽样的浮点数。
# We create a 1000 x 1000 ndarray of random floats drawn from normal (Gaussian) distribution
# with a mean of zero and a standard deviation of 0.1.
X = np.random.normal(0, 0.1, size=(1000,1000))
# We print X
print()
print('X = \n', X)
print()
# We print information about X
print('X has dimensions:', X.shape)
print('X is an object of type:', type(X))
print('The elements in X are of type:', X.dtype)
print('The elements in X have a mean of:', X.mean())
print('The maximum value in X is:', X.max())
print('The minimum value in X is:', X.min())
print('X has', (X < 0).sum(), 'negative numbers')
print('X has', (X > 0).sum(), 'positive numbers')
#输出
X =
[[ 0.04218614 0.03247225 -0.02936003 ..., 0.01586796 -0.05599115 -0.03630946]
[ 0.13879995 -0.01583122 -0.16599967 ..., 0.01859617 -0.08241612 0.09684025]
[ 0.14422252 -0.11635985 -0.04550231 ..., -0.09748604 -0.09350044 0.02514799]
...,
[-0.10472516 -0.04643974 0.08856722 ..., -0.02096011 -0.02946155 0.12930844]
[-0.26596955 0.0829783 0.11032549 ..., -0.14492074 -0.00113646 -0.03566034]
[-0.12044482 0.20355356 0.13637195 ..., 0.06047196 -0.04170031 -0.04957684]]
X has dimensions: (1000, 1000)
X is an object of type: class 'numpy.ndarray' The elements in X are of type: float64
The elements in X have a mean of: -0.000121576684405
The maximum value in X is: 0.476673923106
The minimum value in X is: -0.499114224706 X 具有 500562 个负数 X 具有 499438 个正数
ndarray 中的随机数字的平均值接近 0,X 中的最大值和最小值与 0(平均值)保持对称,正数和负数的数量很接近。
-
np.random.permutation()
输入一个数N或者数组,生成一个随机序列(如果是数的话生成的内容是[1, N)),对多维数组来说是多维随机打乱而不是1维
>>np.random.permutation([1, 4, 9, 12, 15])
array([15, 1, 9, 4, 12])
>>arr = np.arange(9).reshape((3, 3))
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
>>np.random.permutation(arr)
array([[6, 7, 8],
[0, 1, 2],
[3, 4, 5]])
>>permutation = list(np.random.permutation(10))
[5, 1, 7, 6, 8, 9, 4, 0, 2, 3]
>>Y = np.array([[1,1,1,1,0,0,0,0,0,0]])
>>Y_new = Y[:, permutation]
array([[0, 1, 0, 0, 0, 0, 0, 1, 1, 1]])
-
np.random.shuffle()
shuffle与permutatio作用相似,他们的区别是:
函数shuffle与permutation都是对原来的数组进行重新洗牌(即随机打乱原来的元素顺序);区别在于shuffle直接在原来的数组上进行操作,改变原来数组的顺序,无返回值。而permutation不直接在原来的数组上进行操作,而是返回一个新的打乱顺序的数组,并不改变原来的数组。
Numpy- 读取,修改,添加,删除,堆叠,切片
读取,修改
array的读取,修改操作和列表非常的类似--通过索引,但是多维的情况和列表会有些区别,列表的话[0][0]来读取第一行第一列的元素,而array是用[0,0]来读取(格式为 [row, column])。
那么修改就是正常的赋值手段 ‘=’ 。
# We create a 3 x 3 rank 2 ndarray that contains integers from 1 to 9
X = np.array([[1,2,3],[4,5,6],[7,8,9]])
# We print X
print()
print('X = \n', X)
print()
# Let's access some elements in X
print('This is (0,0) Element in X:', X[0,0])
print('This is (0,1) Element in X:', X[0,1])
print('This is (2,2) Element in X:', X[2,2])
#输出
X =
[[1 2 3]
[4 5 6]
[7 8 9]]
This is (0,0) Element in X: 1
This is (0,1) Element in X: 2
This is (2,2) Element in X: 9
删除
np.delete(ndarray, elements, axis=None)
此函数会沿着指定的轴从给定 ndarray 中删除给定的元素列表。对于秩为 1 的 ndarray,不需要使用关键字 axis。对于秩为 2 的 ndarray,axis = 0 表示选择行,axis = 1 表示选择列。
# We create a rank 1 ndarray
x = np.array([1, 2, 3, 4, 5])
# We create a rank 2 ndarray
Y = np.array([[1,2,3],[4,5,6],[7,8,9]])
# We print x
print('Original x = ', x)
# We delete the first and last element of x
x = np.delete(x, [0,4])
# We print x with the first and last element deleted
print('Modified x = ', x)
# We print Y
print('Original Y = \n', Y)
# We delete the first row of y
w = np.delete(Y, 0, axis=0)
# We delete the first and last column of y
v = np.delete(Y, [0,2], axis=1)
# We print w
print('w = \n', w)
# We print v
print('v = \n', v)
#输出
Original x = [1 2 3 4 5]
Modified x = [2 3 4]
Original Y =
[[1 2 3]
[4 5 6]
[7 8 9]]
w =
[[4 5 6]
[7 8 9]]
v =
[[2]
[5]
[8]]
添加
np.append(ndarray, elements, axis)
大致上跟列表追加一样。
函数向 ndarray 中附加值。该函数会将给定的元素列表沿着指定的轴附加到 ndarray 中,对于秩为 1 的 ndarray,不需要使用关键字 axis。对于秩为 2 的 ndarray,axis = 0 表示选择行,axis = 1 表示选择列。
# We create a rank 1 ndarray
x = np.array([1, 2, 3, 4, 5])
# We create a rank 2 ndarray
Y = np.array([[1,2,3],[4,5,6]])
# We print x
print('Original x = ', x)
# We append the integer 6 to x
x = np.append(x, 6)
# We print x
print('x = ', x)
# We append the integer 7 and 8 to x
x = np.append(x, [7,8])
# We print x
print('x = ', x)
# We print Y
print('Original Y = \n', Y)
# We append a new row containing 7,8,9 to y
v = np.append(Y, [[7,8,9]], axis=0)
# We append a new column containing 9 and 10 to y
q = np.append(Y,[[9],[10]], axis=1)
# We print v
print('v = \n', v)
# We print q
print('q = \n', q)
Original x = [1 2 3 4 5]
#输出
x = [1 2 3 4 5 6]
x = [1 2 3 4 5 6 7 8]
Original Y =
[[1 2 3]
[4 5 6]]
v =
[[1 2 3]
[4 5 6]
[7 8 9]]
q =
[[ 1 2 3 9]
[ 4 5 6 10]]
np.insert(ndarray, index, elements, axis)
向 ndarray 中插入值。此函数会将给定的元素列表沿着指定的轴插入到 ndarray 中,并放在给定的索引前面。对于秩为 1 的 ndarray,不需要使用关键字 axis。对于秩为 2 的 ndarray,axis = 0 表示选择行,axis = 1 表示选择列。
# We create a rank 1 ndarray
x = np.array([1, 2, 5, 6, 7])
# We create a rank 2 ndarray
Y = np.array([[1,2,3],[7,8,9]])
# We print x
print('Original x = ', x)
# We insert the integer 3 and 4 between 2 and 5 in x.
x = np.insert(x,2,[3,4])
# We print x with the inserted elements
print('x = ', x)
# We print Y
print('Original Y = \n', Y)
# We insert a row between the first and last row of y
w = np.insert(Y,1,[4,5,6],axis=0)
# We insert a column full of 5s between the first and second column of y
v = np.insert(Y,1,5, axis=1)
# We print w
print('w = \n', w)
# We print v
print('v = \n', v)
#输出
Original x = [1 2 5 6 7]
x = [1 2 3 4 5 6 7]
Original Y =
[[1 2 3]
[7 8 9]]
w =
[[1 2 3]
[4 5 6]
[7 8 9]]
v =
[[1 5 2 3]
[7 5 8 9]]
堆叠
Numpy中stack(),hstack(),vstack(),这三个函数有些相似性,都是堆叠数组,里面最难理解的应该就是stack()函数了。
- stack()函数
函数原型为:stack(arrays, axis=0),arrays可以传数组和列表。
import numpy as np
a=[[1,2,3],
[4,5,6]]
print("列表a如下:")
print(a)
print("增加一维,新维度的下标为0")
c=np.stack(a,axis=0)
print(c)
print("增加一维,新维度的下标为1")
c=np.stack(a,axis=1)
print(c)
输出:
列表a如下:
[[1, 2, 3], [4, 5, 6]]
增加一维,新维度下标为0
[[1 2 3]
[4 5 6]]
增加一维,新维度下标为1
[[1 4]
[2 5]
[3 6]]
首先这里arrays我传的是一个列表,现在我开始讲解这个stack()函数的意思,它就是对arrays里面的每个元素(可能是个列表,元组,或者是个numpy的数组)变成numpy的数组后,再对每个元素增加一维(至于维度加在哪里,是靠axis控制的),然后再把这些元素串起来(至于怎么串,我下面会说)。
arrays里面的每个元素必须形状是一样的,例如本例中列表a中的两个元素[1,2,3]和[4,5,6]的形状是一样的,如果把[4,5,6]换成[4,5] ,那么程序会报错!而axis代表的是在哪个维度上加一维,例如axis=0(它是默认的)代表的就是增加的这一维的下标为0,axis等于多少不是随便乱写的,如果参数arrays里面的每个元素是个1维的,那么调用stack()函数增加一维后会变成2维的,所以axis只能等于0和1(维度的下标是从0开始的),而参数axis=0和axis=1得到的结果是不一样的。
例如上面的代码中a列表中的第一个元素为[1,2,3],那么当axis=0的时候,就是在它的中括号外面再加一个中括号,变成[ [1,2,3] ](其实1,2,3之间是没有逗号的,因为stack()函数会先把参数arrays中的每个元素变成numpy的数组,数组之间是没有逗号的,看看上面的代码输出就知道了,这里大家明白就行,我为了方便讲解,下面还会加上逗号),这样最外面那层中括号才代表维度下标为0的那维;当axis=1的时候,就是在里面加个中括号,变成了[ [1],[2],[3] ],这样里面加的那层中括号才代表维度下标为1的那维。同理当axis=0的时候[4,5,6]变成[ [ 4,5,6] ],当axis=1的时候,变成[ [4],[5],[6] ]。下面我们讲如何把增加一维度后的每个元素串起来。
怎么把上面那两个元素增加维度后的结果串起来呢,其实很简单。现在我们已经知道了增加维度无非是增加中括号的意思,至于在哪里加中括号,取决于axis等于几。我们把增加的中括号想像成一个个的箱子。还拿上面的代码来说,当axis=0的时候,我们把套在[1,2,3]外面的中括号(就是[ [1,2,3] ]最外层的那个中括号)看做是箱子A,这个箱子A也会套在[4,5,6]的外面,所以我们就先把[1,2,3]和[4,5,6]放在一起,变成[1,2,3],[4,5,6],然后再一起套上箱子A,变成[ [1,2,3],[4,5,6] ]这就是当axis=0的时候程序的输出结果。
现在再来看当axis=1的时候,对于[1,2,3],我们把套在1外面的箱子(就是上面讲的[ [1],[2],[3] ]中1外面的那层中括号)看做A,套在2外面的看做B,套在3外面的看做C,同理,箱子A也会套在4的外面,箱子B也会套在5的外面,箱子C也会套在6的外面。那么我们就把1和4放一起,2和5放一起,3和6放一起,变成[ 1,4 ,2,5 ,3,6 ]然后把箱子A,B,C分别套在1,4 , 2,5 , 3,6的外面,变成[ [1,4] , [2,5] , [3,6] ]这就是程序中axis=1的时候程序的输出结果。
大家发现了没有,串起来的时候其实就是把arrays中每个元素在相同的位置套箱子的一些小块(这里叫小块这个名词可能不洽当,但是大家明白就行)放在一起后,再套箱子,就是外面套个中括号,这就是堆叠。
再看下面的代码的输出,测试下你理解的没有。
import numpy as np
a=[[1,2,3,4],
[5,6,7,8],
[9,10,11,12]]
print("列表a如下:")
print(a)
print("增加一维,新维度的下标为0")
c=np.stack(a,axis=0)
print(c)
print("增加一维,新维度的下标为1")
c=np.stack(a,axis=1)
print(c)
输出:
列表a如下:
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
增加一维,新维度的下标为0
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
增加一维,新维度的下标为1
[[ 1 5 9]
[ 2 6 10]
[ 3 7 11]
[ 4 8 12]]
不知道和你想象的输出一样不一样,还有另一种情况,先看下面的代码。
import numpy as np
a=[1,2,3,4]
b=[5,6,7,8]
c=[9,10,11,12]
print("a=",a)
print("b=",b)
print("c=",c)
print("增加一维,新维度的下标为0")
d=np.stack((a,b,c),axis=0)
print(d)
print("增加一维,新维度的下标为1")
d=np.stack((a,b,c),axis=1)
print(d)
输出:
('a=', [1, 2, 3, 4])
('b=', [5, 6, 7, 8])
('c=', [9, 10, 11, 12])
增加一维,新维度的下标为0
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
增加一维,新维度的下标为1
[[ 1 5 9]
[ 2 6 10]
[ 3 7 11]
[ 4 8 12]]
你会发现输出结果和上面的代码一样,其实它俩就是一样的。只不过当你对arrays传参的时候,如果你传的参数是类似于(a,b,c)这种,它会把(a,b,c)当做一个元组来看,a,b,c都是元组的每个元素。然后分别对每个元素处理,上面我已经说了,arrays传的参数可以是列表,元组,或者numpy数组。所以传(a,b,c)和传[a,b,c]或者当x=[a,b,c]的时候传x,效果都是一样的。
上面的代码处理的arrays元素都是一维变二维的情况,下面我们看看二维变三维是什么样的。
import numpy as np
a=[[1,2,3],
[4,5,6]]
b=[[1,2,3],
[4,5,6]]
c=[[1,2,3],
[4,5,6]]
print("a=",a)
print("b=",b)
print("c=",c)
print("增加一维,新维度的下标为0")
d=np.stack((a,b,c),axis=0)
print(d)
print("增加一维,新维度的下标为1")
d=np.stack((a,b,c),axis=1)
print(d)
print("增加一维,新维度的下标为2")
d=np.stack((a,b,c),axis=2)
print(d)
输出:
('a=', [[1, 2, 3], [4, 5, 6]])
('b=', [[1, 2, 3], [4, 5, 6]])
('c=', [[1, 2, 3], [4, 5, 6]])
增加一维,新维度的下标为0
[[[1 2 3]
[4 5 6]]
[[1 2 3]
[4 5 6]]
[[1 2 3]
[4 5 6]]]
增加一维,新维度的下标为1
[[[1 2 3]
[1 2 3]
[1 2 3]]
[[4 5 6]
[4 5 6]
[4 5 6]]]
增加一维,新维度的下标为2
[[[1 1 1]
[2 2 2]
[3 3 3]]
[[4 4 4]
[5 5 5]
[6 6 6]]]
当axis=0的时候,列表a,b,c最外面都需要套箱子(就是加中括号),那么我把你们先放一起,变成下面这样
[[1,2,3],[4,5,6]],
[[1,2,3],[4,5,6]],
[[1,2,3],[4,5,6]]
然后在最外面套箱子,变成
[
[[1,2,3],[4,5,6]],
[[1,2,3],[4,5,6]],
[[1,2,3],[4,5,6]]
]
当axis=1的时候,列表a,b,c中的[1,2,3]需要套同样的箱子,列表a,b,c中的[4,5,6]需要套同样的箱子,好,我先把你们放一块变成下面这样
[
[1,2,3],[1,2,3],[1,2,3]
,
[4,5,6],[4,5,6],[4,5,6]
]
然后开始分别在 [1,2,3],[1,2,3],[1,2,3]的外面和[4,5,6],[4,5,6],[4,5,6]的外面套箱子,变成下面这样
[
[[1,2,3],[1,2,3],[1,2,3]]
,
[[4,5,6],[4,5,6],[4,5,6]]
]
当axis=2的时候,列表a,b,c中的1,2,3,4,5,6都需要套箱子,我把你们先放一起变成:
[
[1,1,1 , 2,2,2 , 3,3,3],
[4,4,4 , 5,5,5 , 6,6,6]
]
然后在1,1,1 ………6,6,6的外面分别套箱子变成:
[
[[1,1,1] , [2,2,2] , [3,3,3]],
[[4,4,4] , [5,5,5] , [6,6,6]]
]
关于stack()函数就讲这么多,这也是我全部理解的部分。
- hstack()函数
函数原型:hstack(tup) ,参数tup可以是元组,列表,或者numpy数组,返回结果为numpy的数组。这个是进行水平堆叠,看下面的代码体会它的含义
import numpy as np
a=[1,2,3]
b=[4,5,6]
print(np.hstack((a,b)))
输出:[1 2 3 4 5 6 ]
a=[[1],[2],[3]]
b=[[1],[2],[3]]
c=[[1],[2],[3]]
d=[[1],[2],[3]]
print(np.hstack((a,b,c,d)))
输出:
[[1 1 1 1]
[2 2 2 2]
[3 3 3 3]]
- vstack()函数
函数原型:vstack(tup) ,参数tup可以是元组,列表,或者numpy数组,返回结果为numpy的数组。这个是进行垂直堆叠,看下面的代码体会它的含义
import numpy as np
a=[1,2,3]
b=[4,5,6]
print(np.vstack((a,b)))
输出:
[[1 2 3]
[4 5 6]]
import numpy as np
a=[[1],[2],[3]]
b=[[1],[2],[3]]
c=[[1],[2],[3]]
d=[[1],[2],[3]]
print(np.vstack((a,b,c,d)))
输出:
[[1]
[2]
[3]
[1]
[2]
[3]
[1]
[2]
[3]
[1]
[2]
[3]]
总结,stack可以进行任意堆叠,np.vstack() 函数进行垂直堆叠,或使用 np.hstack() 函数进行水平堆叠。请务必注意,为了堆叠 ndarray,ndarray 的形状必须相符。
切片
其实理解了列表切片,ndarray的切片差不多,切片方式都是在方括号里用冒号 : 分隔起始和结束索引。
start和end同样也是含头不含尾,如果冒号两遍空着的就代表最开头和最结尾。
区别仅仅是注意维度上的切割,这里就不再举例。
另外注意,你切割没有用冒号,而是用一个整数,切片返回一个秩为 1 的 ndarray,而不是秩为 2 的 ndarray(其实列表也是这样的呢,直接索引和切片,得出来的即使是同一个索引的值,出来的效果不同,切片出来的也是列表哦)。举个例子。
# We create a 4 x 5 ndarray that contains integers from 0 to 19
X = np.arange(20).reshape(4, 5)
# We print X
print('X = \n', X)
# We select all the elements in the 3rd row
v = X[2,:]
# We print v
print('v = ', v)
# We select all the elements in the 3rd column
q = X[:,2]
# We print q
print('q = ', q)
# We select all the elements in the 3rd column but return a rank 2 ndarray
R = X[:,2:3]
# We print R
print('R = \n', R)
#输出
X =
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]
[15 16 17 18 19]]
v = [10 11 12 13 14]
q = [ 2 7 12 17]
R =
[[ 2]
[ 7]
[12]
[17]]
注意例子中的区别。
另外注意切片赋值是引用传递,传递的是地址,即,如果改变z的值,x的值也会发生改变,所以如果想切片生成新的array变量,则需要使用到np.copy()函数,特别注意哦
正确使用的方法:
# We create a 4 x 5 ndarray that contains integers from 0 to 19
X = np.arange(20).reshape(4, 5)
# We print X
print('X = \n', X)
# create a copy of the slice using the np.copy() function
Z = np.copy(X[1:4,2:5])
# create a copy of the slice using the copy as a method
W = X[1:4,2:5].copy()
# We change the last element in Z to 555
Z[2,2] = 555
# We change the last element in W to 444
W[2,2] = 444
# We print X
print('X = \n', X)
# We print Z
print('Z = \n', Z)
# We print W
print('W = \n', W)
X =
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]
[15 16 17 18 19]]
X =
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]
[15 16 17 18 19]]
Z =
[[ 7 8 9]
[ 12 13 14]
[ 17 18 555]]
W =
[[ 7 8 9]
[ 12 13 14]
[ 17 18 444]]
布尔型索引
中括号内不再是冒号和start end这种实际指示的行列或下标,而是一个布尔表达式,用来筛选满足条件的项,非常好用。
可以用这种布尔型索引筛选读取值,也可以用来直接赋值。
举例:
# We create a 5 x 5 ndarray that contains integers from 0 to 24
X = np.arange(25).reshape(5, 5)
print('Original X = \n', X)
print('The elements in X that lees than or equal to 7:', X[X <= 7])
X[(X > 10) & (X < 17)] = -1
# We print X
print('X = \n', X)
#输出:
Original X =
[[ 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]]
The elements in X that lees than or equal to 7: [0 1 2 3 4 5 6 7]
X =
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 -1 -1 -1 -1]
[-1 -1 17 18 19]
[20 21 22 23 24]]
集合运算和排序
排序函数 | 说明 |
---|---|
np.sort( ndarray, axis) | 排序,返回副本,axis跟之前用法一样 |
np.unique(ndarray) | 返回ndarray中的元素,排除重复元素之后,并进行排序 |
np.intersect1d( ndarray1, ndarray2) | 返回二者的交集并排序。 |
np.union1d( ndarray1, ndarray2) | 返回二者的并集并排序。 |
np.setdiff1d( ndarray1, ndarray2) | 返回二者的差。 |
np.setxor1d( ndarray1, ndarray2) | 返回二者的对称差 |
课程中有例子,不再举例。想看其他例子,可以看这里。
另外sort的使用有两种,一种作为函数使用,即np.sort(array),这样的array自身是不会变的,只是返回一个排序后的结果,而如果一个array.sort()这样当方法使用的话,会在np原地进行排序。
原地不变:
# We create an unsorted rank 1 ndarray
x = np.random.randint(1,11,size=(10,))
# We print x
print('Original x = ', x)
# We sort x and print the sorted array using sort as a function.
print('Sorted x (out of place):', np.sort(x))
# When we sort out of place the original array remains intact. To see this we print x again
print('x after sorting:', x)
#输出
Original x = [9 6 4 4 9 4 8 4 4 7]
Sorted x (out of place): [4 4 4 4 4 6 7 8 9 9]
x after sorting: [9 6 4 4 9 4 8 4 4 7]
原地变:
# We create an unsorted rank 1 ndarray
x = np.random.randint(1,11,size=(10,))
# We print x
print('Original x = ', x)
# We sort x and print the sorted array using sort as a method.
x.sort()
# When we sort in place the original array is changed to the sorted array. To see this we print x again
print('x after sorting:', x)
#输出
Original x = [9 9 8 1 1 4 3 7 2 8]
x after sorting: [1 1 2 3 4 7 8 8 9 9]
算术运算
首先了解下numpy广播规则
其实就是满足这两个条件
对两个阵进行操作时,NumPy逐元素地比较他们的形状,从后面的维度向前执行。当以下情形出现时,两个维度是兼容的:
1,它们相等
2,其中一个是1
如果这些条件都没有达到,将会抛出错误:frames are not aligned exception,表示两个阵列形状不兼容。结果阵列的尺寸与输入阵列的各维度最大尺寸相同。
举例子:
可以的:
A (2d array): 5 x 4
B (1d array): 1
Result (2d array): 5 x 4
A (2d array): 5 x 4
B (1d array): 4
Result (2d array): 5 x 4
A (3d array): 15 x 3 x 5
B (3d array): 15 x 1 x 5
Result (3d array): 15 x 3 x 5
A (3d array): 15 x 3 x 5
B (2d array): 3 x 5
Result (3d array): 15 x 3 x 5
A (3d array): 15 x 3 x 5
B (2d array): 3 x 1
Result (3d array): 15 x 3 x 5
A (4d array): 8 x 1 x 6 x 1
B (3d array): 7 x 1 x 5
Result (4d array): 8 x 7 x 6 x 5
不可以的:
A (1d array): 3
B (1d array): 4 # trailing dimensions do not match #维度尺寸不兼容
A (2d array): 2 x 1
B (3d array): 8 x 4 x 3 # second from last dimensions mismatched #倒数第二个维度不兼容
-
基本运算(https://www.yiibai.com/numpy/numpy_arithmetic_operations.html)
add() 相加,subtract() 相减,multiply() 相乘 和divide() 相除
以上运算都是array项进行项与项的运算操作
举例:
# We create two rank 1 ndarrays
x = np.array([1,2,3,4])
y = np.array([5.5,6.5,7.5,8.5])
# We print x
print('x = ', x)
# We print y
print('y = ', y)
# We perfrom basic element-wise operations using arithmetic symbols and functions
print('x + y = ', x + y)
print('add(x,y) = ', np.add(x,y))
print('x - y = ', x - y)
print('subtract(x,y) = ', np.subtract(x,y))
print('x * y = ', x * y)
print('multiply(x,y) = ', np.multiply(x,y))
print('x / y = ', x / y)
print('divide(x,y) = ', np.divide(x,y))
#输出
x = [1 2 3 4]
y = [ 5.5 6.5 7.5 8.5]
x + y = [ 6.5 8.5 10.5 12.5]
add(x,y) = [ 6.5 8.5 10.5 12.5]
x - y = [-4.5 -4.5 -4.5 -4.5]
subtract(x,y) = [-4.5 -4.5 -4.5 -4.5]
x * y = [ 5.5 13. 22.5 34. ]
multiply(x,y) = [ 5.5 13. 22.5 34. ]
x / y = [ 0.18181818 0.30769231 0.4 0.47058824]
divide(x,y) = [ 0.18181818 0.30769231 0.4 0.47058824]
-
numpy.reciprocal()
此函数返回参数逐元素的倒数,。 由于 Python 处理整数除法的方式,对于绝对值大于 1 的整数元素,结果始终为 0, 对于整数 0,则发出溢出警告。 -
numpy.power()
此函数将第一个输入数组中的元素作为底数,计算它与第二个输入数组中相应元素的幂。
例如np.power(a,2) -
numpy.mod()
此函数返回输入数组中相应元素的除法余数。 函数numpy.remainder()也产生相同的结果。 -
三角函数 (https://www.yiibai.com/numpy/numpy_mathematical_functions.html)
不同角度的正弦值,可以通过乘 pi/180 转化为弧度
np.sin(anp.pi/180)
数组中角度的余弦值:
np.cos(anp.pi/180)
'数组中角度的正切值:'
np.tan(a*np.pi/180)
arcsin,arccos,和arctan函数返回给定角度的sin,cos和tan的反三角函数。 这些函数的结果可以通过numpy.degrees()函数通过将弧度制转换为角度制来验证。 -
numpy.around()
这个函数返回四舍五入到所需精度的值。 该函数接受以下参数。
numpy.around(a,decimals)
其中:
序号 参数及描述1. a 输入数组2. decimals 要舍入的小数位数。 默认值为0。 如果为负,整数将四舍五入到小数点左侧的位置 -
numpy.floor()
此函数返回不大于输入参数的最大整数。 即标量x 的下限是最大的整数i ,使得i <= x。 注意在Python中,向下取整总是从 0 舍入。 -
numpy.ceil()
ceil()函数返回输入值的上限,即,标量x的上限是最小的整数i ,使得i> = x。 -
统计运算(https://www.yiibai.com/numpy/numpy_statistical_functions.html)
numpy.amin() 和 numpy.amax()
这些函数从给定数组中的元素沿指定轴返回最小值和最大值。
numpy.median()
中值定义为将数据样本的上半部分与下半部分分开的值。 numpy.median()函数的用法如下面的程序所示。
numpy.mean()
算术平均值是沿轴的元素的总和除以元素的数量。 numpy.mean()函数返回数组中元素的算术平均值。 如果提供了轴,则沿其计算。
numpy.average()
加权平均值是由每个分量乘以反映其重要性的因子得到的平均值。 numpy.average()函数根据在另一个数组中给出的各自的权重计算数组中元素的加权平均值。 该函数可以接受一个轴参数。 如果没有指定轴,则数组会被展开。
考虑数组[1,2,3,4]和相应的权重[4,3,2,1],通过将相应元素的乘积相加,并将和除以权重的和,来计算加权平均值。
加权平均值 = (14+23+32+41)/(4+3+2+1)
numpy.std()
标准差是与均值的偏差的平方的平均值的平方根。 标准差公式如下:
std = sqrt(mean((x - x.mean())^2))
如果数组是[1,2,3,4],则其平均值为2.5。 因此,差的平方是[2.25,0.25,0.25,2.25],并且其平均值的平方根除以4,即sqrt(5/4)是1.1180339887498949。
np.var()
方差是偏差的平方的平均值,即mean((x - x.mean())^ 2)。 换句话说,标准差是方差的平方根。 - 线性代数(https://www.yiibai.com/numpy/numpy_linear_algebra.html)
序号 | 函数及描述 |
---|---|
1. | dot 两个数组的点积 |
2. | vdot 两个向量的点积 |
3. | inner 两个数组的内积 |
4. | matmul 两个数组的矩阵积 |
5. | determinant 数组的行列式 |
6. | solve 求解线性矩阵方程 |
7. | inv 寻找矩阵的乘法逆矩阵 |