1 排序和搜索
1.1 数组排序
1.1 .1 numpy.sort()
-
对输入数组执行排序,并返回一个数组副本
numpy.sort(a, axis, kind, order) # a:要排序的数组; # axis:沿着指定轴进行排序 # kind:默认为 quicksort(快速排序); # order:若数组设置了字段,则 order 表示要排序的字段。
arr_num = np.array([[3, 7], [9, 1]])
print(f'原数组是:\n{arr_num}')
# 调用sort()函数
print("默认排序为:\n", np.sort(arr_num))
print(f"列排序:\n{np.sort(arr_num, axis=0)}")
print(f"行排序:\n{np.sort(arr_num, axis=1)}")
# 设置在sort函数中排序字段
dt = np.dtype([('name', 'S10'), ('age', int)])
arr_num = np.array([("ava", 21), ("lisa", 25), ("peter", 17), ("alice", 27)], dtype=dt)
print(arr_num)
print(np.sort(arr_num, order='name'))
代码的运行结果为:
原数组是:
[[3 7]
[9 1]]
默认排序为:
[[3 7]
[1 9]]
列排序:
[[3 1]
[9 7]]
行排序:
[[3 7]
[1 9]]
[(b'ava', 21) (b'lisa', 25) (b'peter', 17) (b'alice', 27)]
[(b'alice', 27) (b'ava', 21) (b'lisa', 25) (b'peter', 17)]
-
同样的在二维数组中,我们设置坐标轴,默认0为垂直方向,1为水平方向进行排序。
1.1.2 numpy.argsort()
-
沿着指定的轴,对输入数组的元素值进行排序,并返回排序后的元素索引数组
arr_num = np.array([90, 29, 89, 12])
print(f"原数组:{arr_num}")
sort_ind = np.argsort(arr_num)
print(f"打印排序元素索引值{sort_ind}")
sort_arr = arr_num[sort_ind]
print(f"打印排序元素:{sort_arr}")
代码的运行结果为:
原数组:[90 29 89 12]
打印排序元素索引值[3 1 2 0]
打印排序元素:[12 29 89 90]
1.1.3 numpy.lexsort()
-
按键序列对数组进行排序,它返回一个已排序的索引数组
arr_one = np.array(['a', 'c', 'b', 'd', 'e'])
arr_two = np.array([12, 90, 38, 18, 21])
arr_ind = np.lexsort((arr_two, arr_one))
arr_ind_two = np.lexsort((arr_one, arr_two))
# 打印排序元素的索引数组
print("arr_ind为:\n", arr_ind)
print("arr_ind_two为:\n", arr_ind_two)
# 使用索引数组对数组进行排序
for data in arr_ind:
print(arr_one[data], arr_two[data])
代码的运行结果为:
arr_ind为:
[0 2 1 3 4]
arr_ind_two为:
[0 3 4 2 1]
a 12
b 38
c 90
d 18
e 21
- 这里对这个方法的注意点就是,在使用lexsort方法时,一定是以数组的形式传入两个数组,并且,这里会按照后面的一个数组来返回我们排序的索引值结果。
1.2 数组搜索
1.2.1 numpy.nonzero()
-
该函数从数组中查找非零元素的索引位置
arr_num = np.array([12, 90, 0, 18, 21])
print("原数组arr_num", arr_num)
print(f"打印非0元素的索引位置:\n{arr_num.nonzero()}")
代码的运行结果为:
原数组arr_num [12 90 0 18 21]
打印非0元素的索引位置:
(array([0, 1, 3, 4], dtype=int64),)
1.2.2 numpy.where()
-
numpy.where() 的返回值是满足了给定条件的元素索引值。
arr_num = np.array([12, 90, 38, 18, 21])
print(np.where(arr_num > 12))
arr_two = np.array([[24, 14, 22], [12, 23, 18]])
print("arr_two为:\n", arr_two)
print(np.where(arr_two > 12))
代码的运行结果为:
(array([1, 2, 3, 4], dtype=int64),)
arr_two为:
[[24 14 22]
[12 23 18]]
(array([0, 0, 0, 1, 1], dtype=int64), array([0, 1, 2, 1, 2], dtype=int64))
-
这里有一个注意点是,在看返回的元素索引值时,一定要前后两个列表一起看。比如在arr_two中元素大于12,其中24是一个元素,他的索引值(0,0),14为(0,1)就分别从前一个列表选一个,从后一个列表选一个元素,组成其索引值。
1.2.3 numpy.extract()
-
该函数的返回值是满足了给定条件的元素值
arr_one = np.arange(9.).reshape(3, 3)
# 打印数组x:'
print(arr_one)
# 设置条件选择偶数元素
condition = np.mod(arr_one, 2) == 0
# 输出布尔值数组
print(condition)
# 按condition提取满足条件的元素值
print(np.extract(condition, arr_one))
代码的运行结果为:
[[0. 1. 2.]
[3. 4. 5.]
[6. 7. 8.]]
[[ True False True]
[False True False]
[ True False True]]
[0. 2. 4. 6. 8.]
1.2.4 numpy.argmax()
-
该函数返回最大值的的索引,与其相反的函数是 argmin() 求最小值索引
arr_num = np.array([[30, 40, 70], [80, 20, 10], [50, 90, 60]])
# a数组
print(f"原数组:\n{arr_num}")
print(f"最大索引:{np.argmax(arr_num)}")
# 将数组以一维展开
print(f"展开一维数组:{arr_num.flatten()}")
# 沿轴0的最大值索引:
max_index_y = np.argmax(arr_num, axis=0)
print(max_index_y)
# 沿轴1的最大值索引
max_index_x = np.argmax(arr_num, axis=1)
print(max_index_x)
代码的运行结果为:
原数组:
[[30 40 70]
[80 20 10]
[50 90 60]]
最大索引:7
展开一维数组:[30 40 70 80 20 10 50 90 60]
[1 2 0]
[2 0 1]
2 副本和视图
2.1 副本
从内存角度来说,副本就是对原数组进行深拷贝,新产生的副本与原数组具有不同的存储位置。而视图可理解为对数组的引用,它和原数组有着相同的内存位置。
2.1.1 赋值操作
-
赋值操作是数组引用的一种方法。比如,将 a 数组赋值给变量 b,被赋值后的变量 b 与 a 组具有相同的内存 id
arr_one = np.array([[1, 2, 3, 4], [9, 0, 2, 3], [1, 2, 3, 19]])
print(f"原数组:\n{arr_one}")
arr_two = arr_one
print(f"新数组arr_two:\n{arr_two}")
print(f"数组arr_one的ID:{id(arr_one)}")
print(f"数组arr_two的ID:{id(arr_two)}")
# 对arr_two数组进行修改
arr_two.shape = 4, 3
print(arr_one)
代码的运行结果为:
原数组:
[[ 1 2 3 4]
[ 9 0 2 3]
[ 1 2 3 19]]
新数组arr_two:
[[ 1 2 3 4]
[ 9 0 2 3]
[ 1 2 3 19]]
数组arr_one的ID:2469313613712
数组arr_two的ID:2469313613712
[[ 1 2 3]
[ 4 9 0]
[ 2 3 1]
[ 2 3 19]]
-
这里有一个注意事项就是,这里的赋值类似于,python中的浅拷贝,浅拷贝的特点就是,浅拷贝的后的两个数组的地址都是一样的,更改其中的一个数组,另外一个数组的结果也会发生改变。
2.1.2 ndarray.view()
-
ndarray.view() 返回一个新生成的数组副本,因此对该数组的操作,不会影响到原数组
import numpy as np
arr_one = np.array([[1, 2, 3, 4], [9, 0, 2, 3], [1, 2, 3, 19]])
print(f"原数组:\n{arr_one}")
print(f"数组arr_one的ID:{id(arr_one)}")
arr_two = arr_one.view()
print(f"数组arr_two的ID:{id(arr_two)}")
# 打印arr_two数组
print(f"新数组:\n{arr_two}")
# 改变arr_two数组形状
arr_two.shape = 4, 3
print("原数组arr_one\n", arr_one)
print("新数组arr_two\n", arr_two)
代的运行结果为:
原数组:
[[ 1 2 3 4]
[ 9 0 2 3]
[ 1 2 3 19]]
数组arr_one的ID:1718919157808
数组arr_two的ID:1718922413616
新数组:
[[ 1 2 3 4]
[ 9 0 2 3]
[ 1 2 3 19]]
原数组arr_one
[[ 1 2 3 4]
[ 9 0 2 3]
[ 1 2 3 19]]
新数组arr_two
[[ 1 2 3]
[ 4 9 0]
[ 2 3 1]
[ 2 3 19]]
2.1.3 ndarray.copy()
-
该方法返回原数组的副本,对副本的修改不会影响到原数组
arr_one = np.array([[1, 2, 3, 4], [9, 0, 2, 3], [1, 2, 3, 19]])
print(f"原数组:\n{arr_one}")
print(f"原数组ID:{id(arr_one)}")
arr_two = arr_one.copy()
print("arr_two数组ID:", id(arr_two))
print(f"新数组:\n{arr_two}")
arr_two.shape = 4, 3
print(f"原数组:\n{arr_one}")
print(f"新数组:\n{arr_two}")
代码的运行结果为:
原数组:
[[ 1 2 3 4]
[ 9 0 2 3]
[ 1 2 3 19]]
原数组ID:1795153451824
arr_two数组ID: 1793432341840
新数组:
[[ 1 2 3 4]
[ 9 0 2 3]
[ 1 2 3 19]]
原数组:
[[ 1 2 3 4]
[ 9 0 2 3]
[ 1 2 3 19]]
新数组:
[[ 1 2 3]
[ 4 9 0]
[ 2 3 1]
[ 2 3 19]]
-
从这里看出来,copy的效果和view的效果好像相同,鼠鼠也不知道这两个之间的区别是什么,如果有知道的小伙伴可以告诉我一下哦。
2.2 视图
2.2.1 切片创建视图
-
使用切片可以创建视图数组,若要修改视图的就会影响到原数组
arr_num = np.arange(10)
print(f'数组arr_num:{arr_num}')
# 创建切片修改原数组arr_num
arr_one = arr_num[3:]
print(arr_one)
arr_two = arr_num[3:]
print(arr_two)
arr_one[1] = 123
arr_two[2] = 234
print(arr_num)
代码的运行结果为:
数组arr_num:[0 1 2 3 4 5 6 7 8 9]
[3 4 5 6 7 8 9]
[3 4 5 6 7 8 9]
[ 0 1 2 3 123 234 6 7 8 9]
3 Matrix矩阵库
NumPy 提供了一个 矩阵库模块numpy.matlib
,该模块中的函数返回的是一个 matrix 对象,而非 ndarray 对象。矩阵由 m 行 n 列(m*n)元素排列而成,矩阵中的元素可以是数字、符号或数学公式等。
- 我这里为什么没有写这个相关的代码,是因为这个库,已经被淘汰了。
3.1 matlib.empty()
-
返回一个空矩阵,所以它的创建速度非常快
numpy.matlib.empty(shape, dtype, order) # shape:以元组的形式指定矩阵的形状。 # dtype:表示矩阵的数据类型。 # order:有两种选择,C(行序优先) 或者 F(列序优先)。
3.1.1 numpy.matlib.zeros()
-
创建一个以 0 填充的矩阵
import numpy as np import numpy.matlib # 创建一个2x2的全0矩阵 matrix = np.matlib.zeros((2, 2)) print(matrix)
3.1.2 numpy.matlib.ones()
-
创建一个以 1 填充的矩阵。
import numpy.matlib import numpy as np print(np.matlib.ones((2,2)))
3.1.3 numpy.matlib.eye()
-
返回一个对角线元素为 1,而其他元素为 0 的矩阵 。
import numpy as np # 创建一个3x3的对角线为1的矩阵 matrix = np.matlib.eye(3) print(matrix)
4 线性代数
NumPy 提供了 numpy.linalg 模块,该模块中包含了一些常用的线性代数计算方法
函数名称 | 描述说明 |
---|---|
dot | 两个数组的点积。 |
vdot | 两个向量的点积。 |
inner | 两个数组的内积。 |
matmul | 两个数组的矩阵积。 |
det | 计算输入矩阵的行列式。 |
solve | 求解线性矩阵方程。 |
inv | 计算矩阵的逆矩阵,逆矩阵与原始矩阵相乘,会得到单位矩阵。 |
4.1 numpy.dot()
-
按照矩阵的乘法规则,计算两个矩阵的点积运算结果。当输入一维数组时返回一个结果值,若输入的多维数组则同样返回一个多维数组结果。
-
点积运算就是将arr_one数组的每一行元素与arr_two数组的每一列元素相乘再相加。
arr_one = [1, 2, 3]
arr_two = [4, 5, 6]
print(np.dot(arr_one, arr_two))
代码运行的结果为:
32
-
多维数组
arr_one = np.array([[100, 200], [23, 12]])
arr_two = np.array([[10, 20], [12, 21]])
dot = np.dot(arr_one, arr_two)
print(dot)
代码的运行结果为:
[[3400 6200]
[ 374 712]]
""" 多维数组计算过程如下 [[100*10+200*12,100*20+200*21] [23*10+12*12,23*20+12*21]] """
4.2 numpy.vdot()
-
该函数用于计算两个向量的点积结果,与 dot() 函数不同。
arr_one = np.array([[1, 2, 3, 4]])
print(arr_one)
arr_two = np.array([[5, 6, 7, 8]])
arr_num = np.vdot(arr_one, arr_two)
print(arr_num)
代码的运行结果为:
[[1 2 3 4]]
70
arr_one = np.array([[4, 3], [5, 6]])
arr_two = np.array([[10, 11], [12, 13]])
arr_num = np.vdot(arr_one, arr_two)
print(arr_num)
代码的运行结果为:
211
- 计算方式为 —— 4 * 10 + 3 * 11 + 5 * 12 + 6 * 13
4.3 numpy.inner()
-
inner() 方法用于计算数组之间的内积。当计算的数组是一维数组时,它与 dot() 函数相同,若输入的是多维数组则两者存在不同
arr_one = [[1, 10], [100, 1000]]
arr_two = [[1, 2], [3, 4]]
# inner函数
print(np.inner(arr_one, arr_two))
# dot函数
print(np.dot(arr_one, arr_two))
代码的运行结果为:
[[ 21 43]
[2100 4300]]
[[ 31 42]
[3100 4200]]
""" 多维数组计算过程: [[1*1+2*10 1*3+10*4 ] [100*1+1000*2 100*3+1000*4]] """