numpy 数组和矩阵的运算

一、数组运算

对数组做基本的算术运算,将会对整个数组的所有元组进行逐一运算,并将运算结果保存在一个新的数组内,而不会破坏原始的数组。

>>> a = np.array( [20,30,40,50] )
>>> b = np.arange( 4 )
>>> b
array([0, 1, 2, 3])
>>> c = a-b
>>> c
array([20, 29, 38, 47])
>>> b**2
array([0, 1, 4, 9])
>>> 10*np.sin(a)
array([ 9.12945251, -9.88031624,  7.4511316 , -2.62374854])
>>> a<35
array([ True, True, False, False])

考虑一个问题,计算b的平方很好理解,各个元素自己算平方就好了。那么对于a-b这种,如果a和b的形状不一样呢?比如a长度为5,b长度为6:

>>> a = np.arange(5)
>>> b = np.arange(6)
>>> a,b
(array([0, 1, 2, 3, 4]), array([0, 1, 2, 3, 4, 5]))
>>> c=a-b
ValueError                                Traceback (most recent call last)
<ipython-input-27-508c408ffd98> in <module>()
----> 1 c=a-b

ValueError: operands could not be broadcast together with shapes (5,) (6,) 

结果是弹出异常!不能这么操作!

另外,不同于数学中的矩阵乘法,使用星号做乘号时,numpy对数组的每个元素,一一对应的做乘法。如果要进行矩阵的乘法怎么办?使用@或者dot函数!

>>> A = np.array( [[1,1],
...             [0,1]] )
>>> B = np.array( [[2,0],
...             [3,4]] )
>>> A * B                       # 元素间相乘
array([[2, 0],
       [0, 4]])
>>> A @ B                       #矩阵乘法
array([[5, 4],
       [3, 4]])
>>> A.dot(B)                    # 矩阵乘法
array([[5, 4],
       [3, 4]])

numpy除了支持数组之间的四则运算以及比较运算外,还支持数组之间的逻辑运算:

>>> arr1 = np.array([[1, 2], [3, 4]])
>>> arr1
array([[1, 2],
       [3, 4]])
>>> arr2 = np.array([[2, 3], [3, 2]])
>>> arr2
array([[2, 3],
       [3, 2]])
>>> np.all(arr1 > arr2)#相当于and
False
>>> np.any(arr1 > arr2)#相当于or
True

可以看到在numpy的数组运算中,数组之间的比较运算的返回值是一个bool类型的数组,而数组间的逻辑运算的返回值则是一个bool类型的值。

对于+=和 *= 这一类操作符,会修改原始的数组,而不是新建一个:

>>> a = np.ones((2,3), dtype=int)
>>> b = np.random.random((2,3))
>>> a *= 3
>>> a
array([[3, 3, 3],
       [3, 3, 3]])
>>> b += a
>>> b
array([[ 3.417022  ,  3.72032449,  3.00011437],
       [ 3.30233257,  3.14675589,  3.09233859]])
>>> a += b                  # b不会自动地转换为整数类型,所以弹出异常
Traceback (most recent call last):
  ...
TypeError: Cannot cast ufunc add output from dtype('float64') to dtype('int64') with casting rule 'same_kind'

当对两个不同类型的数组进行运算操作时,将根据精度,选择最复杂的作为结果的类型:

>>> a = np.ones(3, dtype=np.int32)
>>> b = np.linspace(0,pi,3)
>>> b.dtype.name
'float64'
>>> c = a+b
>>> c
array([ 1.        ,  2.57079633,  4.14159265])
>>> c.dtype.name
'float64'
>>> d = np.exp(c*1j)
>>> d
array([ 0.54030231+0.84147098j, -0.84147098+0.54030231j,
       -0.54030231-0.84147098j])
>>> d.dtype.name
'complex128'

许多一元操作(例如计算数组中所有元素的总和)都作为ndarray类的方法实现:

>>> a = np.random.random((2,3))
>>> a
array([[ 0.18626021,  0.34556073,  0.39676747],
       [ 0.53881673,  0.41919451,  0.6852195 ]])
>>> a.sum()  # 计算所有元素的总和
2.5718191614547998
>>> a.min() #找出最小值
0.1862602113776709
>>> a.max()  #找出最大值
0.6852195003967595v

默认情况下,这些操作都会应用于整个数组,就好像它是一个数字列表,而不管其形状如何。但是,通过指定轴参数,可以沿数组的指定轴应用操作:

>>> b = np.arange(12).reshape(3,4)
>>> b
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>>
>>> b.sum(axis=0)                            # 对每一列进行求和
array([12, 15, 18, 21])
>>>
>>> b.min(axis=1)                            # 找出每一行的最小值
array([0, 4, 8])
>>>
>>> b.cumsum(axis=1)                         # 对每行进行循环累加
array([[ 0,  1,  3,  6],
       [ 4,  9, 15, 22],
       [ 8, 17, 27, 38]])

可以使用sort方法直接对数组或数组某一维度进行就地排序,这会修改数组本身。

>>> a = np.array([[1,6,2],[6,1,3],[1,5,2]])
>>> b=a
>>> b.sort()
>>> b
array([[1, 2, 6],
       [1, 3, 6],
       [1, 2, 5]])
>>> a
array([[1, 2, 6],
       [1, 3, 6],
       [1, 2, 5]])
>>> a = np.array([[1,6,2],[6,1,3],[1,5,2]])
>>> a
array([[1, 6, 2],
       [6, 1, 3],
       [1, 5, 2]])
>>> a.sort(axis=1)
>>> a
array([[1, 2, 6],
       [1, 3, 6],
       [1, 2, 5]])
>>> a = np.array([[1,6,2],[6,1,3],[1,5,2]])
>>> a.sort(axis=0)
>>> a
array([[1, 1, 2],
       [1, 5, 2],
       [6, 6, 3]])

sort方法可以直接对数组元素进行排序,对于多维数组可以通过axis参数来指定对某个特定轴进行排序。sort方法中,对数值型的数据是直接排序;对于英文数组是通过ASCII码进行排序;对于中文数组是通过Unicode编码进行排序。在sort方法里,默认是使用快排进行排序。

也可以使用argsort方法进行间接排序,该方法不会改变原数组里元素的顺序,它的返回值是排序后的元素在原数组中的下标索引组成的数组。

>>> arr = np.array([4, 2, 5, 3, 6, 1, 9, 7, 0, 8])
>>> arr
array([4, 2, 5, 3, 6, 1, 9, 7, 0, 8])
>>> arr.argsort()
array([8, 5, 1, 3, 0, 2, 4, 7, 9, 6], dtype=int64)
>>> arr
array([4, 2, 5, 3, 6, 1, 9, 7, 0, 8])

二、矩阵运算

numpy中不仅仅提供了对于数组的运算方法,也提供了对于矩阵类型的运算(例如四则运算、转置、求逆等)。

矩阵的四则运算:

>>> m1=np.mat([[1,2],[5,6]])
>>> m1
matrix([[1, 2],
        [5, 6]])
>>> m2=np.asmatrix([[2,3],[3,4]])
>>> m2
matrix([[2, 3],
        [3, 4]])
#矩阵的加法
>>> m1+m2 
matrix([[ 3,  5],
        [ 8, 10]])
#矩阵的减法
>>> m1-m2
matrix([[-1, -1],
        [ 2,  2]])
#矩阵与数相乘
>>> m1*3
matrix([[ 3,  6],
        [15, 18]])
#矩阵的乘法
>>> m1*m2
matrix([[ 8, 11],
        [28, 39]])
>>> np.matmul(m1,m2)
matrix([[ 8, 11],
        [28, 39]])
>>> np.dot(m1,m2)
matrix([[ 8, 11],
        [28, 39]])
#矩阵的对应位置元素相乘--要满足同型矩阵
>>> np.multiply(m1,m2)
matrix([[ 2,  6],
        [15, 24]])

矩阵的转置:

>>> m1.T
matrix([[1, 5],
        [2, 6]])

矩阵的逆矩阵:

>>> m1.I
matrix([[-1.5 ,  0.5 ],
        [ 1.25, -0.25]])

矩阵的共轭转置:

>>> m1.H
matrix([[1, 5],
        [2, 6]])

矩阵的视图:

>>> m1.A
array([[1, 2],
       [5, 6]])
>>> type(m1.A)
<class 'numpy.ndarray'>

可以看到矩阵通过视图转化为了数组类型,所以我们可以通过np.mat方法将ndarray转化为矩阵,通过矩阵.A方法转回ndarray类型数据。

posted @ 2020-04-01 09:59  如心幻雨  阅读(597)  评论(0编辑  收藏  举报