ndarray的矩阵操作
1. 基本矩阵操作
- 算术运算符:
- 加减乘除
# ndarray和单个数字的运算
# 每个元素分别和这个数字运算
n = np.random.randint(0, 10, size=(2, 3))
n
"""
array([[0, 2, 8],
[4, 0, 5]])
"""
# ndarray和ndarray的运算: 对应位置的元素进行运算.
n + 1
"""
array([[1, 3, 9],
[5, 1, 6]])
"""
n3 = np.random.randint(0, 10, size=(2, 3))
n4 = np.random.randint(0, 10, size=(2, 3))
display(n3, n4)
"""
array([[8, 6, 4],
[4, 8, 4]])
array([[7, 3, 3],
[0, 5, 4]])
"""
n3 + n4
"""
array([[14, 9, 3],
[ 6, 8, 8]])
"""
注意:如果shape不相同, 就不能运算.
- 矩阵积np.dot()
np.dot(A,B): 矩阵的积, 点乘. A . B
# 第一个矩阵的每一行和第二个矩阵的每一列元素分别相乘再相加.
# 要求, 第一个矩阵的列数和第二个矩阵的行数必须相同才可以运算.
n1 = np.random.randint(0, 10, size=(2, 3))
n2 = np.random.randint(0, 10, size=(3, 2))
display(n1, n2)
"""
array([[6, 4, 7],
[6, 2, 1]])
array([[7, 0],
[2, 6],
[7, 0]])
"""
np.dot(n1, n2) # n1 @ n2 同样的效果
"""
array([[99, 24], # n1[0][] * n2[][0]; n1[0][] * n2[][1]
[53, 12]]) # n1[1][] * n2[][0]; n1[1][] * n2[][1]
"""
2. 广播机制
【重要】ndarray广播机制的两条规则
- 规则一:为缺失的维度补1
- 规则二:假定缺失元素用已有值填充
例1:
m = np.ones((2, 3)); a = np.arange(3); 求m+a
m = np.ones((2, 3))
m
"""
array([[1., 1., 1.],
[1., 1., 1.]])
"""
a = np.arange(3)
a # array([0, 1, 2])
m + a
"""
array([[1., 2., 3.],
[1., 2., 3.]])
这里由于a[0, 1, 2] shape:(1,3) 计算时候会自动加个维度,
缺数据, 用已有的数据填充 --> [[0, 1, 2], [0, 1, 2]]
"""
例2:
a = np.arange(3).reshape((3, 1))
b = np.arange(3)
求a+b
a = np.arange(3).reshape((3, 1))
a
"""
array([[0],
[1],
[2]])
"""
b = np.arange(3)
b # array([0, 1, 2])
a + b
"""
array([[0, 1, 2],
[1, 2, 3],
[2, 3, 4]])
"""
注意: 若是A 和B ndarry在行和列维度均不一致,是无法进行广播机制
n1 = np.random.randint(0, 10, size=(2, 3))
n2 = np.random.randint(0, 10, size=(5))
display(n1, n2)
"""
array([[8, 6, 5],
[2, 7, 4]])
array([8, 5, 8, 4, 9])
"""
n1+n2
"""
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
~\AppData\Local\Temp\ipykernel_6908\1842054168.py in <module>
8 array([8, 5, 8, 4, 9])
9 """
---> 10 n1+n2
ValueError: operands could not be broadcast together with shapes (2,3) (5,)
"""
ndarray的排序
1. 快速排序
np.sort()与ndarray.sort()区别:
- np.sort() 是 NumPy 中的函数,它返回数组的排序副本,而不会修改原始数组。
- ndarray.sort() 会修改数组本身内容,而不返回任何内容
n = np.array([6, 1, 2, 5, 4, 3])
np.sort(n) # array([1, 2, 3, 4, 5, 6]); 返回拷贝n,并经过排序的副本
n # array([6, 1, 2, 5, 4, 3]); 原始数组不变
n.sort() # 修改了原始数组,并且没有输出
n # array([1, 2, 3, 4, 5, 6]); 原始数组已经被改变
2. 分区(部分排序)
np.partition
partition: 翻译为分区; 也是一种部分排序,它将数组中的元素重新排列,使得分区索引左侧的元素都小于分区索引处的元素,而分区索引右侧的元素都大于或等于分区索引处的元素
arr = np.array([4, 3, 5, 1, 6, 2, 3])
# 对数组进行分区,使得分区索引为2的元素处于正确的位置
p_arr = np.partition(arr, 2)
p_arr # array([1, 2, 3, 4, 6, 5, 3]);
partition各个参数了解
`numpy.partition(a, kth, axis=-1, kind=‘introselect’, order=None)
a:要分区的数组。
kth:分区的索引或索引数组。在结果中,所有小于分区索引的元素都将出现在索引的左侧,而所有大于或等于分区索引的元素都将出现在右侧。
axis:指定沿着哪个轴进行分区,默认为最后一个轴。
kind:指定使用的算法类型: 'introselect’(默认值):这是一种结合了快速选择(quickselect)和堆排序(heapsort)的算法。它在大多数情况下表现良好,并且是默认的选择。
'quicksort’:使用快速排序算法。快速排序是一种常用的排序算法,通常在大多数情况下表现良好,但在最坏情况下的时间复杂度为
O(n^2)。'heapsort’:使用堆排序算法。堆排序是一种稳定的排序算法,它的时间复杂度为 O(n log
n),但相对于快速排序,它在实践中可能会稍慢。order:指定排序的顺序: None:默认值。如果 order 参数设置为 None,则表示不进行排序,仅对数组进行分区操作。
'C’:按行(逐行)排序。在多维数组中,按行排序意味着沿着每行的方向对元素进行排序。
'F’:按列(逐列)排序。在多维数组中,按列排序意味着沿着每列的方向对元素进行排序。