• Numpy入门[3]——Numpy数组及其索引


    Numpy入门[3]——Numpy数组及其索引

    参考:

    https://ailearning.apachecn.org/

    使用Jupyter进行练习

    先导入numpy:

    import numpy as np
    
    • 1

    产生数组

    从列表产生数组

    mylist = [0, 1, 2, 3]
    a = np.array(mylist)
    a
    
    
    • 1
    • 2
    • 3
    • 4
    array([0, 1, 2, 3])
    
    • 1

    或者直接将列表传入

    a = np.array([1, 2, 3, 4])
    a
    
    • 1
    • 2
    array([1, 2, 3, 4])
    
    • 1

    数组属性

    查看类型:

    type(a)
    
    • 1
    numpy.ndarray
    
    • 1

    查看数组中的数据类型:

    a.dtype
    
    • 1
    dtype('int32')
    
    • 1

    查看每个元素所占的字节:

    a.itemsize
    
    • 1
    4
    
    • 1

    查看形状,会返回一个元组,每个元素代表这一维的元素数目:

    a.shape
    
    • 1
    (4,)
    
    • 1

    或者使用:

    np.shape(a)
    
    • 1
    (4,)
    
    • 1

    查看元素数目:

    a.size
    
    • 1
    4
    
    • 1
    np.size(a)
    
    • 1
    4
    
    • 1

    查看所有元素所占的空间:

    a.nbytes
    
    • 1
    16
    
    • 1

    但事实上,数组所占的存储空间要比这个数字大,因为要用一个header来保存shape,dtype这样的信息。

    查看数组维数:

    a.ndim
    
    • 1
    1
    
    • 1

    使用fill方法设定初始值

    可以使用fill方法将数组设定为指定值:

    a.fill(-1)
    a
    
    • 1
    • 2
    array([-1, -1, -1, -1])
    
    • 1
    a.fill(-4.8)
    a
    
    • 1
    • 2
    array([-4, -4, -4, -4])
    
    • 1

    与列表不同,数组中要求所有元素的 dtype 是一样的,如果传入参数的类型与数组类型不一样,需要按照已有的类型进行转换。

    索引和切片

    索引第一个元素:

    a=np.array([0, 1, 2, 3])
    a[0]
    
    • 1
    • 2
    0
    
    • 1

    修改第一个元素的值:

    a[0]=520
    a
    
    • 1
    • 2
    array([520,   1,   2,   3])
    
    • 1

    切片,支持负索引:

    a=np.array([11, 12, 13, 14, 15])
    a[1:3]
    
    • 1
    • 2
    array([12, 13])
    
    • 1
    a[1:-2]
    
    • 1
    array([12, 13])
    
    • 1
    a[-4:3]
    
    • 1
    array([12, 13])
    
    • 1

    省略参数:

    a[::2]
    
    • 1
    array([11, 13, 15])
    
    • 1
    a[-2:]
    
    • 1
    array([14, 15])
    
    • 1

    假设我们记录一辆汽车表盘上每天显示的里程数:

    od = np.array([21000, 21180, 21240, 22100, 22400])
    
    • 1

    计算每天的旅程数如下:

    dist = od[1:] - od[:-1]
    dist
    
    • 1
    • 2
    array([180,  60, 860, 300])
    
    • 1

    多维数组及其属性

    array可以用于生成多维数组

    a = np.array([[ 0, 1, 2, 3],
               [10,11,12,13]])
    a
    
    • 1
    • 2
    • 3
    array([[ 0,  1,  2,  3],
           [10, 11, 12, 13]])
    
    • 1
    • 2
    # 查看形状
    a.shape
    
    • 1
    • 2
    (2, 4)
    
    • 1
    # 查看元素个数
    a.size
    
    • 1
    • 2
    8
    
    • 1
    # 查看维数
    a.ndim
    
    • 1
    • 2
    2
    
    • 1

    多维数组索引

    对于二维数组,可以传入两个数字来索引:

    a[1,3]
    
    • 1
    13
    
    • 1

    其中,1是行索引,3是列索引,中间用逗号隔开,事实上,Python会将它们看成一个元组(1,3),然后按照顺序进行对应。

    可以利用索引给它赋值:

    a[1,3]=520
    a
    
    • 1
    • 2
    array([[  0,   1,   2,   3],
           [ 10,  11,  12, 520]])
    
    • 1
    • 2

    可以使用单个索引来索引一整行内容:

    a[1]
    
    • 1
    array([ 10,  11,  12, 520])
    
    • 1

    多维数组切片

    a = np.array([[ 0, 1, 2, 3, 4, 5],
               [10,11,12,13,14,15],
               [20,21,22,23,24,25],
               [30,31,32,33,34,35],
               [40,41,42,43,44,45],
               [50,51,52,53,54,55]])
    a
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    array([[ 0,  1,  2,  3,  4,  5],
           [10, 11, 12, 13, 14, 15],
           [20, 21, 22, 23, 24, 25],
           [30, 31, 32, 33, 34, 35],
           [40, 41, 42, 43, 44, 45],
           [50, 51, 52, 53, 54, 55]])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    得到第一行的第 4 和第 5 两个元素:

    a[0, 3:5]
    
    
    • 1
    • 2
    array([3, 4])
    
    • 1

    得到最后两行的最后两列:

    a[-2:,-2:]
    
    • 1
    array([[44, 45],
           [54, 55]])
    
    • 1
    • 2
    a[4:,4:]
    
    • 1
    array([[44, 45],
           [54, 55]])
    
    • 1
    • 2

    得到第三列:

    a[:,2]
    
    • 1
    array([ 2, 12, 22, 32, 42, 52])
    
    • 1

    取出3,5行的奇数列:

    a[2::2,::2]
    
    • 1
    array([[20, 22, 24],
           [40, 42, 44]])
    
    • 1
    • 2

    切片是引用

    切片在内存中使用的是引用机制。

    a = np.array([0, 1, 2, 3, 4])
    b = a[2:4]
    print(b)
    
    
    • 1
    • 2
    • 3
    • 4
    [2 3]
    
    • 1

    引用机制意味着,Python并没有为 b 分配新的空间来存储它的值,而是让 b 指向了 a 所分配的内存空间,因此,改变 b 会改变 a 的值:

    b[0] = 10
    a
    
    
    • 1
    • 2
    • 3
    array([ 0,  1, 10,  3,  4])
    
    • 1

    而这种现象在列表中并不会出现:

    a = [1,2,3,4,5]
    b = a[2:3]
    b[0] = 13234
    print(a)
    
    • 1
    • 2
    • 3
    • 4
    [1, 2, 3, 4, 5]
    
    • 1

    这样做的好处在于,对于很大的数组,不用大量复制多余的值,节约了空间。

    缺点在于,可能出现改变一个值改变另一个值的情况。

    一个解决方法是使用copy()方法产生一个复制,这个复制会申请新的内存:

    a = np.array([0,1,2,3,4])
    b = a[2:4].copy()
    b[0] = 10
    a
    
    • 1
    • 2
    • 3
    • 4
    array([0, 1, 2, 3, 4])
    
    • 1

    花式索引

    切片只能支持连续或者等间隔的切片操作,要想实现任意位置的操作,需要使用花式索引 fancy slicing

    一维花式索引

    与 range 函数类似,可以使用 arange 函数来产生等差数组。

    a = np.arange(0, 80, 10)
    a
    
    • 1
    • 2
    array([ 0, 10, 20, 30, 40, 50, 60, 70])
    
    • 1

    花式索引需要指定索引位置:

    dict = [1, 2, -1]
    b = a[dict]
    b
    
    • 1
    • 2
    • 3
    array([10, 20, 70])
    
    • 1

    可以使用布尔数组来花式索引:

    mask = np.array([0,1,1,0,0,1,0,0],
                dtype=bool)
    a[mask]
    
    • 1
    • 2
    • 3
    array([10, 20, 50])
    
    • 1

    或者用布尔表达式生成 mask,选出了所有大于0.5的值:

    from numpy.random import rand
    x = rand(10)
    print(x)
    mask = x > 0.5
    print(mask.dtype)
    print(x[mask])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    [0.27839355 0.35630865 0.68024875 0.19407979 0.82448345 0.46120622
     0.83562489 0.98924664 0.7125346  0.27196064]
    bool
    [0.68024875 0.82448345 0.83562489 0.98924664 0.7125346 ]
    
    • 1
    • 2
    • 3
    • 4

    二维花式索引

    a = np.array([[ 0, 1, 2, 3, 4, 5],
               [10,11,12,13,14,15],
               [20,21,22,23,24,25],
               [30,31,32,33,34,35],
               [40,41,42,43,44,45],
               [50,51,52,53,54,55]])
    a
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    array([[ 0,  1,  2,  3,  4,  5],
           [10, 11, 12, 13, 14, 15],
           [20, 21, 22, 23, 24, 25],
           [30, 31, 32, 33, 34, 35],
           [40, 41, 42, 43, 44, 45],
           [50, 51, 52, 53, 54, 55]])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    对于二维花式索引,需要给定 rowcol 的值:

    a[(0,1,2,3,4), (1,2,3,4,5)]
    
    • 1
    array([ 1, 12, 23, 34, 45])
    
    • 1
    # 最后三行的1,3,5列
    a[-3:, [0,2,5]]
    
    • 1
    • 2
    array([[30, 32, 35],
           [40, 42, 45],
           [50, 52, 55]])
    
    • 1
    • 2
    • 3

    也可以使用mask进行索引:

    mask = np.array([1,0,1,0,0,1],
                dtype=bool)
    a[mask, 2]
    
    • 1
    • 2
    • 3
    array([ 2, 22, 52])
    
    • 1

    与切片不同,花式索引返回的是原对象的一个复制而不是引用。

    不完全索引

    y = a[:3]
    y
    
    • 1
    • 2
    array([[ 0,  1,  2,  3,  4,  5],
           [10, 11, 12, 13, 14, 15],
           [20, 21, 22, 23, 24, 25]])
    
    • 1
    • 2
    • 3
    # 使用花式索引取出第2,3,5行:
    condition = np.array([0,1,1,0,1,0],
                     dtype=bool)
    a[condition]
    
    • 1
    • 2
    • 3
    • 4
    array([[10, 11, 12, 13, 14, 15],
           [20, 21, 22, 23, 24, 25],
           [40, 41, 42, 43, 44, 45]])
    
    • 1
    • 2
    • 3

    where语句

    where(array)
    
    • 1

    where函数会返回所有非零元素的索引

    一维数组

    a = np.array([0, 12, 5, 20])
    # 判断数组中的元素是不是大于10
    a > 10
    
    • 1
    • 2
    • 3
    array([False,  True, False,  True])
    
    • 1

    数组中所有大于10的元素的索引位置:

    np.where(a > 10)
    
    • 1
    (array([1, 3], dtype=int64),)
    
    • 1

    注意到 where 的返回值是一个元组。

    使用元组是由于 where 可以对多维数组使用,此时返回值就是多维的。

    可以直接用 where 的返回值进行索引:

    loc = np.where(a > 10)
    a[loc]
    
    • 1
    • 2
    array([12, 20])
    
    • 1

    多维数组

    a = np.array([[0, 12, 5, 20],
               [1, 2, 11, 15]]) 
    print(a)
    loc = np.where(a > 10)
    loc
    
    • 1
    • 2
    • 3
    • 4
    • 5
    [[ 0 12  5 20]
     [ 1  2 11 15]]
    
    
    
    
    
    (array([0, 0, 1, 1], dtype=int64), array([1, 3, 2, 3], dtype=int64))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    返回结果是一个二维的元组,每一维代表这一维的索引值:

    可以直接用来索引a:

    a[loc]
    
    • 1
    array([12, 20, 11, 15])
    
    • 1

    或者可以这样:

    rows, cols = np.where( a > 10)
    print(rows)
    print(cols)
    a[rows,cols]
    
    • 1
    • 2
    • 3
    • 4
    [0 0 1 1]
    [1 3 2 3]
    
    
    
    
    
    array([12, 20, 11, 15])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    另一个例子

    c = np.arange(25)
    c.shape= 5,5
    c
    
    • 1
    • 2
    • 3
    array([[ 0,  1,  2,  3,  4],
           [ 5,  6,  7,  8,  9],
           [10, 11, 12, 13, 14],
           [15, 16, 17, 18, 19],
           [20, 21, 22, 23, 24]])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    c > 12
    
    • 1
    array([[False, False, False, False, False],
           [False, False, False, False, False],
           [False, False, False,  True,  True],
           [ True,  True,  True,  True,  True],
           [ True,  True,  True,  True,  True]])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    np.where( c > 12 )
    
    • 1
    (array([2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4], dtype=int64),
     array([3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4], dtype=int64))
    
    • 1
    • 2
  • 相关阅读:
    Cortex-M系列处理器偶发死机定位方法
    ChatTTS web应用;基于文本指导的图像生成;使用Groq和Llama3在几秒内生成整本书;协作机器人画家,可以根据语言描述或图像在画布上作画
    【Linux】环境基础开发工具使用——vim使用
    算法设计实验第二周测试题解
    制作一个简单HTML电影网页设计(HTML+CSS)
    实战:基于卷积的MNIST手写体分类
    vue项目打包后dist目录运行方法
    LED点灯
    微信小程序-3
    机器人到达指定位置的方法数问题
  • 原文地址:https://blog.csdn.net/weixin_47692652/article/details/128144856