如果不懂 numpy,请别说自己是 python 程序员

论坛 期权论坛 期权     
Python开发者   2019-7-14 18:13   3489   0
(给Python开发者加星标,提升Python技能)
作者:牧马人 (本文来自作者投稿)
0. 前言




大约七八年前,我曾经用 pyOpenGL 画过地球磁层顶的三维模型,这段代码至今仍然还运行在某科研机构里。在那之前,我一直觉得自己是一个合(you)格(xiu)的 python 程序员,似乎无所不能。但磁层顶模型的显示效果令我沮丧——尽管这个模型只有十几万个顶点,拖拽、缩放却非常卡顿。最终,我把顶点数量删减到两万左右,以兼顾模型质量和响应速度,才勉强交付了这个任务。从此我开始怀疑 python 的性能,甚至一度怀疑 python 是否还是我的首选工具。

幸运的是,后来我遇到了 numpy 这个神器。numpy 是 python 科学计算的基础软件包,提供多了维数组对象,多种派生对象(掩码数组、矩阵等)以及用于快速操作数组的函数及 API,它包括数学、逻辑、数组形状变换、排序、选择、I/O 、离散傅立叶变换、基本线性代数、基本统计运算、随机模拟等等。

了解 numpy之后,我才想明白当初磁层顶的三维模型之所以慢,是因为使用了 list(python 数组)而不是 ndarray(numpy 数组)存储数据。有了 numpy,python 程序员才有可能写出媲美 C 语言运行速度的代码。熟悉 numpy,才能学会使用 pyOpenGL / pyOpenCV / pandas / matplotlib 等数据处理及可视化的模块。

事实上,numpy 的数据组织结构,尤其是数组(numpy.ndarray),几乎已经成为所有数据处理与可视化模块的标准数据结构了(这一点,类似于在机器学习领域 python 几乎已经成为首选工具语言)。越来越多的基于 python 的科学和数学软件包使用 numpy 数组,虽然这些工具通常都支持 python 的原生数组作为参数,但它们在处理之前会还是会将输入的数组转换为 numpy 的数组,而且也通常输出为 numpy 数组。在 python 的圈子里,numpy 的重要性和普遍性日趋增强。换句话说,为了高效地使用当今科学/数学基于 python 的工具(大部分的科学计算工具),你只知道如何使用 python 的原生数组类型是不够的,还需要知道如何使用 numpy 数组。

总结:在这个 AI 和 ML 霸屏的时代,如果不懂 numpy,请别说自己是 python 程序员。

1. list VS ndarray

numpy 的核心是 ndarray 对象(numpy 数组),它封装了 python 原生的同数据类型的 n 维数组(python 数组)。numpy 数组和 python 数组之间有几个重要的区别:

  • numpy 数组一旦创建,其元素数量就不能再改变了。 增删 ndarray 元素的操作,意味着创建一个新数组并删除原来的数组。python 数组的元素则可以动态增减不同,
  • numpy 数组中的元素都需要具有相同的数据类型,因此在内存中的大小相同。 python 数组则无此要求。
  • numpy 数组的方法涵盖了大量数学运算和复杂操作,许多方法在最外层的 numpy 命名空间中都有对应的映射函数。和 python 数组相比,numpy 数组的方法功能更强大,执行效率更高,代码更简洁。

然而,以上的差异并没有真正体现出 ndarray 的优势之所在,ndarray 的精髓在于 numpy 的两大特征:矢量化(vectorization)和广播(broadcast)。矢量化可以理解为代码中没有显式的循环、索引等,广播可以理解为隐式地对每个元素实施操作。矢量化和广播理解起来有点抽象,我们还是举个栗子来说明一下吧。

**例题 ** a 和 b 是等长的两个整数数组,求 a 和 b 对应元素之积组成的数组。

1.用 python 数组实现:

  1. c = list()
复制代码
  1. for i in range(len(a)):
复制代码
  1.   c.append(a[i]*b[i])
复制代码
用 numpy 数组实现:

  1. c = a*b
复制代码
这个栗子是不是体现了矢量化和广播的强大力量呢?请仔细体会!

总结:

  • 矢量化代码更简洁,更易于阅读
  • 更少的代码行通常意味着更少的错误
  • 代码更接近于标准的数学符号
  • 矢量化代码更 pythonic

2. dtype AND shape

子曰:找对象先了解品行,学对象先了解属性。 ndarray 对象有很多属性,详见下表。

属性                 说明
ndarray.dtype 元素类型
ndarray.shape 数组的结构
ndarray.ndim 秩,即轴的数量或维度的数量
ndarray.size 数组元素的个数
ndarray.itemsize 每个元素的大小,以字节为单位
ndarray.flags 数组的内存信息
ndarray.real 元素的实部
ndarray.imag 元素的虚部
ndarray.data 数组元素的实际存储区

基于以下三个原因,我认为,dtype 和 shape 是 ndarray 最重要的两个属性,重要到几乎可以忽略其他的属性。

  • 我们趟过的坑,几乎都是 dtype 挖的
  • 我们的迷茫,几乎都是因为 shape 和我们期望的不一样
  • 我们的工作,很多都是在改变 shape

ndarray.astype() 可以修改元素类型, ndarray.reshape() 可以重新定义数组的结构,这两个方法的重要性和其对应的属性一样。记住这两个属性和对应的两个方法,就算是登堂入室了。想了解 numpy 支持的元素类型,请点击《数学建模三剑客MSN》

3. 创建数组

(1) 创建简单数组

  1. numpy.array(object, dtype=None, copy=True, order=None, subok=False, ndmin=0)
复制代码
  1. numpy.empty(shape, dtype=float, order='C')
复制代码
  1. numpy.zeros(shape, dtype=float, order='C')
复制代码
  1. numpy.ones(shape, dtype=float, order='C')
复制代码
  1. numpy.eye(N, M=None, k=0, dtype=float, order='C')
复制代码
应用示例:

  1. >>> import numpy as np
复制代码
  1. >>>> np.array([1, 2, 3])
复制代码
  1. array([1, 2, 3])
复制代码
  1. >>> np.empty((2, 3))
复制代码
  1. array([[2.12199579e-314, 6.36598737e-314, 1.06099790e-313],
复制代码
  1.        [1.48539705e-313, 1.90979621e-313, 2.33419537e-313]])
复制代码
  1. >>> np.zeros(2)
复制代码
  1. array([0., 0.])
复制代码
  1. >>> np.ones(2)
复制代码
  1. array([1., 1.])
复制代码
  1. >>> np.eye(3)
复制代码
  1. array([[1., 0., 0.],
复制代码
  1.        [0., 1., 0.],
复制代码
  1.        [0., 0., 1.]])
复制代码
(2) 创建随机数组

  1. numpy.random.random(size=None)
复制代码
  1. numpy.random.randint(low, high=None, size=None, dtype='l')
复制代码
应用示例:

  1. >>> np.random.random(3)
复制代码
  1. array([0.29334156, 0.45858765, 0.99297047])
复制代码
  1. >>> np.random.randint(2, size=10)
复制代码
  1. array([1, 0, 0, 0, 1, 1, 0, 0, 1, 0])
复制代码
  1. >>> np.random.randint(5, size=(2, 4))
复制代码
  1. array([[4, 0, 2, 1],
复制代码
  1.        [3, 2, 2, 0]])
复制代码
  1. >>> np.random.randint(3,10,(2,4))
复制代码
  1. array([[4, 8, 9, 6],
复制代码
  1.        [7, 7, 7, 9]])
复制代码
(3) 在数值范围内创建数组

  1. numpy.arange(start, stop, step, dtype=None)
复制代码
  1. numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)
复制代码
  1. numpy.logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None)
复制代码
应用示例:

  1. >>> np.arange(5)
复制代码
  1. array([0, 1, 2, 3, 4])
复制代码
  1. >>> np.arange(0,5,2)
复制代码
  1. array([0, 2, 4])
复制代码
  1. >>> np.linspace(0, 5, 5)
复制代码
  1. array([0.  , 1.25, 2.5 , 3.75, 5.  ])
复制代码
  1. >>> np.linspace(0, 5, 5, endpoint=False)
复制代码
  1. array([0., 1., 2., 3., 4.])
复制代码
  1. >>> np.logspace(1,3,3)
复制代码
  1. array([  10.,  100., 1000.])
复制代码
  1. >>> np.logspace(1, 3, 3, endpoint=False)
复制代码
  1. array([ 10.        ,  46.41588834, 215.443469  ])
复制代码
(4) 从已有数组创建数组

  1. numpy.asarray(a, dtype=None, order=None)
复制代码
  1. numpy.empty_like(a, dtype=None, order='K', subok=True)
复制代码
  1. numpy.zeros_like(a, dtype=None, order='K', subok=True)
复制代码
  1. numpy.ones_like(a, dtype=None, order='K', subok=True)[source]
复制代码
应用示例:

  1. >>> np.asarray([1,2,3])
复制代码
  1. array([1, 2, 3])
复制代码
  1. >>> np.empty_like(np.asarray([1,2,3]))
复制代码
  1. array([0, 0, 0])
复制代码
  1. >>> np.zeros_like(np.asarray([1,2,3]))
复制代码
  1. array([0, 0, 0])
复制代码
  1. >>> np.ones_like(np.asarray([1,2,3]))
复制代码
  1. array([1, 1, 1])
复制代码
(5) 构造复杂数组

[1] 重复数组 tile

  1. >>> a = np.arange(3)
复制代码
  1. >>> a
复制代码
  1. array([0, 1, 2])
复制代码
  1. >>> np.tile(a, 2)
复制代码
  1. array([0, 1, 2, 0, 1, 2])
复制代码
  1. >>> np.tile(a, (2,3))
复制代码
  1. array([[0, 1, 2, 0, 1, 2, 0, 1, 2],
复制代码
  1.        [0, 1, 2, 0, 1, 2, 0, 1, 2]])
复制代码
[2] 重复元素 repeat

  1. >>> a = np.arange(3)
复制代码
  1. >>> a
复制代码
  1. array([0, 1, 2])
复制代码
  1. >>> a.repeat(2)
复制代码
  1. array([0, 0, 1, 1, 2, 2])
复制代码
[3] 一维数组网格化: meshgrid

  1. >>> lon = np.arange(30, 120, 10)
复制代码
  1. >>> lon
复制代码
  1. array([ 30,  40,  50,  60,  70,  80,  90, 100, 110])
复制代码
  1. >>> lat = np.arange(10, 50, 10)
复制代码
  1. >>> lat
复制代码
  1. array([10, 20, 30, 40])
复制代码
  1. >>> lons, lats = np.meshgrid(lon, lat)
复制代码
  1. >>> lons
复制代码
  1. array([[ 30,  40,  50,  60,  70,  80,  90, 100, 110],
复制代码
  1.        [ 30,  40,  50,  60,  70,  80,  90, 100, 110],
复制代码
  1.        [ 30,  40,  50,  60,  70,  80,  90, 100, 110],
复制代码
  1.        [ 30,  40,  50,  60,  70,  80,  90, 100, 110]])
复制代码
  1. >>> lats
复制代码
  1. array([[10, 10, 10, 10, 10, 10, 10, 10, 10],
复制代码
  1.        [20, 20, 20, 20, 20, 20, 20, 20, 20],
复制代码
  1.        [30, 30, 30, 30, 30, 30, 30, 30, 30],
复制代码
  1.        [40, 40, 40, 40, 40, 40, 40, 40, 40]])
复制代码
[4] 指定范围和分割方式的网格化: mgrid

  1. >>> lats, lons= np.mgrid[10:50:10, 30:120:10]
复制代码
  1. >>> lats
复制代码
  1. array([[10, 10, 10, 10, 10, 10, 10, 10, 10],
复制代码
  1.        [20, 20, 20, 20, 20, 20, 20, 20, 20],
复制代码
  1.        [30, 30, 30, 30, 30, 30, 30, 30, 30],
复制代码
  1.        [40, 40, 40, 40, 40, 40, 40, 40, 40]])
复制代码
  1. >>> lons
复制代码
  1. array([[ 30,  40,  50,  60,  70,  80,  90, 100, 110],
复制代码
  1.        [ 30,  40,  50,  60,  70,  80,  90, 100, 110],
复制代码
  1.        [ 30,  40,  50,  60,  70,  80,  90, 100, 110],
复制代码
  1.        [ 30,  40,  50,  60,  70,  80,  90, 100, 110]])
复制代码
  1. >>> lats, lons = np.mgrid[10:50:5j, 30:120:10j]
复制代码
  1. >>> lats
复制代码
  1. array([[10., 10., 10., 10., 10., 10., 10., 10., 10., 10.],
复制代码
  1.        [20., 20., 20., 20., 20., 20., 20., 20., 20., 20.],
复制代码
  1.        [30., 30., 30., 30., 30., 30., 30., 30., 30., 30.],
复制代码
  1.        [40., 40., 40., 40., 40., 40., 40., 40., 40., 40.],
复制代码
  1.        [50., 50., 50., 50., 50., 50., 50., 50., 50., 50.]])
复制代码
  1. >>> lons
复制代码
  1. array([[ 30.,  40.,  50.,  60.,  70.,  80.,  90., 100., 110., 120.],
复制代码
  1.        [ 30.,  40.,  50.,  60.,  70.,  80.,  90., 100., 110., 120.],
复制代码
  1.        [ 30.,  40.,  50.,  60.,  70.,  80.,  90., 100., 110., 120.],
复制代码
  1.        [ 30.,  40.,  50.,  60.,  70.,  80.,  90., 100., 110., 120.],
复制代码
  1.        [ 30.,  40.,  50.,  60.,  70.,  80.,  90., 100., 110., 120.]])
复制代码
上面的例子中用到了虚数。构造复数的方法如下:

  1. >>> complex(2,5)
复制代码
  1. (2+5j)
复制代码
  1. 1
复制代码
  1. 2
复制代码
  1. 4. 数组操作
复制代码
  1. (1) 切片和索引
复制代码
  1. 对于一维数组的索引和切片,numpy和python的list一样,甚至更灵活。
复制代码
  1. a = np.arange(9)
复制代码
  1. >>> a[-1]                            # 最后一个元素
复制代码
  1. 8
复制代码
  1. >>> a[2:5]                           # 返回第2到第5个元素
复制代码
  1. array([2, 3, 4])
复制代码
  1. >>> a[:7:3]                          # 返回第0到第7个元素,步长为3
复制代码
  1. array([0, 3, 6])
复制代码
  1. >>> a[::-1]                          # 返回逆序的数组
复制代码
  1. array([8, 7, 6, 5, 4, 3, 2, 1, 0])
复制代码
假设有一栋2层楼,每层楼内的房间都是3行4列,那我们可以用一个三维数组来保存每个房间的居住人数(当然,也可以是房间面积等其他数值信息)。

  1. >>> a = np.arange(24).reshape(2,3,4)    # 2层3行4列
复制代码
  1. >>> a
复制代码
  1. array([[[ 0,  1,  2,  3],
复制代码
  1.         [ 4,  5,  6,  7],
复制代码
  1.         [ 8,  9, 10, 11]],
复制代码
  1.        [[12, 13, 14, 15],
复制代码
  1.         [16, 17, 18, 19],
复制代码
  1. [/code][code]        [20, 21, 22, 23]]])
复制代码
  1. >>> a[1][2][3]                          # 虽然可以这样
复制代码
  1. [/code][code]23
复制代码
  1. >>> a[1,2,3]                            # 但这才是规范的用法
复制代码
  1. 23
复制代码
  1. >>> a[:,0,0]                            # 所有楼层的第1排第1列
复制代码
  1. array([ 0, 12])
复制代码
  1. [/code][code]>>> a[0,:,:]                            # 1楼的所有房间,等价与a[0]或a[0,...]
复制代码
  1. array([[ 0,  1,  2,  3],
复制代码
  1. [/code][code]       [ 4,  5,  6,  7],
复制代码
  1. [/code][code]       [ 8,  9, 10, 11]])
复制代码
  1. [/code][code]>>> a[:,:,1:3]                          # 所有楼层所有排的第2到4列
复制代码
  1. [/code][code]array([[[ 1,  2],
复制代码
  1.         [ 5,  6],
复制代码
  1.         [ 9, 10]],
复制代码
  1. [/code][code]       [[13, 14],
复制代码
  1.         [17, 18],
复制代码
  1.        [21, 22]]])
复制代码
  1. [/code][code]>>> a[1,:,-1]                           # 2层每一排的最后一个房间
复制代码
  1. array([15, 19, 23])
复制代码
提示:对多维数组切片或索引得到的结果,维度不是确定的。

(2) 改变数组的结构

  1. numpy 数组的存储顺序和数组的维度是不相干的,因此改变数组的维度是非常便捷的操作,除 resize() 外,这一类操作不会改变所操作的数组本身的存储顺序。
复制代码
  1. >>> a = np.array([[1,2,3],[4,5,6]])
复制代码
  1. [/code][code]>>> a.shape                     # 查看数组维度
复制代码
  1. [/code][code](2, 3)
复制代码
  1. [/code][code]>>> a.reshape(3,2)              # 返回3行2列的数组
复制代码
  1. [/code][code]array([[1, 2],
复制代码
  1. [/code][code]       [3, 4],
复制代码
  1. [/code][code]       [5, 6]])
复制代码
  1. [/code][code]>>> a.ravel()                   # 返回一维数组
复制代码
  1. [/code][code]array([1, 2, 3, 4, 5, 6])
复制代码
  1. [/code][code]>>> a.transpose()               # 行变列(类似于矩阵转置)
复制代码
  1. [/code][code]array([[1, 4],
复制代码
  1. [/code][code]       [2, 5],
复制代码
  1. [/code][code]       [3, 6]])
复制代码
  1. [/code][code]>>> a.resize((3,2))             # 类似于reshape,但会改变所操作的数组
复制代码
  1. [/code][code]>>> a
复制代码
  1. array([[1, 2],
复制代码
  1. [/code][code]       [3, 4],
复制代码
  1. [/code][code]       [5, 6]])
复制代码
np.rollaxis() 用于改变轴的顺序,返回一个新的数组。用法如下:

  1. numpy.rollaxis(a, axis, start=0)
复制代码

  • a: 数组
  • axis: 要改变的轴。其他轴的相对顺序保持不变
  • start: 要改变的轴滚动至此位置之前。默认值为0

应用示例:

  1. >>> a = np.ones((3,4,5,6))
复制代码
  1. >>> np.rollaxis(a, 3, 1).shape
复制代码
  1. (3, 6, 4, 5)
复制代码
  1. >>> np.rollaxis(a, 2).shape
复制代码
  1. (5, 3, 4, 6)
复制代码
  1. >>> np.rollaxis(a, 1, 4).shape
复制代码
  1. (3, 5, 6, 4)
复制代码
(3) 数组合并

[1] append

对于刚刚上手 numpy 的程序员来说,最大的困惑就是不能使用 append() 方法向数组内添加元素了,甚至连 append() 方法都找不到了。其实,numpy 仍然保留了 append() 方法,只不过这个方法不再是 numpy 数组的方法,而是是升级到最外层的 numpy 命名空间了,并且该方法的功能不再是追加元素,而是合并数组了。

  1. >>> np.append([1, 2, 3], [[4, 5, 6], [7, 8, 9]])
复制代码
  1. array([1, 2, 3, 4, 5, 6, 7, 8, 9])
复制代码
  1. >>> np.append([[1, 2, 3]], [[4, 5, 6]], axis=0)
复制代码
  1. array([[1, 2, 3],
复制代码
  1.       [4, 5, 6]])
复制代码
  1. >>> np.append(np.array([[1, 2, 3]]), np.array([[4, 5, 6]]), axis=1)
复制代码
  1. array([[1, 2, 3, 4, 5, 6]])
复制代码
[2] concatenate

concatenate() 和 append() 的用法非常类似,不过是把两个合并对象写成了一个元组 。

  1. >>> a = np.array([[1, 2], [3, 4]])
复制代码
  1. >>> b = np.array([[5, 6]])
复制代码
  1. >>> np.concatenate((a, b), axis=0)
复制代码
  1. array([[1, 2],
复制代码
  1. [/code][code]       [3, 4],
复制代码
  1. [/code][code]       [5, 6]])
复制代码
  1. >>> np.concatenate((a, b.T), axis=1)
复制代码
  1. array([[1, 2, 5],
复制代码
  1. [/code][code]       [3, 4, 6]])
复制代码
  1. >>> np.concatenate((a, b), axis=None)
复制代码
  1. array([1, 2, 3, 4, 5, 6])
复制代码
[3] stack

除了 append() 和 concatenate() ,数组合并还有更直接的水平合并(hstack)、垂直合并(vstack)、深度合并(dstack)等方式。假如你比我还懒,那就只用 stack 吧,足够了。

  1. >>> a = np.arange(9).reshape(3,3)
复制代码
  1. [/code][code]>>> b = np.arange(9,18).reshape(3,3)
复制代码
  1. [/code][code]>>> a
复制代码
  1. [/code][code]array([[0, 1, 2],
复制代码
  1. [/code][code]       [3, 4, 5],
复制代码
  1. [/code][code]       [6, 7, 8]])
复制代码
  1. [/code][code]>>> b
复制代码
  1. [/code][code]array([[ 9, 10, 11],
复制代码
  1. [/code][code]       [12, 13, 14],
复制代码
  1. [/code][code]       [15, 16, 17]])
复制代码
  1. [/code][code]>>> np.hstack((a,b))                        # 水平合并
复制代码
  1. [/code][code]array([[ 0,  1,  2,  9, 10, 11],
复制代码
  1. [/code][code]       [ 3,  4,  5, 12, 13, 14],
复制代码
  1. [/code][code]       [ 6,  7,  8, 15, 16, 17]])
复制代码
  1. [/code][code]>>> np.vstack((a,b))                        # 垂直合并
复制代码
  1. [/code][code]array([[ 0,  1,  2],
复制代码
  1. [/code][code]       [ 3,  4,  5],
复制代码
  1. [/code][code]       [ 6,  7,  8],
复制代码
  1. [/code][code]       [ 9, 10, 11],
复制代码
  1. [/code][code]       [12, 13, 14],
复制代码
  1. [/code][code]       [15, 16, 17]])
复制代码
  1. [/code][code]>>> np.dstack((a,b))                        # 深度合并
复制代码
  1. [/code][code]array([[[ 0,  9],
复制代码
  1. [/code][code]        [ 1, 10],
复制代码
  1. [/code][code]        [ 2, 11]],
复制代码
  1. [/code][code]
复制代码
  1. [/code][code]       [[ 3, 12],
复制代码
  1. [/code][code]        [ 4, 13],
复制代码
  1. [/code][code]        [ 5, 14]],
复制代码
  1. [/code][code]
复制代码
  1. [/code][code]       [[ 6, 15],
复制代码
  1. [/code][code]        [ 7, 16],
复制代码
  1. [/code][code]        [ 8, 17]]])
复制代码
(4) 数组拆分

拆分是合并的逆过程,概念是一样的,但稍微有一点不同:

  1. >>> a = np.arange(4).reshape(2,2)
复制代码
  1. [/code][code]>>> a
复制代码
  1. [/code][code]array([[0, 1],
复制代码
  1. [/code][code]       [2, 3]])
复制代码
  1. [/code][code]>>> x, y = np.hsplit(a, 2)                        # 水平拆分,返回list
复制代码
  1. [/code][code]>>> x
复制代码
  1. [/code][code]array([[0],
复制代码
  1. [/code][code]       [2]])
复制代码
  1. [/code][code]>>> y
复制代码
  1. [/code][code]array([[1],
复制代码
  1. [/code][code]       [3]])
复制代码
  1. [/code][code]>>> x, y = np.vsplit(a, 2)                        # 垂直拆分,返回list
复制代码
  1. [/code][code]>>> x
复制代码
  1. [/code][code]array([[0, 1]])
复制代码
  1. [/code][code]>>> y
复制代码
  1. [/code][code]array([[2, 3]])
复制代码
  1. [/code][code]>>> a = np.arange(8).reshape(2,2,2)
复制代码
  1. [/code][code]>>> a
复制代码
  1. [/code][code]array([[[0, 1],
复制代码
  1. [/code][code]        [2, 3]],
复制代码
  1. [/code][code]
复制代码
  1. [/code][code]       [[4, 5],
复制代码
  1. [/code][code]        [6, 7]]])
复制代码
  1. [/code][code]>>> x,y = np.dsplit(a, 2)                        # 深度拆分,返回list
复制代码
  1. [/code][code]>>> x
复制代码
  1. [/code][code]array([[[0],
复制代码
  1. [/code][code]        [2]],
复制代码
  1. [/code][code]
复制代码
  1. [/code][code]       [[4],
复制代码
  1. [/code][code]        [6]]])
复制代码
  1. [/code][code]>>> y
复制代码
  1. [/code][code]array([[[1],
复制代码
  1. [/code][code]        [3]],
复制代码
  1. [/code][code]
复制代码
  1. [/code][code]       [[5],
复制代码
  1. [/code][code]        [7]]])
复制代码
(5) 数组排序

排序不是 numpy 数组的强项,但 python 数组的排序速度依然只能望其项背。

[1] numpy.sort()

numpy.sort() 函数返回输入数组的排序副本。

  1. numpy.sort(a, axis=-1, kind='quicksort', order=None)
复制代码
  • a: 要排序的数组
  • axis: 沿着它排序数组的轴,如果没有,数组会被展开,沿着最后的轴排序
  • kind: 排序方法,默认为’quicksort’(快速排序),其他选项还有 ‘mergesort’(归并排序)和 ‘heapsort’(堆排序)
  • order: 如果数组包含字段,则是要排序的字段

应用示例:

  1. >>> a = np.array([3,  1,  2])
复制代码
  1. [/code][code]>>> np.sort(a)
复制代码
  1. [/code][code]array([1, 2, 3])
复制代码
  1. [/code][code]>>> dt = np.dtype([('name',  'S10'),('age',  int)])
复制代码
  1. [/code][code]>>> a = np.array([("raju",21),("anil",25),("ravi",  17),  ("amar",27)], dtype = dt)
复制代码
  1. [/code][code]>>> a
复制代码
  1. [/code][code]array([(b'raju', 21), (b'anil', 25), (b'ravi', 17), (b'amar', 27)],
复制代码
[code][/code][code]      dtype=[('name', 'S10'), ('age', '
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:835
帖子:167
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP