考研那年年末学习和梳理了numpy和matplotlib这两个模块,该文档主要就是基于那时的笔记,matplotlib没有时间重新整理了,见原始笔记(matplotlib初级教程、3D绘图、patches与path)
Numpy主要提供了同构(所有元素类型相同)多维(维度也被称为“轴”)数组对象ndarray
,具有矢量化运算能力,除了支持多维数组与矩阵运算,此外还针对数组运算提供大量的数学函数库
首先看看核心对象ndarray
的主要属性:
ndim
:轴的数量,即数组维数shape
:数组的形状,一个整数元组,长度即为数组维数,从左到右依次是每个维度的轴长,譬如一个n
行m
列的矩阵,其形状为(n,m)
,表示第0维(轴)的长度为n
、第1维(轴)的长度为m
dtype
:数组元素类型,如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.itemsize
size
:数组中的元素个数(可用于判断数组是否为空,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
为C
order
为C
'F' order
为F
order
为F
subok
:默认情况下将创建的数组强制转换为基类数组对象(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 | for i in range(5)) g=(i |
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 | 20210527) np.random.seed( |
形状重塑
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 | 1,2,3],[4,5,6]],(-1,)) np.reshape([[ |
需要注意的是,如果reshape()
的order
参数为C
,只有在a
为C-contiguous(a.flags['C_CONTIGUOUS']
为True
)时才会返回视图,否则返回深拷贝,反之,若order
为F
,则只有在a
为F-contiguous(a.flags['F_CONTIGUOUS']
为True
)时才会返回视图,否则返回深拷贝
1 | 1,2,3],[4,5,6]],order='F') a=np.array([[ |
np.resize(a, newshape)
函数说明:
作用同np.reshape()
,最大的区别在于np.resize()
返回的是一个完全独立的新数组,对其所做的一切修改不会影响原数组,且此时允许指定错误的或者说不匹配的newshape
,多余的部分会被丢弃,不足的部分则会复用已有的数据补全(描述能力有限,具体见示例),另外,虽然也可以直接在ndarray
对象上调用resize()
方法,但ndarray.resize(...)
是原址操作,无返回值(返回值为无意义的None
),此时newshape
形状元组中禁止使用代表缺省维数的-1
(np.resize(...)
虽然不直接报错,但是结果也不正确,也必须禁止),不匹配的newshape
则会导致错误
1 | 10) a=np.arange( |
np.swapaxes(a, axis1, axis2)
函数说明:
用于交换多维数组的某两个维度,函数返回原数组的“视图”,可以直接在ndarray
上调用ndarray.swapaxes(axis1,axis2)
1 | 1,2,3]]) x = np.array([[ |
以二维或三维数组为例,将其分别放到二维平面和三维空间坐标系中,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 | 0,1],[2,3]],[[4,5],[6,7]]]) x=np.array([[[ |
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 | 24).reshape(2,3,4) a=np.arange( |
ndarray.flatten(order='C')
函数说明:
用于“一维化”多维数组(降维),返回的是原数组的深拷贝
1 | 0,1,2],[3,4,5]]) a=np.array([[ |
np.expand_dims(a, axis)
函数说明:
该函数用于扩展数组a
的维度,一次只能增加一个维度,新增维度的轴长为1,函数将返回原数组的“视图”,比较常见的是扩充第一个或最后一个维度,但一般会用a[None,...]
或a[...,None]
简写达到同样的效果
1 | 6).reshape(2,-1) a=np.arange( |
np.squeeze(a, axis=None)
函数说明:
该函数默认用于删除多维数组a
中的所有轴长为1的维度(axis
为None
),函数将返回原数组的“视图”,也可以直接在ndarray
对象上调用该方法,也可以指定axis
参数,即删除指定的维度(但该维度的轴长必须为1)
1 | 24).reshape(2,3,4) a=np.arange( |
数组切片和索引
先说说(数值)索引,对数组(单个)元素的索引是通过数字下标进行定位的,譬如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 | list(range(10)) a= |
Numpy索引还支持一个特殊对象None
,之前在介绍np.expand_dims()
时顺带展示了相关用法,这里再简单回顾一下:
1 | 10).reshape((2,-1)) a=np.arange( |
数组元素迭代
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 | 1], [2], [3]]) x=np.array([[ |
1 | 1], [2], [3]]) x=np.array([[ |
np.broadcast_to(array, shape, subok=False)
函数说明:
用于将一个数组广播至一个指定的形状
1 | 1], [2], [3]]),(3,5)) np.broadcast_to(np.array([[ |
数组拼接与分割
数组增删改查
np.append(arr, values, axis=None)
函数说明:
用于沿指定轴axis
向数组中追加数据values
(多维数组对象),该操作基本同np.concatenate()
函数,要追加的子数组values
的形状和arr
的形状除axis
轴长度可以不一致外,其余轴长必须一致,另外当axis
置为None
时(默认值),会将一维化的arr
和values
连接成一个一维数组并返回
1 | 4).reshape(2,-1),np.arange(6).reshape(2,3),axis=1) np.append(np.arange( |
np.delete(arr, obj, axis=None)
函数说明:
用于沿指定轴axis
删除特定位置处的子数组。obj
参数可以是整数(指定要删除的刻度位置处的元素)、切片或整数列表(指定要删除的多个刻度对应位置处的元素),特别地,当axis
置为None
时(默认值),将会首先“展平”(一维化)arr
数组
1 | 1,2,3,4],[5,6,7,8],[9,10,11,12]]) arr=np.array([[ |
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 | 12).reshape(2,2,3) a=np.arange( |
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 | 6,7,6,6,5,2,9,8,2,5]).reshape(2,-1) a=np.array([ |
np.sort(a, axis=-1, kind='quicksort', order=None)
函数说明:
用于沿指定轴对输入数组进行排序。默认是沿着最后一个轴(axis=-1
)进行排序,如果axis
置为None
,则先一维化展平数组a
,然后再进行排序(最终将返回一个一维数组),kind
参数指定排序算法,还可取值mergesort
(归并排序)和heapsort
(堆排序),此处的order
参数并非有关内存布局,而是用于自定义结构化数据类型时,设置不同字段参与排序时的优先级(order
列表中字段的优先级从左至右依次降低),没有出现在order
的字段,其优先级低于order
中的字段,且按照定义结构化数据类型dtype
时的字段顺序依次降低
1 | 1,4],[3,1]]) a = np.array([[ |
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 | 0,24,12).reshape(3,-1) a=np.random.randint( |
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 | 24).reshape(2,3,4) a=np.arange( |
np.cumprod(a, axis=None, dtype=None, out=None)
函数说明:
计算数组或沿轴元素的累乘,当axis
为None
时,会先展平一维化数组,然后再计算累乘,所得也会是一个一维数组。可以直接在ndarray
对象上调用该方法
1 | 0,5,12).reshape(3,4) a=np.random.randint( |
np.nonzero(a)
函数说明:
用于返回数组a
中非零元素的下标索引(按坐标分量返回),根据此下标索引可以获取所有非零元素并以一维数组返回,若要直接返回数组中的非零元素,直接a[a!=0]
。该函数常用于查找条件为真的数组元素索引,譬如,给定数组a
,条件a>3
返回一个布尔数组,由于False
就是整数0(有False==0
成立),所以np.nonzero(a>3)
将返回符合条件的数组元素的下标索引。另外也可以直接在ndarray
对象上调用nonzero()
方法
1 | 0,24,12).reshape(3,-1) a=np.random.randint( |
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 | 0, 1],[1, 0]]) np.where([[ |
np.extract(condition, arr)
函数说明:
用于从数组a
中提取满足条件的元素。这不就是a[condition]
么
1 | 12).reshape((3, 4)) arr = np.arange( |
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 | 12).reshape(3, 4) arr = np.arange( |
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 | 3,4,5,2,1] #这里有五个数,使用np.sort()按升序排序得到:[1,2,3,4,5],记作s a=[ |
kth
为多个整数序列时:1 | a=[2,6,10,1,5,2,4,8,1,9,7,7,13] |
1 | 2,6,10,1,5,2,4,8,1,9,7,7,13] a=[ |
1 | 'name', 'S10'), ('height', float), ('age', int)] dtype = [( |
数学运算
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 | 0,10,3).reshape(3) a=np.random.randint( |
np.log(a)
函数说明:
逐元素的以e
为底的对数计算,满足log(exp(x)) = x
(以e
为底exp(x)
的对数就是x
),还有np.log2()
、np.log10()
,而基于其他底数的对数计算,通常可以采用换底公式转换为以10为底的对数(也就是ln
)计算:
1 | 12)) np.log(np.exp( |
np.sqrt(a)
函数说明:
逐元素计算平方根。要计算任意次方根,可以使用**
运算符,如a**(1/2)
、a**(1/3)
,其等同于调用np.power()
函数(或math
库中的pow()
),如np.power(a,1/2)
、np.power(a,1/3)
1 | 1,4,9]) np.sqrt([ |
np.mod(a,b)
函数说明:
逐元素的取模运算
1 | 8).reshape(2,4) a=np.arange( |
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 | 1,2,3]) f=np.poly1d([ |
[1] Numpy官方英文文档·用户手册
[2] Numpy中文网入门教程
[3] RUNOOB菜鸟教程 Numpy入门教程