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

(给Python开发者加星标,提升Python技能)

作者:牧马人 (本文来自作者投稿)

0. 前言

2160ac7882f8c7e0fd3c68501ddec30b.png

大约七八年前,我曾经用 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 数组实现: 

c = list()for i in range(len(a)):  c.append(a[i]*b[i])

用 numpy 数组实现:

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) 创建简单数组

numpy.array(object, dtype=None, copy=True, order=None, subok=False, ndmin=0)numpy.empty(shape, dtype=float, order='C')numpy.zeros(shape, dtype=float, order='C')numpy.ones(shape, dtype=float, order='C')numpy.eye(N, M=None, k=0, dtype=float, order='C')

应用示例:

>>> import numpy as np>>>> np.array([1, 2, 3])array([1, 2, 3])>>> np.empty((2, 3))array([[2.12199579e-314, 6.36598737e-314, 1.06099790e-313],       [1.48539705e-313, 1.90979621e-313, 2.33419537e-313]])>>> np.zeros(2)array([0., 0.])>>> np.ones(2)array([1., 1.])>>> np.eye(3)array([[1., 0., 0.],       [0., 1., 0.],       [0., 0., 1.]])

(2) 创建随机数组

numpy.random.random(size=None)numpy.random.randint(low, high=None, size=None, dtype='l')

应用示例:

>>> np.random.random(3)array([0.29334156, 0.45858765, 0.99297047])>>> np.random.randint(2, size=10)array([1, 0, 0, 0, 1, 1, 0, 0, 1, 0])>>> np.random.randint(5, size=(2, 4))array([[4, 0, 2, 1],       [3, 2, 2, 0]])>>> np.random.randint(3,10,(2,4))array([[4, 8, 9, 6],       [7, 7, 7, 9]])

(3) 在数值范围内创建数组

numpy.arange(start, stop, step, dtype=None)numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)numpy.logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None)

应用示例:

>>> np.arange(5)array([0, 1, 2, 3, 4])>>> np.arange(0,5,2)array([0, 2, 4])>>> np.linspace(0, 5, 5)array([0.  , 1.25, 2.5 , 3.75, 5.  ])>>> np.linspace(0, 5, 5, endpoint=False)array([0., 1., 2., 3., 4.])>>> np.logspace(1,3,3)array([  10.,  100., 1000.])>>> np.logspace(1, 3, 3, endpoint=False)array([ 10.        ,  46.41588834, 215.443469  ])

(4) 从已有数组创建数组

numpy.asarray(a, dtype=None, order=None)numpy.empty_like(a, dtype=None, order='K', subok=True)numpy.zeros_like(a, dtype=None, order='K', subok=True)numpy.ones_like(a, dtype=None, order='K', subok=True)[source]

应用示例:

>>> np.asarray([1,2,3])array([1, 2, 3])>>> np.empty_like(np.asarray([1,2,3]))array([0, 0, 0])>>> np.zeros_like(np.asarray([1,2,3]))array([0, 0, 0])>>> np.ones_like(np.asarray([1,2,3]))array([1, 1, 1])

(5) 构造复杂数组

[1] 重复数组 tile

>>> a = np.arange(3)>>> aarray([0, 1, 2])>>> np.tile(a, 2)array([0, 1, 2, 0, 1, 2])>>> np.tile(a, (2,3))array([[0, 1, 2, 0, 1, 2, 0, 1, 2],       [0, 1, 2, 0, 1, 2, 0, 1, 2]])

[2] 重复元素 repeat

>>> a = np.arange(3)>>> aarray([0, 1, 2])>>> a.repeat(2)array([0, 0, 1, 1, 2, 2])

[3] 一维数组网格化: meshgrid

>>> lon = np.arange(30, 120, 10)>>> lonarray([ 30,  40,  50,  60,  70,  80,  90, 100, 110])>>> lat = np.arange(10, 50, 10)>>> latarray([10, 20, 30, 40])>>> lons, lats = np.meshgrid(lon, lat)>>> lonsarray([[ 30,  40,  50,  60,  70,  80,  90, 100, 110],       [ 30,  40,  50,  60,  70,  80,  90, 100, 110],       [ 30,  40,  50,  60,  70,  80,  90, 100, 110],       [ 30,  40,  50,  60,  70,  80,  90, 100, 110]])>>> latsarray([[10, 10, 10, 10, 10, 10, 10, 10, 10],       [20, 20, 20, 20, 20, 20, 20, 20, 20],       [30, 30, 30, 30, 30, 30, 30, 30, 30],       [40, 40, 40, 40, 40, 40, 40, 40, 40]])

[4] 指定范围和分割方式的网格化: mgrid

>>> lats, lons= np.mgrid[10:50:10, 30:120:10]>>> lats array([[10, 10, 10, 10, 10, 10, 10, 10, 10],       [20, 20, 20, 20, 20, 20, 20, 20, 20],       [30, 30, 30, 30, 30, 30, 30, 30, 30],       [40, 40, 40, 40, 40, 40, 40, 40, 40]])>>> lonsarray([[ 30,  40,  50,  60,  70,  80,  90, 100, 110],       [ 30,  40,  50,  60,  70,  80,  90, 100, 110],       [ 30,  40,  50,  60,  70,  80,  90, 100, 110],       [ 30,  40,  50,  60,  70,  80,  90, 100, 110]])>>> lats, lons = np.mgrid[10:50:5j, 30:120:10j]>>> latsarray([[10., 10., 10., 10., 10., 10., 10., 10., 10., 10.],       [20., 20., 20., 20., 20., 20., 20., 20., 20., 20.],       [30., 30., 30., 30., 30., 30., 30., 30., 30., 30.],       [40., 40., 40., 40., 40., 40., 40., 40., 40., 40.],       [50., 50., 50., 50., 50., 50., 50., 50., 50., 50.]])>>> lonsarray([[ 30.,  40.,  50.,  60.,  70.,  80.,  90., 100., 110., 120.],       [ 30.,  40.,  50.,  60.,  70.,  80.,  90., 100., 110., 120.],       [ 30.,  40.,  50.,  60.,  70.,  80.,  90., 100., 110., 120.],       [ 30.,  40.,  50.,  60.,  70.,  80.,  90., 100., 110., 120.],       [ 30.,  40.,  50.,  60.,  70.,  80.,  90., 100., 110., 120.]])

上面的例子中用到了虚数。构造复数的方法如下:

>>> complex(2,5)(2+5j)124. 数组操作(1) 切片和索引对于一维数组的索引和切片,numpy和python的list一样,甚至更灵活。a = np.arange(9)>>> a[-1]                            # 最后一个元素8>>> a[2:5]                           # 返回第2到第5个元素array([2, 3, 4])>>> a[:7:3]                          # 返回第0到第7个元素,步长为3array([0, 3, 6])>>> a[::-1]                          # 返回逆序的数组array([8, 7, 6, 5, 4, 3, 2, 1, 0])

假设有一栋2层楼,每层楼内的房间都是3行4列,那我们可以用一个三维数组来保存每个房间的居住人数(当然,也可以是房间面积等其他数值信息)。

>>> a = np.arange(24).reshape(2,3,4)    # 2层3行4列>>> aarray([[[ 0,  1,  2,  3],        [ 4,  5,  6,  7],        [ 8,  9, 10, 11]],       [[12, 13, 14, 15],        [16, 17, 18, 19],        [20, 21, 22, 23]]])>>> a[1][2][3]                          # 虽然可以这样23>>> a[1,2,3]                            # 但这才是规范的用法23>>> a[:,0,0]                            # 所有楼层的第1排第1列array([ 0, 12])>>> a[0,:,:]                            # 1楼的所有房间,等价与a[0]或a[0,...]array([[ 0,  1,  2,  3],       [ 4,  5,  6,  7],       [ 8,  9, 10, 11]])>>> a[:,:,1:3]                          # 所有楼层所有排的第2到4列array([[[ 1,  2],        [ 5,  6],        [ 9, 10]],       [[13, 14],        [17, 18],       [21, 22]]])>>> a[1,:,-1]                           # 2层每一排的最后一个房间array([15, 19, 23])

提示:对多维数组切片或索引得到的结果,维度不是确定的。

(2) 改变数组的结构

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

np.rollaxis() 用于改变轴的顺序,返回一个新的数组。用法如下:

numpy.rollaxis(a, axis, start=0)
  • a: 数组

  • axis: 要改变的轴。其他轴的相对顺序保持不变

  • start: 要改变的轴滚动至此位置之前。默认值为0

应用示例:

>>> a = np.ones((3,4,5,6))>>> np.rollaxis(a, 3, 1).shape(3, 6, 4, 5)>>> np.rollaxis(a, 2).shape(5, 3, 4, 6)>>> np.rollaxis(a, 1, 4).shape(3, 5, 6, 4)

(3) 数组合并

[1] append

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

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

[2] concatenate

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

>>> a = np.array([[1, 2], [3, 4]])>>> b = np.array([[5, 6]])>>> np.concatenate((a, b), axis=0)array([[1, 2],       [3, 4],       [5, 6]])>>> np.concatenate((a, b.T), axis=1)array([[1, 2, 5],       [3, 4, 6]])>>> np.concatenate((a, b), axis=None)array([1, 2, 3, 4, 5, 6])

[3] stack

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

>>> a = np.arange(9).reshape(3,3)>>> b = np.arange(9,18).reshape(3,3)>>> aarray([[0, 1, 2],       [3, 4, 5],       [6, 7, 8]])>>> barray([[ 9, 10, 11],       [12, 13, 14],       [15, 16, 17]])>>> np.hstack((a,b))                        # 水平合并array([[ 0,  1,  2,  9, 10, 11],       [ 3,  4,  5, 12, 13, 14],       [ 6,  7,  8, 15, 16, 17]])>>> np.vstack((a,b))                        # 垂直合并array([[ 0,  1,  2],       [ 3,  4,  5],       [ 6,  7,  8],       [ 9, 10, 11],       [12, 13, 14],       [15, 16, 17]])>>> np.dstack((a,b))                        # 深度合并array([[[ 0,  9],        [ 1, 10],        [ 2, 11]],       [[ 3, 12],        [ 4, 13],        [ 5, 14]],       [[ 6, 15],        [ 7, 16],        [ 8, 17]]])

(4) 数组拆分

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

>>> a = np.arange(4).reshape(2,2)>>> aarray([[0, 1],       [2, 3]])>>> x, y = np.hsplit(a, 2)                        # 水平拆分,返回list>>> xarray([[0],       [2]])>>> yarray([[1],       [3]])>>> x, y = np.vsplit(a, 2)                        # 垂直拆分,返回list>>> xarray([[0, 1]])>>> yarray([[2, 3]])>>> a = np.arange(8).reshape(2,2,2)>>> aarray([[[0, 1],        [2, 3]],       [[4, 5],        [6, 7]]])>>> x,y = np.dsplit(a, 2)                        # 深度拆分,返回list>>> xarray([[[0],        [2]],       [[4],        [6]]])>>> yarray([[[1],        [3]],       [[5],        [7]]])

(5) 数组排序

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

[1] numpy.sort()

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

numpy.sort(a, axis=-1, kind='quicksort', order=None)
  • a: 要排序的数组

  • axis: 沿着它排序数组的轴,如果没有,数组会被展开,沿着最后的轴排序

  • kind: 排序方法,默认为’quicksort’(快速排序),其他选项还有 ‘mergesort’(归并排序)和 ‘heapsort’(堆排序)

  • order: 如果数组包含字段,则是要排序的字段

应用示例:

>>> a = np.array([3,  1,  2])>>> np.sort(a)array([1, 2, 3])>>> dt = np.dtype([('name',  'S10'),('age',  int)])>>> a = np.array([("raju",21),("anil",25),("ravi",  17),  ("amar",27)], dtype = dt)>>> aarray([(b'raju', 21), (b'anil', 25), (b'ravi', 17), (b'amar', 27)],      dtype=[('name', 'S10'), ('age', ')])>>> np.sort(a, order='name')array([(b'amar', 27), (b'anil', 25), (b'raju', 21), (b'ravi', 17)],      dtype=[('name', 'S10'), ('age', ')])

[2] numpy.argsort()

函数返回的是数组值从小到大的索引值。

numpy.argsort(a, axis=-1, kind='quicksort', order=None)
  • a: 要排序的数组

  • axis: 沿着它排序数组的轴,如果没有,数组会被展开,沿着最后的轴排序

  • kind: 排序方法,默认为’quicksort’(快速排序),其他选项还有 ‘mergesort’(归并排序)和 ‘heapsort’(堆排序)

  • order: 如果数组包含字段,则是要排序的字段

应用示例:

>>> a = np.array([3,  1,  2])>>> np.argsort(a)array([1, 2, 0], dtype=int64)

(6) 查找和筛选

[1] 返回数组中最大值和最小值的索引

numpy.argmax(a, axis=None, out=None)numpy.argmin(a, axis=None, out=None)

[2] 返回数组中非零元素的索引

numpy.nonzero(a)

[3] 返回数组中满足给定条件的元素的索引

numpy.where(condition[, x, y])

应用示例:

>>> a = np.arange(10)>>> aarray([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])>>> np.where(a 5)(array([0, 1, 2, 3, 4], dtype=int64),)>>> a = a.reshape((2, -1))>>> aarray([[0, 1, 2, 3, 4],       [5, 6, 7, 8, 9]])>>> np.where(a 5)(array([0, 0, 0, 0, 0], dtype=int64), array([0, 1, 2, 3, 4], dtype=int64))>>> np.where(a 5, a, array([[ 0,  1,  2,  3,  4],       [50, 60, 70, 80, 90]])

[4] 返回数组中被同结构布尔数组选中的各元素

numpy.extract(condition, arr)

应用示例:

>>> a = np.arange(12).reshape((3, 4))>>> aarray([[ 0,  1,  2,  3],       [ 4,  5,  6,  7],       [ 8,  9, 10, 11]])>>> condition = np.mod(a, 3)==0>>> conditionarray([[ True, False, False,  True],       [False, False,  True, False],       [False,  True, False, False]])>>> np.extract(condition, a)array([0, 3, 6, 9])

(7) 增减元素

[1] 在给定索引之前沿给定轴在输入数组中插入值,并返回新的数组

numpy.insert(arr, obj, values, axis=None)

应用示例:

>>> a = np.array([[1, 1], [2, 2], [3, 3]])>>> aarray([[1, 1],       [2, 2],       [3, 3]])>>> np.insert(a, 1, 5)array([1, 5, 1, 2, 2, 3, 3])>>> np.insert(a, 1, 5, axis=0)array([[1, 1],       [5, 5],       [2, 2],       [3, 3]])>>> np.insert(a, 1, [5,7], axis=0)array([[1, 1],       [5, 7],       [2, 2],       [3, 3]])>>> np.insert(a, 1, 5, axis=1)array([[1, 5, 1],       [2, 5, 2],       [3, 5, 3]])

[2] 在给定索引之前沿给定轴删除指定子数组,并返回新的数组

numpy.delete(arr, obj, axis=None)

应用示例:

>>> a = np.array([[1, 2], [3, 4], [5, 6]])>>> aarray([[1, 2],       [3, 4],       [5, 6]])>>> np.delete(a, 1)array([1, 3, 4, 5, 6])>>> np.delete(a, 1, axis=0)array([[1, 2],       [5, 6]])>>> np.delete(a, 1, axis=1)array([[1],       [3],       [5]])

[3] 去除重复元素

numpy.unique(ar, return_index=False, return_inverse=False, return_counts=False, axis=None)
  • arr:输入数组,如果不是一维数组则会展开

  • return_index:如果为true,返回新列表元素在旧列表中的位置(下标),并以列表形式储

  • return_inverse:如果为true,返回旧列表元素在新列表中的位置(下标),并以列表形式储

  • return_counts:如果为true,返回去重数组中的元素在原数组中的出现次数

应用示例:

>>> a = np.array([[1, 0, 0], [1, 0, 0], [2, 3, 4]])>>> np.unique(a)array([0, 1, 2, 3, 4])>>> np.unique(a, axis=0)array([[1, 0, 0],       [2, 3, 4]])>>> u, indices = np.unique(a, return_index=True)>>> uarray([0, 1, 2, 3, 4])>>> indicesarray([1, 0, 6, 7, 8], dtype=int64)>>> u, indices = np.unique(a, return_inverse=True)>>> uarray([0, 1, 2, 3, 4])>>> indicesarray([1, 0, 0, 1, 0, 0, 2, 3, 4], dtype=int64)>>> u, num = np.unique(a, return_counts=True)>>> uarray([0, 1, 2, 3, 4])>>> numarray([4, 2, 1, 1, 1], dtype=int64)

(8) 数组IO

numpy 为 ndarray 对象引入了新的二进制文件格式,用于存储重建 ndarray 所需的数据、图形、dtype 和其他信息。.npy 文件存储单个数组,.npz 文件存取多个数组。

[1] 保存单个数组到文件

numpy.save(file, arr, allow_pickle=True, fix_imports=True)
  • file: 要保存的文件,扩展名为 .npy,如果文件路径末尾没有扩展名 .npy,该扩展名会被自动加上

  • arr: 要保存的数组

  • allow_pickle: 可选,布尔值,允许使用 python pickles 保存对象数组,python 中的 pickle 用于在保存到磁盘文件或从磁盘文件读取之前,对对象进行序列化和反序列化

  • fix_imports: 可选,为了方便 pyhton2 读取 python3 保存的数据

[2] 保存多个数组到文件

numpy.savze() 函数用于将多个数组写入文件,默认情况下,数组是以未压缩的原始二进制格式保存在扩展名为 .npz 的文件中。

numpy.savez(file, *args, **kwds)
  • file: 要保存的文件,扩展名为 .npz,如果文件路径末尾没有扩展名 .npz,该扩展名会被自动加上

  • args: 要保存的数组,可以使用关键字参数为数组起一个名字,非关键字参数传递的数组会自动起名为 arr_0, arr_1, …

  • kwds: 要保存的数组使用关键字名称

[3] 从文件加载数组

numpy.load(file, mmap_mode=None, allow_pickle=True, fix_imports=True, encoding='ASCII')
  • file: 类文件对象(支持 seek() 和 read()方法)或者要读取的文件路径

  • arr: 打开方式,None | ‘r+’ | ‘r’ | ‘w+’ | ‘c’

  • allow_pickle: 可选,布尔值,允许使用 python pickles 保存对象数组,python 中的 pickle 用于在保存到磁盘文件或从磁盘文件读取之前,对对象进行序列化和反序列化

  • fix_imports: 可选,为了方便 pyhton2 读取 python3 保存的数据

  • encoding: 编码格式,‘latin1’ | ‘ASCII’ | ‘bytes’

应用示例:

a = np.array([[1,2,3],[4,5,6]])b = np.arange(0, 1.0, 0.1)c = np.sin(b)# c 使用了关键字参数 sin_arraynp.savez("runoob.npz", a, b, sin_array = c)r = np.load("runoob.npz")  print(r.files) # 查看各个数组名称print(r["arr_0"]) # 数组 aprint(r["arr_1"]) # 数组 bprint(r["sin_array"]) # 数组 c

[4] 使用文本文件存取数组

numpy 也支持以文本文件存取数据。savetxt() 函数是以简单的文本文件格式存储数据,对应的使用 loadtxt() 函数来获取数据。

应用示例:

a = np.array([1,2,3,4,5]) np.savetxt('out.txt',a) b = np.loadtxt('out.txt')  print(b)

5. 常用函数

(1) 舍入函数

[1] 四舍五入

numpy.around(a, decimals=0, out=None)

应用示例:

>>> np.around([-0.42, -1.68, 0.37, 1.64])array([-0., -2.,  0.,  2.])>>> np.around([-0.42, -1.68, 0.37, 1.64], decimals=1)array([-0.4, -1.7,  0.4,  1.6])>>> np.around([.5, 1.5, 2.5, 3.5, 4.5]) # rounds to nearest even valuearray([ 0.,  2.,  2.,  4.,  4.])

[2] 去尾和进一

numpy.floor(a)numpy.ceil(a)

应用示例:

>>> np.floor([-0.42, -1.68, 0.37, 1.64])array([-1., -2.,  0.,  1.])>>> np.ceil([-0.42, -1.68, 0.37, 1.64])array([-0., -1.,  1.,  2.])

(2) 数学函数

函数                                                  说明

numpy.deg2rad() / numpy.radians() 度转弧度

numpy.rad2deg() / numpy.degrees() 弧度转度

numpy.sin() 正弦函数

numpy.arcsin() 反正弦函数

numpy.cos() 余弦函数

numpy.arccos() 反余弦函数

numpy.tan() 正切函数

numpy.arctan() 反正切函数

numpy.hypot() 计算直角三角形斜边

numpy.square() 平方

numpy.sqrt() 开平方

numpy.power 乘方

numpy.exp() 指数

numpy.log() 对数

numpy.log2() 对数

numpy.log10() 对数

(3) 统计函数

函数 说明

numpy.sum(a[, axis, dtype, out, keepdims]) 按指定的轴求元素之和

numpy.nansum(a[, axis, dtype, out, keepdims]) 按指定的轴求元素之和,numpy.nan视为0

numpy.cumsum(a[, axis, dtype, out]) 按指定的轴求元素累进和

numpy.prod(a[, axis, dtype, out, keepdims]) 按指定的轴求元素之积

numpy.diff(a[, n, axis]) 返回相邻元素的差

numpy.ptp() 返回数组中元素最大值与最小值的差

numpy.var() 返回数组方差

numpy.std() 返回数组标准差

numpy.median() 返回数组元素的中位数

numpy.mean(a, axis=None, dtype=None, out=None, keepdims=) 返回所有元素的算数平均值

numpy.average() 根据权重数据,返回数据数组所有元素的夹权平均值

6. 牛刀小试

**例题 ** vertices 是若干三维空间随机点的集合,p 是三维空间的一点,找出 vertices 中距离 p 点最近的一个点,并计算它们的距离。

用 python 数组实现:

import mathvertices = [[3,4,5], [7,8,9], [4,9,3]] p = [2,7,4]d = list()for v in vertices:  d.append(math.sqrt(math.pow(v[0]-p[0], 2)+math.pow(v[1]-p[1], 2)+math.pow(v[2]-p[2], 2)))print(vertices[d.index(min(d))], min(d))

用 numpy 数组实现:

import numpy as npvertices = np.array([[3,4,5], [7,8,9], [4,9,3]])p = np.array([2,7,4])d = np.sqrt(np.sum(np.square((vertices-p)), axis=1))print(vertices[d.argmin()], d.min())

用随机方式生成1000个点,比较两种的方法的效率。

【本文作者】

许向武:山东远思信息科技有限公司CEO,网名牧码人(天元浪子),齐国土著,太公之后。少小离家,独闯江湖,后归隐于华不注山。素以敲击键盘为业,偶尔游戏于各网络对局室,擅长送财送分,深为众棋友所喜闻乐见。

推荐阅读

(点击标题可跳转阅读)

写给 python 程序员的 OpenGL 教程

Numpy 库准备放弃支持 Python 2

觉得本文对你有帮助?请分享给更多人

关注「Python开发者」加星标,提升Python技能

72bf0ee649de826a41c94fb399b495e7.png

好文章,我在看❤️

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/454586.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

android 编译luajit,Android 嵌入 LuaJIT 的曲折道路

相关链接:Windows 下编译 LuaJIT懒人与伸手党可以直接看最底部。为什么使用 LuaJITLua 官方版的编译嵌入相对简单,但是为什么要用 LuaJIT 呢?我所了解到的优势有:更高的运行效率。支持运行 Lua 编译后的机器码。虽然 Lua 也支持编…

运维自动化之使用PHP+MYSQL+SHELL打造私有监控系统(一)

前言 记得刚来这家公司的时候,我部门就我一个运维工程师,然后就是经理,刚开始公司平台什么监控都没有,在我与经理的努力下,先搭建nagioscacti监控平台,后来随着公司业务的增加,平台的功能与服务…

Redis Python

Python操作Redis 安装Python使用Redis的库 sudo pip install redis or sudo easy_install redis or 源码安装 详见:https://github.com/WoLpH/redis-py 1.1 操作模式 redis-py提供两个类Redis和StrictRedis用于实现Redis的命令,StrictRedis用于实现大…

js更新数组对象_7 种Vue 数据已更新而页面没有更新的情况及深化总结(收藏)

作者:前端1943链接:https://segmentfault.com/a/1190000022772025如果你发现你自己需要在 Vue 中做一次强制更新,99.9% 的情况,是你在某个地方做错了事。1. Vue 无法检测实例被创建时不存在于 data 中的 property原因:…

从P560小型机B181201B故障代码识别手把手详解

背景:生产小型机发生宕机事件,现场发现液晶面板存在B181201B代码,可是查看网络,未见有权威的参考文章,通过管理口登录HMC管理界面,发现错误代码B181201B,同时提示可能是电源故障,后登…

Python 之 线程

进程 之前我们已经了解了操作系统中进程的概念,程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程。程序和进程的区别就在于:程序是指令的集合,它是进程…

flymcu无法打开串口_西门子1200与其他PLC/组态软件无线串口通讯(自由口)

一、控制系统原理图1:控制系统原理二、硬件需求S7-1200 PLC目前有3种类型的CPU:1)S7-1211C CPU2)S7-1212C CPU3)S7-1214C CPU这三种类型的CPU都可以连接三个串口通信模版本例中使用的PLC硬件为:1)PM1207电源(6EP1 332-1SH71)2)S7-1214C(6ES7 214-1BE30-0…

收银管理系统怎样帮助商家很好地经营服装门店

收银管理系统对于服装门店的经营可以提供多方面的帮助,以下是一些具体的优势和功能: 1. 快速准确的收银:收银管理系统可以实现快速、准确的收银操作,通过条码扫描或手动输入商品信息,自动计算价格并生成收据。这样可以…

Python 之 进程

目录 理论知识 操作系统背景知识 进程 什么是进程 进程调度 进程的并行与并发 同步异步阻塞非阻塞 同步和异步 阻塞与非阻塞 同步/异步与阻塞/非阻塞 组合 进程的创建与结束 进程的创建 进程的结束 在python程序中的进程操作 multiprocess(multiproc…

metric learning -- 马氏距离与欧氏距离

一 基本概念 方差:(variance)是在概率论和统计方差衡量随机变量或一组数据时离散程度的度量。概率论中方差用来度量随机变量和其数学期望(即均值)之间的偏离程度。统计中的方差(样本方差)是每个…

深入理解 C# 协变和逆变

msdn 解释如下: “协变”是指能够使用与原始指定的派生类型相比,派生程度更大的类型。 “逆变”则是指能够使用派生程度更小的类型。 解释的很正确,大致就是这样,不过不够直白。 直白的理解: “协变”->”和谐的变”…

华为mate20能用鸿蒙吗,华为mate20可以用5g网络吗

华为mate20不可以用5g网络,它是4g手机在2018年上市,当时5g并没有开始流行,因此mate20是不支持5G的。不过在后来的2019年秋季,华为发布了mate20 x的5g版本,这也是mate20系列里唯一支持5G的,除此之外mate20、…

基本农田卫星地图查询_#重庆朝天门#谷歌百度腾讯高德“卫星地图”PK,谷歌更胜一筹...

截图自便民查询网,各家卫星地图PK,各有千秋~谷歌精确度最高:5m,来福士修建中,嘉陵江是绿的,长江是黄的。两江交汇处有一条分明的界线。谷歌 5m:20ft谷歌 50m:100ft谷歌 200m:500ft谷歌 300m:1000ft谷歌 500…

Python 第三方库之 Celery 分布式任务队列

一、Celery介绍和使用: Celery 是一个 基于python开发的分布式异步消息任务队列,通过它可以轻松的实现任务的异步处理, 如果你的业务场景中需要用到异步任务,就可以考虑使用celery, 举几个实例场景中可用的例子: 你想…

windows server 2008 (五)web服务器的搭建和部署

Windows server 2008 web服务器的搭建和部署相对于windows server 2003的IIS6来说,windows server 2008推出的IIS7.0为管理员提供了统一的web平台,为管理员和开发人员提供了一个一致的web解决方案。并针对安全方面做了改进,可以减少利用自定义…

改装摩托车

摩托车发动机就是将进入气缸中的燃料混合气点燃使其燃烧所产生的热能变为机械能,并由曲轴将动力通过传动机构传给摩托车后轮而变为车辆行驶动力的机械。发动机的进排气量和气流速是影响高转速(功率)输出的关键因素之一。 发动机工作时气流的路…

华为鸿蒙os logo,华为鸿蒙OS Logo曝光:Powered by HarmonyOS

IT之家 9 月 13 日消息 9 月 10 日,鸿蒙 OS 2.0 亮相华为开发者大会的主舞台上,华为常务董事、消费者业务 CEO 余承东表示,鸿蒙 OS 是首个真正为全场景时代打造的分布式操作系统,鸿蒙 OS 2.0 全面使能全场景生态。现在博主 勇气数…

python判断语句_详解Python判断语句的使用方法

本篇介绍Python判断语句的使用,主要讨论简单条件语句、多重条件语句和嵌套条件语句,在讲解的每个案例中都配有流程图和代码说明。通过本篇的学习,可以达成如下目标。 ● 掌握判断语句的使用规则 ● 判断语句流程图的画法 前面我们学习了Pytho…

js setTimeout 使用方法

在项目过程中遇到一些异步加载和其他js方法冲突的问题: 如图初始化的时候会加载“商户基本信息”,修改商户名称字段第二个页面也需要修改: function setSeqAndName(){var pritab2 $("#allTabs").tabs("getTab", 1).find("ifra…

机器学习算法之 logistic、Softmax 回归

逻辑回归本质是分类问题,而且是二分类问题,不属于回归,但是为什么又叫回归呢。我们可以这样理解,逻辑回归就是用回归的办法来做分类。它是在线性回归的基础上,通过Sigmoid函数进行了非线性转换,从而具有更强…