numpy与线性代数

本文介绍了NumPy库中的数组操作,包括排序函数如numpy.sort(),numpy.argsort(),和numpy.lexsort(),以及搜索功能如numpy.nonzero(),numpy.where(),和numpy.extract()。同时涵盖了副本和视图的区别,以及numpy.matlib模块和线性代数函数如numpy.dot()的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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]]
"""

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值