考研那年年末学习和梳理了numpy和matplotlib这两个模块,该文档主要就是基于那时的笔记,matplotlib没有时间重新整理了,见原始笔记(matplotlib初级教程、3D绘图、patches与path)
Numpy主要提供了同构(所有元素类型相同)多维(维度也被称为“轴”)数组对象ndarray,具有矢量化运算能力,除了支持多维数组与矩阵运算,此外还针对数组运算提供大量的数学函数库
首先看看核心对象ndarray的主要属性:
ndim:轴的数量,即数组维数shape:数组的形状,一个整数元组,长度即为数组维数,从左到右依次是每个维度的轴长,譬如一个n行m列的矩阵,其形状为(n,m),表示第0维(轴)的长度为n、第1维(轴)的长度为mdtype:数组元素类型,如np.int32、np.int16和np.float64(np是numpy的缩写)flags:数组的内存布局信息real和imag:分别是数组的实部和虚部(即时非虚数类型也有这两个属性)itemsize:数组元素大小,以字节为单位,如元素为float64类型的数组itemsize为8(64/8,一个字节占8位),而complex32类型的数组itemsize为4(32/8),其等于ndarray.dtype.itemsizesize:数组中的元素个数(可用于判断数组是否为空,np.array([]).size=0)T:数组转置,仅针对二维数组(或矩阵matrix对象)strides:跨度元组,其中的整数是指为了前进到当前维度下一个元素需要“跨过”的字节数flat:数组的元素迭代器,返回一个flatiter对象,可以用作一维数组“视图”
创建数组
np.array(object, dtype=None, copy=True, order='K', subok=False, ndmin=0)
参数说明:
object:可以是python原生序列类型,如(嵌套)列表、(嵌套)元组等,也可以是ndarray类型及其子类,函数默认行为总是会返回object的(深)拷贝副本,两者占据完全不同的内存dtype:设置数组元素的数据类型,缺省时会根据object的类型自行确定copy:控制当object为ndarray类型或其子类matrix时是否进行(深)复制的行为,设为False,如果object是ndarray类型,将直接返回object自身(即满足is判断),如果object是matrix类型,则浅拷贝,修改任意一方都会体现在对方,且只有当subok置为True时才会返回object自身order:指定数组在内存中的布局,有两种不同的风格(C或Fortran),C为行主方向(譬如一个二维数组,在内存中依次存储数组的每一行),F为列主方向(譬如一个二维数组,在内存中依次存储数组的每一列),如果object非ndarray类型,可取值就是C(默认)或者F,否则,还可以取值A或K,所创建的数组order由以下规则确定:order copy=False copy=True 'K' 和 object的order一致F & C order preserved, otherwise most similar order(没懂) 'A' 和 object的order一致若 object的order为F且非C,则order为F,反之为C'C' order为Corder为C'F' order为Forder为Fsubok:默认情况下将创建的数组强制转换为基类数组对象(ndarray),设为True则返回子类(譬如矩阵类型matrix是ndarray的子类,m=np.matrix('1 2 3; 4 5 6');a=np.array(m,subok=True),type(a)为numpy.matrixlib.defmatrix.matrix,且issubclass(type(a),np.ndarray)为True)ndmin:设置最低维度,创建的多维数组至少是ndmin维(譬如object的形状为(2,3),而ndmin为4,则创建的数组形状为(1,1,2,3)),当object的维度大于此值时,则不管,维度同object
注(order参数),给定一个二维数组a=[[1,2,3],[4,5,6]],如果按照C顺序创建x=np.array(a,order='C'),此时默认的dtype为np.int32,x.itemsize为4,形状x.shape为(2,3),其在内存中的存储为:|1|2|3|4|5|6|(因为内存总是连续的),每个格子占据4字节大小,其跨度元组x.strides为(12,4),表示第0维前进到下一个元素需要“跨过”12个字节(如内存中1到4之间的距离),第1维前进到下一个元素需要“跨过”4个字节(如内存中1到2之间的距离),如果是按照F顺序创建y=np.array(a,order='F'),y.itemsize为4,形状y.shape为(2,3),其在内存中的存储为:|1|4|2|5|3|6|,其跨度元组y.strides为(4,8)
1 | import numpy as np |
np.asarray(a, dtype=None, order=None)
函数说明:
作用也是将输入a转换为一个ndarray对象,除了比np.array()少了很多控制参数,最大的区别是,当a是ndarray对象时,将返回自身,如果a是列表、元组等,则还是深拷贝,但当a是matrix对象,则浅拷贝,此时虽然不满足is判断,但是修改任意一方,都会体现在对方,换句话说,np.asarray()相当于np.array()的参数copy置为False时的版本
1 | import numpy as np |
np.fromiter(iterable, dtype, count=-1)
函数说明:
将一个一维的可迭代(序列)对象iterable转为一维数组并返回,如果(序列)元素也是序列,则只能自定义结构化数据类型,否则出错。注意参数dtype是必填参数,count参数用于决定读取序列的多少个元素,默认值-1表示全部读取。须知,np.array()仅能将array_like对象转换为ndarray,如列表等,如果是生成器等或其他自定义可迭代对象则无法转换
1 | g=(i for i in range(5)) |
np.fromfunction(function, shape, dtype=float)
函数说明:function函数可接受参数个数应等于shape形状元组的长度(假设shape长度为n,则表示function是一个n元函数),同时shape也是将要创建的数组的形状。以二维为例,shape=(m,n),则function是一个二元函数,创建的数组记作a,则有a[i,j]=function(i,j)。更一般的,对shape=(k1,k2,k3...kn)来说,fromfunction()将返回一个n维数组对象a,第i维的长度为ki,a[i1,i2,...,in]的值就是function(i1,i2,...,in)
1 | #(3,4)形二维数组位置坐标 |
如果希望能够重现生成的伪随机数,只需要设置相同的随机种子np.random.seed(seed)(参数seed是一个整数,范围限于),如:
1 | np.random.seed(20210527) |
形状重塑
np.reshape(a, newshape, order='C')
函数说明:
将多维数组a变形为newshape,一般是直接在ndarray对象上调用该方法,形式为ndarray.reshape(newshape,order='C')(此时既可以直接传递形状元组,也可以将其解包为多个位置参数传递), 需要注意的是,reshape()函数返回的新数组其实是原多维数组对象a的“视图”,所谓“视图”,即你对视图的修改将原封不动地反映在原始数据中,因此对reshape()函数返回的“新数组”的修改将影响到a(如果a是python对象自然不会影响),如果不希望变形操作影响原数组,则采用np.resize()替代,或者先进行一次深拷贝(np.copy())
参数说明:
a:除了是numpy多维数组对象,也可以是python列表newshape:设原始形状为(d1,d2,...,dn),newshape为(d1',d2',...,dn'),其必须满足d1d2...dn=d1'd2'...dn',且newshape形状元组中允许出现一个-1作为缺省,对应维度的轴长将被自动计算order:可取值为{'C', 'F', 'A'},按照指定风格从原数组中读取数据以及填充新数组,并将此风格设为新数组的内存布局
1 | np.reshape([[1,2,3],[4,5,6]],(-1,)) |
需要注意的是,如果reshape()的order参数为C,只有在a为C-contiguous(a.flags['C_CONTIGUOUS']为True)时才会返回视图,否则返回深拷贝,反之,若order为F,则只有在a为F-contiguous(a.flags['F_CONTIGUOUS']为True)时才会返回视图,否则返回深拷贝
1 | a=np.array([[1,2,3],[4,5,6]],order='F') |
np.resize(a, newshape)
函数说明:
作用同np.reshape(),最大的区别在于np.resize()返回的是一个完全独立的新数组,对其所做的一切修改不会影响原数组,且此时允许指定错误的或者说不匹配的newshape,多余的部分会被丢弃,不足的部分则会复用已有的数据补全(描述能力有限,具体见示例),另外,虽然也可以直接在ndarray对象上调用resize()方法,但ndarray.resize(...)是原址操作,无返回值(返回值为无意义的None),此时newshape形状元组中禁止使用代表缺省维数的-1(np.resize(...)虽然不直接报错,但是结果也不正确,也必须禁止),不匹配的newshape则会导致错误
1 | a=np.arange(10) |
np.swapaxes(a, axis1, axis2)
函数说明:
用于交换多维数组的某两个维度,函数返回原数组的“视图”,可以直接在ndarray上调用ndarray.swapaxes(axis1,axis2)
1 | x = np.array([[1,2,3]]) |
以二维或三维数组为例,将其分别放到二维平面和三维空间坐标系中,swapaxes()操作相当于交换某两个轴的名称
1 | import matplotlib.pyplot as plt |
np.transpose(a, axes=None)
函数说明:
区别于np.swapaxes()只能一次性交换两个维度,该操作用于同时变换n个轴的名称(n≤a.ndim),axes即是一个长度为a.ndim的元组,里面是要转换的维度序号,当其为None时,相当于np.transpose(a,axes=list(reversed(range(len(a.shape))))),此时可以用于二维数组的转置操作,函数返回的是原数组的“视图”(ndarray对象的T属性返回的也是“视图”),也可以直接在ndarray上调用ndarray.transpose(axes=None)。另外轴变换后得到的数组内存布局将会发生变化,譬如一个二维的列主序数组,transpose后会变成行主序
1 | x=np.array([[[0,1],[2,3]],[[4,5],[6,7]]]) |
np.rollaxis(a, axis, start=0)
函数说明:
向前或向后滚动特定的轴axis到一个特定位置start,在滚动过程中,其它轴的相对位置不会改变,默认是将某根轴向前滚动到位置0,即变成轴0,向前滚动时要滚动到位置几就将start置为几即可,譬如将轴2滚动到轴1位置处,即为np.rollaxis(a,2,1),但是向后滚动时需要人为加1,譬如一个三维数组,要将轴0滚动到原本的轴2位置处,应当是np.rollaxis(a,0,3)而非np.rollaxis(a,0,2),函数返回的仍是“视图”,但是ndarray对象上并无rollaxis()方法属性
1 | a=np.arange(24).reshape(2,3,4) |
ndarray.flatten(order='C')
函数说明:
用于“一维化”多维数组(降维),返回的是原数组的深拷贝
1 | a=np.array([[0,1,2],[3,4,5]]) |
np.expand_dims(a, axis)
函数说明:
该函数用于扩展数组a的维度,一次只能增加一个维度,新增维度的轴长为1,函数将返回原数组的“视图”,比较常见的是扩充第一个或最后一个维度,但一般会用a[None,...]或a[...,None]简写达到同样的效果
1 | a=np.arange(6).reshape(2,-1) |
np.squeeze(a, axis=None)
函数说明:
该函数默认用于删除多维数组a中的所有轴长为1的维度(axis为None),函数将返回原数组的“视图”,也可以直接在ndarray对象上调用该方法,也可以指定axis参数,即删除指定的维度(但该维度的轴长必须为1)
1 | a=np.arange(24).reshape(2,3,4) |
数组切片和索引
先说说(数值)索引,对数组(单个)元素的索引是通过数字下标进行定位的,譬如a[i][j]表示沿着数组a的第0轴获取第i个位置上的元素,记作b=a[i],然后再沿着数组b的第0轴获取第j个位置上的元素,就得到a[i][j],简写形式为a[i,j],其中逗号用于分隔不同的维度(事实上,不管是此处的数值索引还是后面的切片索引,对于不足的维度说明,譬如a[i]就是只给出了第0维的索引说明,总是会自动在最后使用...对其他维度的索引说明进行补全,譬如a[i]即等同于a[i,...],...含义后面会说),而切片索引可以同时访问多个元素,有两种使用方式(同原生python),一是创建切片对象slice(start,end,stride)(切片范围不包括end在内),二是使用冒号语法start:end:stride(同样切片范围不包括end在内)替代slice对象,譬如a[i:j],同样,可以使用逗号作为不同维度的间隔,譬如a[i:j,i:j]表示沿着数组a的第0轴获取第i个位置到第j个位置之前的所有元素,记作b=a[i:j],然后再沿着数组b的第1轴获取第i个位置到第j个位置之前的所有元素,即b[:,i:j],要知道每进行一次数值索引,返回的数组维数都会减一,而切片索引的返回结果则始终保持维数不变(许多numpy函数都有一个叫做keepdims的参数,就是这个意思),因此上面a[i][j]的描述也可以改成:首先沿着数组a的第0轴获取第i个位置上的元素且保持维数不变,即得到b=a[i:i+1],然后再沿着数组b的第1轴获取第j个位置上的元素且保持维数不变,即b[:,j:j+1],所得相当于[[a[i,j]]],数值索引和切片索引自然可以混用,譬如a[:,i](表示获取数组a的第i列),另外,numpy索引还支持...(ellipse对象,须知其在索引中只能出现一次,原生python索引不支持)用于替代一个或多个(逗号间隔且连续的):,譬如a[i:j,:,:]可以替换成a[i:j,...]、a[:,:,i:j]可以替换成a[...,i:j]、a[:]可以替换成a[...]、a[:,i]可以替换成a[...,i]
1 | a=list(range(10)) |
Numpy索引还支持一个特殊对象None,之前在介绍np.expand_dims()时顺带展示了相关用法,这里再简单回顾一下:
1 | a=np.arange(10).reshape((2,-1)) |
数组元素迭代
np.nditer(a, order, flags, op_flags, ...)
函数说明:
对一个多维数组使用for循环迭代只能遍历第0维上的元素,要迭代所有元素,需使用flatten()等函数展平(一维化)数组,并且可以指定访问风格,行主序或列主序,numpy为我们提供了一个专门的函数nditer(),通过该函数将创建一个在多维数组上的元素迭代器
参数说明(部分):
order:指定数组元素的迭代风格,行主序或列主序flags参数(部分)可取值(一个字符串序列,可以同时指定以下多个值):c_index:表示跟踪C顺序的索引(从0开始计数),索引值通过函数返回的迭代器的index属性获取,即便实际是以F风格(order参数)迭代数组元素,给出的也是C风格索引。注意c_index和f_index两者只能取其一f_index:表示跟踪F顺序的索引,同上multi_index:表示跟踪迭代元素的全(位置)坐标,通过函数返回的迭代器的multi_index属性获取external_loop(没懂):其将多维数组a视为由诸多一维数组元素构成的数组,若指定order='F',那么迭代次数将为reduce(lambda x,y:x*y,a.shape[1:]),此时第0维上的向量被视为单个元素,若指定order='C',那么迭代次数将为1,访问的元素就是np.flatten(a),一个一维数组,这有何用?
op_flags:默认取值readonly,即视待遍历的数组为只读对象,为了在遍历数组的同时实现对数组元素值的修改,需指定为readwrite或writeonly
1 | import numpy as np |
并行迭代,如果两个数组是同形的(弱化条件为两者可以广播至同一形状),那么nditer()能够同时迭代它们:
1 | import numpy as np |
该属性返回多维数组的元素迭代器(一个flatiter对象,由于是迭代器对象,用完即弃),遵循C风格,也可以作为一个一维数组“视图”使用,支持切片索引、花式索引等,flatiter对象上有一个copy()方法将其转为(一维的)ndarray对象(深拷贝),其还有三个主要属性:
base:返回flatiter对象的原始数组引用index:返回当前迭代元素的索引(从0开始计数)coords:返回当前迭代元素在原数组中的全坐标
1 | import numpy as np |
上述输出不正确,这里不建议通过for循环的方式去获取索引或坐标,因为flatiter只有调用一次__next__()方法后才能获取到(第一个)迭代元素,而调用后其index和coords属性又会立即更新(变成第二个迭代元素的索引和坐标),因此必须在next()前获取index和coords,for循环无法控制next()调用的时机,因此可以通过while方式并手动调用next()迭代元素:
1 | import numpy as np |
ndarray.flat本身也可以作为展平后的一维数组“视图”使用:
1 | import numpy as np |
广播机制
广播机制是处理不同维度数组间操作的一个非常重要的手段,要知道两个不同的多维数组能够进行操作的基本条件是其形状相同,当形状不同时,但符合广播的条件,则会自动对这两个或其中一个多维数组进行维度补齐并进行元素复制(补齐维数)
广播的规则:
- 让所有输入数组都向其中维数最大(
shape最长)的数组看齐,shape中不足的部分在前面加1补齐维度 - 输出数组的
shape根据所有输入数组shape的各个轴上的最大值得到 - 如果输入数组的某个轴和输出数组的对应轴的长度相同或者不同但其中一方长度为1时,这些输入数组被认为能够广播至输出数组的形状,即符合广播的条件,否则抛出异常
- 当输入数组的某个轴的长度为1且输出数组对应轴长大于1时,将沿着此轴复制第一个元素来进一步补齐维数
1 | a=np.arange(24).reshape((2,3,4)) |
np.broadcast(*arrs)
函数说明:
函数可以接受任意数量(设为n)的输入数组,并产生基于这些输入数组的“广播对象”作为函数返回值,这个广播对象有一些属性和方法,其中shape和ndim(或nd)分别获取经广播机制作用后的输出数组的形状和维数,而iters属性返回一个长度为n(数量可由numiter属性获取)的由诸多flatiter对象构成的元组,这些flatiter(用完即弃)分别代表那些输入数组经广播(维度补齐和元素复制)后的数据内容,此外,广播对象本身也是一个迭代器(用完即弃),相当于并行迭代前面的flatiter对象,为了复用广播对象,其有一个reset()方法能够重置初始的迭代状态
1 | x=np.array([[1], [2], [3]]) |
1 | x=np.array([[1], [2], [3]]) |
np.broadcast_to(array, shape, subok=False)
函数说明:
用于将一个数组广播至一个指定的形状
1 | np.broadcast_to(np.array([[1], [2], [3]]),(3,5)) |
数组拼接与分割
数组增删改查
np.append(arr, values, axis=None)
函数说明:
用于沿指定轴axis向数组中追加数据values(多维数组对象),该操作基本同np.concatenate()函数,要追加的子数组values的形状和arr的形状除axis轴长度可以不一致外,其余轴长必须一致,另外当axis置为None时(默认值),会将一维化的arr和values连接成一个一维数组并返回
1 | np.append(np.arange(4).reshape(2,-1),np.arange(6).reshape(2,3),axis=1) |
np.delete(arr, obj, axis=None)
函数说明:
用于沿指定轴axis删除特定位置处的子数组。obj参数可以是整数(指定要删除的刻度位置处的元素)、切片或整数列表(指定要删除的多个刻度对应位置处的元素),特别地,当axis置为None时(默认值),将会首先“展平”(一维化)arr数组
1 | arr=np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]]) |
np.insert(arr, obj, values, axis=None)
函数说明:
此操作类似于np.append(),可以认为append()是insert()的一个特例(在末尾插入子数组),参数obj可以是整数(在指定刻度位置处插入子数组values)、切片对象或整数列表(在指定的多个刻度位置处插入子数组values),具体的,当obj为切片或整数列表时,values的形状和arr的形状除了满足“除axis所在轴长度可以不一致外其余轴长必须相同”的条件外(基本原则),还需要满足“values的axis所在轴长要么是1,要么是切片或整数列表的长度”的条件,当obj为整数时,values的形状除了需要满足基本原则,还需要满足“values的axis所在轴长必须为1”的条件,最后还要删除这个多余的长度为1的axis维(squeeze()),当obj为单整数序列时,values的形状只需要满足基本原则即可。特别地,axis参数可以为None时(默认值),表示会将arr一维化展开,其余的,正常按照前述规则,就像在一维数组中插入数据一样
1 | a=np.arange(12).reshape(2,2,3) |
np.unique(arr, return_index=False, return_inverse=False, return_counts=False, axis=None)
函数说明:
用于去除数组arr中的重复元素,返回以升序排序的去重值数组(由于axis默认为None,因此会首先一维化arr,并最终返回一个去重的一维数组)
参数说明:
axis:沿axis轴对数组元素进行去重,举个例子,当arr为二维数组,axis为1,表示要去重的元素是二维数组中的列向量,反之,axis为0,表示要去重的元素是二维数组中的行向量。axis置为None时,表示将arr一维化return_index:若为True,同时返回去重数组中元素在原始数组中的位置下标return_inverse:若为True,同时返回原始数组中元素在去重数组中的位置下标return_counts:若为True,同时返回去重数组中元素在原始数组中出现的次数
1 | a=np.array([6,7,6,6,5,2,9,8,2,5]).reshape(2,-1) |
np.sort(a, axis=-1, kind='quicksort', order=None)
函数说明:
用于沿指定轴对输入数组进行排序。默认是沿着最后一个轴(axis=-1)进行排序,如果axis置为None,则先一维化展平数组a,然后再进行排序(最终将返回一个一维数组),kind参数指定排序算法,还可取值mergesort(归并排序)和heapsort(堆排序),此处的order参数并非有关内存布局,而是用于自定义结构化数据类型时,设置不同字段参与排序时的优先级(order列表中字段的优先级从左至右依次降低),没有出现在order的字段,其优先级低于order中的字段,且按照定义结构化数据类型dtype时的字段顺序依次降低
1 | a = np.array([[1,4],[3,1]]) |
np.max(a, axis=None, out=None, keepdims=False)
函数说明:
该操作返回数组的最大值(axis=None的默认行为)或者沿轴的最大值(结果数组的维数可能会减1,以(m,n)形二维数组为例,若沿0轴获取最大值,即获取数组中每个列向量中的最大值,所得结果数组形状将变为(n,),除非keepdims设为True,此时结果数组维数将变为(1,n),仍为二维),另外也可以直接在ndarray对象上调用该方法。out参数用于存放结果数组,keepdims参数表示是否维持数组的维数不变。实际上,axis还可以是一个元组,以(m,n,q)形三维数组为例说明,若沿着axis=(0,1)获取最大值,即获取数组中(沿2轴的)每个“面”中的最大值,所得结果数组形状将变为(q,),除非keepdims为True,此时结果数组维数将变为(1,1,q),仍保持三维。最后提醒一下,np.max()还可以写成np.amax(),两个函数就是一回事
1 | a=np.random.randint(0,24,12).reshape(3,-1) |
np.min(axis=None, out=None, keepdims=False)
函数说明:
等同于函数np.amin(),具体参见np.max(),只不过一个求最大一个求最小而已
np.sum(a, axis=None, dtype=None, out=None, keepdims=False)
函数说明:
求和运算,类似于np.max()、np.min(),都是“聚合”操作,参数含义也都一样,就不多说了。可以直接在ndarray对象上调用该方法
1 | a=np.arange(24).reshape(2,3,4) |
np.cumprod(a, axis=None, dtype=None, out=None)
函数说明:
计算数组或沿轴元素的累乘,当axis为None时,会先展平一维化数组,然后再计算累乘,所得也会是一个一维数组。可以直接在ndarray对象上调用该方法
1 | a=np.random.randint(0,5,12).reshape(3,4) |
np.nonzero(a)
函数说明:
用于返回数组a中非零元素的下标索引(按坐标分量返回),根据此下标索引可以获取所有非零元素并以一维数组返回,若要直接返回数组中的非零元素,直接a[a!=0]。该函数常用于查找条件为真的数组元素索引,譬如,给定数组a,条件a>3返回一个布尔数组,由于False就是整数0(有False==0成立),所以np.nonzero(a>3)将返回符合条件的数组元素的下标索引。另外也可以直接在ndarray对象上调用nonzero()方法
1 | a=np.random.randint(0,24,12).reshape(3,-1) |
np.where(condition, [x, y])
函数说明:
分两种情况(其中condition将返回一个布尔数组):
np.where(condition):此时等同于condition.nonzero()np.where(condition,x,y):首先创建一个空的结果数组,形状同condition,如果condition某个位置的元素为True,表示符合条件,则从x中对应位置处取出元素并放到结果数组中的相应位置,如果condition某个位置的元素为False,表示不符合条件,则从y中对应位置处取出元素并放到结果数组中的相应位置。并不要求x、y和condition的形状完全一致,但是其应能广播至同一形状
1 | np.where([[0, 1],[1, 0]]) |
np.extract(condition, arr)
函数说明:
用于从数组a中提取满足条件的元素。这不就是a[condition]么
1 | arr = np.arange(12).reshape((3, 4)) |
np.place(arr, mask, vals)
函数说明:
将数组arr中满足条件mask(掩码数组)的元素用数据vals进行替换(原址操作)。这不就是arr[mask]=vals么。注意vals参数是一个一维数组或一维序列,指定用于替换的元素,设其长度为N,而符合条件的元素个数记为M,若N>M,则将只使用vals序列的前M个元素用于替换,若N<=M,则将循环重复使用这个序列的元素,譬如vals=[1,2,3],且符合条件的元素有5个,则用于替换的元素为:[1,2,3,1,2]
1 | arr = np.arange(12).reshape(3, 4) |
np.partition(a, kth, axis=-1, kind='introselect', order=None)
函数说明:
指定一个或多个数,对数组进行分区。这玩意儿常用来求序列的第k项最大(小)值,特别是前几项最大(小)值,效率较高,因为它不对分区元素排序
参数说明:
kth:可以是单个整数,也可以是多个整数的序列,单个整数值时,kth表示第k个元素,k是指按升序排序后的数组(记作s,参数axis决定了具体沿哪个轴进行排序)的下标索引,axis所在轴长也就是kth参数的合法取值(实际取值区间为[-len(arr),len(arr)-1],负数索引譬如-1表示的是最后一个元素的索引,这里姑且假设axis取0,于是0轴长度就是len(arr)),函数的功能是将原数组中小于s[k]的元素放到(s[k]的)左边区域,将大于或等于s[k]的元素放到(s[k]的)右边区域,但分区区域中元素并无顺序。显而易见的是,由于第k个元素指的是排序后的数组(s)的第k个元素,因此s本身就是一个符合条件的函数返回值,因为s[k]左边的元素的确都比s[k]小,s[k]右边的元素的确都比s[k]大或等啊。当kth参数是多值序列时(设为[k0,k1,,k2,...]),序列中的每一个整数都要在“合法取值”内,只需记住:作为函数返回值的数组的第k0、k1、k2、…个元素就是按升序排列后的数组的第k0、k1、k2、…个元素,将这些元素视为一个一个的分界点,左边的数总是小于它,右边的数总是大于等于它axis:指定要排序的轴,缺省为-1,表示沿最后一根轴排序,若指定为None,则首先将数组“展平”为一维,然后再排序,同np.sort()order:非内存布局,而是用于自定义结构化数据类型时,指定字段排序优先级,仍同np.sort()
kth为整数时:1 | a=[3,4,5,2,1] #这里有五个数,使用np.sort()按升序排序得到:[1,2,3,4,5],记作s |
kth为多个整数序列时:1 | a=[2,6,10,1,5,2,4,8,1,9,7,7,13] |
1 | a=[2,6,10,1,5,2,4,8,1,9,7,7,13] |
1 | dtype = [('name', 'S10'), ('height', float), ('age', int)] |
数学运算
np.dot(a, b, out=None)
函数说明:
矩阵乘法(可以在ndarray对象上直接调用该方法),等同于np.matmul(a,b)或使用@运算符:a @ b,注意区别于np.multiply()方法,这是用于两个数组之间的逐元素乘法操作,对应运算符*,即a * b
a和b都是标量,表示数值间的普通乘法a和b都是一维时,表示计算这两个向量的内积a和b都是二维或其中一个允许是一维,表示矩阵乘法a是N维(N>2)而b是一维,则结果是a和b的最后一个轴上元素的和积,因此需满足条件:a和b最后一个轴的长度相同,等同于:reduce(lambda last,now:last+now[0]*now[1],zip(np.rollaxis(a,a.ndim-1),b),0),结果数组形状为a.shape[:-1]a是N维(N>2)而b是M维(M>=2),则结果是a的最后一个轴和b的倒数第二个轴上元素的和积,需满足条件:a的最后一个轴长等于b的倒数第二个轴长,且有:dot(a, b)[i,j,k,m] = sum(a[i,j,:] * b[k,:,m]),这条没看懂
1 | a=np.random.randint(0,10,3).reshape(3) |
np.log(a)
函数说明:
逐元素的以e为底的对数计算,满足log(exp(x)) = x(以e为底exp(x)的对数就是x),还有np.log2()、np.log10(),而基于其他底数的对数计算,通常可以采用换底公式转换为以10为底的对数(也就是ln)计算:
1 | np.log(np.exp(12)) |
np.sqrt(a)
函数说明:
逐元素计算平方根。要计算任意次方根,可以使用**运算符,如a**(1/2)、a**(1/3),其等同于调用np.power()函数(或math库中的pow()),如np.power(a,1/2)、np.power(a,1/3)
1 | np.sqrt([1,4,9]) |
np.mod(a,b)
函数说明:
逐元素的取模运算
1 | a=np.arange(8).reshape(2,4) |
np.poly1d(c_or_r, r=False, variable='x')
函数说明:
用于创建一个一元多项式函数,有两种模式,一是r为False(默认),此时c_or_r指定多项式的系数,譬如c_or_r=[1,2,3],创建的多项式函数为,二是r为True,此时c_or_r指定多项式的根,仍以c_or_r=[1,2,3]为例,创建的多项式函数为,实际poly1d是一个类,若返回的类实例记作f=np.poly1d([1,2,3]),可以直接用()调用之(f()),返回多项式的具体值,variable参数指定未知变量字母,控制多项式函数的打印结果,默认为'x',f有一些属性,r属性返回多项式的根,c属性返回多项式的系数数组,order属性返回多项式的最高次方,f可以用[i]进行索引,获取的系数,f还有两个方法,deriv([m])表示求导,可选的参数m表示求几次导,默认求一次导,返回的仍是一个多项式函数,integ([m,k])表示求积分,可选的参数m表示积几次分,k表示积分后的常数项的值
1 | f=np.poly1d([1,2,3]) |
[1] Numpy官方英文文档·用户手册
[2] Numpy中文网入门教程
[3] RUNOOB菜鸟教程 Numpy入门教程




