• Numpy数组中的运算与拼接,看这篇就够了


    上一篇数据分析的文章我们介绍了Numpy的索引和切片,用于获取Numpy数组的元素。我们也提到Numpy中ndarray对象是类似列表的,但是也有区别比如:

    • 数组对象内的元素类型必须相同

    • 数组大小不可修改

    列表可以使用的符号有:+ 、* 、in,那在ndarray中能使用的有哪些?

    本篇文章主要介绍Numpy数组的一些运算和拼接内容。

    广播机制

    在Numpy中当数组进行运算时,如果两个数组的形状相同,那么两个数组相加就是两个数组的对应位相加,这是要求维数相加,并且各维度的长度相同。比如:

    1. import numpy as np
    2. data1 = np.arange(9,dtype=np.int32).reshape(3,3)  # 维数是(3,3)
    3. data2 = np.ones((3,3),dtype=np.int32)  # 维数是(3,3)
    4. # 两个相加
    5. print(data1+data2)

    原来两个数是:

    1. [[0 1 2]
    2.  [3 4 5]
    3.  [6 7 8]]
    4. [[1 1 1]
    5.  [1 1 1]
    6.  [1 1 1]]

    相加之后的结果:

    1. [[123],
    2.  [456],
    3.  [789]]

    当运算中两个数组的形状不同使时,numpy将会自动触发广播机制,那什么是广播机制呢?

    复习下数学知识😂,在线性代数中我们曾经学到过如下规则:

    a1 =3 ,a2 = 4,a1,a2是0维张量,即标量;

     b1,b2是1维张量,即向量;

    c1,c2是如下所示的2维张量,即矩阵:

    a1与a2之间可以进行加减乘除,b1与b2可以进行逐元素的加减乘除运算,c1与c2之间可以进行逐元素的加减乘除以及矩阵相乘运算(矩阵相乘必须满足维度的对应关系),而a与b,或者b与c之间不能进行逐元素的加减乘除运算,原因是他们的维度不匹配。而这种在数学方面的不可能在NumPy中,就可以通过广播完成这项操作。 

    再比如:

    1. import numpy as np
    2. data1 = np.arange(9,dtype=np.int32).reshape(3,3)  # 维数是(3,3)
    3. print(data1+1)

    此时data1是3行3列的矩阵,跟一个1进行运算,能否成功呢?在Numpy中这时ok的,data1中的每个元素都会跟1相加而得到一个新的矩阵,这就是广播机制。

    所以结果就是:

    1. [[1 2 3]
    2.  [4 5 6]
    3.  [7 8 9]]

    如果是跟一个3行1列的进行加法呢?

    1. import numpy as np
    2. data1 = np.arange(9,dtype=np.int32).reshape(3,3)  # 维数是(3,3)
    3. data2 = np.array([[1],[2],[3]])
    4. print(data1+data2)

    这个操作也是ok的,结果是:

    1. [[ 1  2  3]
    2.  [ 5  6  7]
    3.  [ 9 10 11]]

    如果是跟一个2行3列的数据进行加法运算呢?

    1. import numpy as np
    2. data1 = np.arange(9,dtype=np.int32).reshape(3,3)  # 维数是(3,3)
    3. data2 = np.array([[1,2,3],[1,1,1]])
    4. print(data1+data2)

    此时会报错:

    1. ---------------------------------------------------------------------------
    2. ValueError                                Traceback (most recent call last)
    3. <ipython-input-13-f381f9bc5a62> in <module>
    4. ----> 1 print(data1+data2)
    5. ValueError: operands could not be broadcast together with shapes (3,3) (2,3)

    报错的原因是什么呢?我们一起来看一张图

    所以广播的规则是:

    1. 形状相同的广播

    1.  import numpy as np
    2.  
    3.  data1 = np.arange(9,dtype=np.int32).reshape(3,3)
    4.  print(data1+data1)
    1. 相同维度,但其中某一个或多个维度长度为 1 的广播:

    1.  import numpy as np
    2.  
    3.  data1 = np.arange(9,dtype=np.int32).reshape(3,3)  # 维数是(3,3)
    4.  data2 = np.array([[1],[2],[3]])
    5.  print(data1+data2)
    6.  
    7.  data2 = data2.T
    8.  print(data1+data2)
    1. 如果是标量的话,会广播整个数组上

    1.  import numpy as np
    2.  
    3.  data1 = np.arange(9,dtype=np.int32).reshape(3,3)  # 维数是(3,3)
    4.  print(data1+5)

    所以我们要首先了解numpy的广播机制,接下来才能更好的进行数组的运算。

    numpy数组的运算

    加法

    其实上面我们已经使用了数组的加法运算,而在运算中是使用广播机制的。假设我们现在有这样的两组数据:

    1. import numpy as np
    2. data1 = np.arange(12,dtype=np.int32).reshape(3,4)  # 维数是(3,3)
    3. data2 = np.ones((3,1))
    4. print(data1+data2)

    结果:

    1. [[ 1  2  3  4]
    2.  [ 5  6  7  8]
    3.  [ 9 10 11 12]]

    减法

    print(data1-data2)
    

    结果:

    1. [[-1  0  1  2]
    2.  [ 3  4  5  6]
    3.  [ 7  8  9 10]]

    乘法

    print(data1*data2)
    

    结果:

    1. [[ 0  1  2  3]
    2.  [ 4  5  6  7]
    3.  [ 8  9 10 11]]

    除法

    print(data1/data2)
    

    结果:

    1. [[ 0.  1.  2.  3.]
    2.  [ 4.  5.  6.  7.]
    3.  [ 8.  91011.]]

    当然还有整除和幂运算

    1. data2 = np.array([2,2,2,2])
    2. print(data1//data2)

    结果:

    1. [[0 0 1 1]
    2.  [2 2 3 3]
    3.  [4 4 5 5]]

    如果是幂运算呢?

    print(data1**data2)
    

    结果:

    1. [[  0   1   4   9]
    2.  [ 16  25  36  49]
    3.  [ 64  81 100 121]]

    当然数组也可以进行比较,也是会自动应用广播机制

    1. import numpy as np
    2. arr1=np.array([[1,2,3],[4,5,6]])
    3. arr2=np.array([[1,1,1],[1,1,1]])
    4. print(arr2>arr1)

    结果:

    1. [[FalseFalseFalse],
    2.  [FalseFalseFalse]]

    拼接

    Numpy中提供了concatenate,append, stack类(包括hsatck、vstack、dstack、row_stack、column_stack),r_和c_等类和函数用于数组拼接的操作。

    各种函数的特点和区别如下表:

    在我们学习拼接之前我们先了解一些轴和维度。

    上一篇我们提到numpy中的ndim和shape来分别查看维度,以及在对应维度上的长度的。而其中的axis表示的是轴

    concatenate函数

    1. concatenate(tuple, axis=0, out=None)
    2. """
    3. 参数说明:
    4. tuple:对需要合并的数组用元组的形式给出
    5. axis: 沿指定的轴进行拼接,默认0,即第一个轴
    6. """

    比如我们有两个数组:

     

    所以是对两个数组进行了axis=0轴的合并,如果将axis换成1则变成:

    append函数

    函数的说明如下:

    1. append(arr, values, axis=None)
    2. """
    3. 参数说明:
    4. arr:类似array的数据
    5. values: 类似array的数据
    6. axis:进行append操作的axis的方向,默认无
    7. """

    代码示例:

     

    大家发现,若axis为None,则先将arr和values进行ravel扁平化,再拼接;如果指定axis=0表示x轴的拼接,而如果axis=1表示y轴的拼接。

    stack函数

    函数的说明如下:

    1. stack(arrays, axis=0, out=None)
    2. """
    3. 沿着指定的axis对arrays(每个array的shape必须一样)进行拼接,返回值的维度比原arrays的维度高1
    4. axis:默认为0,即第一个轴,若为-1即为第二个轴
    5. """

    代码演示:(仍然使用上面的data1和data2)

    可以发现如果axis=1,就是x轴的依次进行组合,如果是axis=-1就是两个数组的列进行组合。当然如果想直接进行行或者列的拼接也可以使用:hstack、vstack分别表示只进行行的拼接,或者列的拼接,类似上面的axis=1或axis=-1的情况。

    总结:

    增加行(对行进行拼接)的方法有

    1. np.concatenate((ar1, ar2),axis=0)
    2. np.append(ar1, ar2, axis=0)
    3. np.vstack((ar1,ar2))

    增加列(对列进行拼接)的方法有:

    1. np.concatenate((ar1, ar2),axis=1)
    2. np.append(ar1, ar2, axis=1)
    3. np.hstack((ar1,ar2))

    内容比较多,大家要多多练习哦!

    -END-

    扫码添加请备注:python,进群与宋老师面对面交流:517745409

     

  • 相关阅读:
    Node.js 20 —— 几个令人大开眼界的特性
    perl删除目录下过期的文件
    计算机毕业设计SSM电子投票系统【附源码数据库】
    帆软FineReport本地部署springboot
    Ubuntu20.04.4 LTS正确安装方案及问题解决
    前端页面基础HTML、CSS、JS学习Day01
    日程安排小程序实战教程(上篇)
    OpenLayer系列——【一】初识OpenLayer与OpenLayer视图操作
    投资有风险,入市需谨慎
    Java(七)——集合框架---Set集合
  • 原文地址:https://blog.csdn.net/qiqi1220/article/details/126646625