Numpy基础知识体系
目录
数组属性
NumPy 数组的维数称为秩(rank),秩就是轴的数量,即数组的维度。
在 NumPy中,每一个线性的数组称为是一个轴(axis),也就是维度(dimensions)。比如说,二维数组相当于是两个一维数组,其中第一个一维数组中每个元素又是一个一维数组。所以一维数组就是 NumPy 中的轴(axis),第一个轴相当于是底层数组,第二个轴是底层数组里的数组。而轴的数量——秩,就是数组的维数。
很多时候可以声明 axis。axis=0,表示沿着第 0 轴进行操作,即对每一列进行操作;axis=1,表示沿着第1轴进行操作,即对每一行进行操作。
属性 | 说明 |
---|---|
ndarray.ndim | 秩,即轴的数量或维度的数量 |
ndarray.shape | 数组的维度,对于矩阵,n 行 m 列 |
ndarray.size | 数组元素的总个数,相当于 .shape 中 n*m 的值 |
ndarray.dtype | ndarray 对象的元素类型 |
ndarray.itemsize | ndarray 对象中每个元素的大小,以字节为单位 |
ndarray.flags | ndarray 对象的内存信息 |
ndarray.real | ndarray元素的实部 |
ndarray.imag | ndarray 元素的虚部 |
ndarray.data | 包含实际数组元素的缓冲区,由于一般通过数组的索引获取元素,所以通常不需要使用这个属性。 |
创建数组
#未初始化
numpy.empty(shape, dtype = float, order = 'C')
#初始化为0
numpy.zeros(shape, dtype = float, order = 'C')
#初始化为1
numpy.ones(shape, dtype = None, order = 'C')
参数 | 描述 |
---|---|
shape | 数组形状 |
dtype | 数据类型,可选 |
order | 有"C"和"F"两个选项,分别代表,行优先和列优先,在计算机内存中的存储元素的顺序。 |
从数值范围创建数组
numpy.arange(start, stop, step, dtype)
#起始值,终止值,步长,返回的数据类型
#生成0~5的数组
x = np.arrange(5)
#numpy.linspace 函数用于创建一个一维数组,数组是一个等差数列构成的
np.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)
#num未生成的样本数量(保证等步长) endpoint为fasle是数列中不包含stop
#retstep为true时,生成的数组中会显示间距
#numpy.logspace 函数用于创建一个于等比数列
np.logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None)
#base为log的底数
a = np.logspace(0,9,10,base=2)
print (a)
#[ 1. 2. 4. 8. 16. 32. 64. 128. 256. 512.]
索引
a = np.arange(10)
s = slice(2, 7, 2) #从索引2开始到索引7前,步长为2
ic(a[s])
ic(a[2:7:2])#可以用冒号间隔三个参数start、stop、step
ic(a[2:])#表示2后所有的元素
x = np.array([[1, 2], [3, 4], [5, 6]])
#获取(0,0) (1,1) (2,0)位置的元素
y = x[[0, 1, 2], [0, 1, 0]]
#得到结果
[1, 4, 5]
x = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]])
print("数组为:", x)
print('\n')
# index = np.array([0, 0, 3, 3], [0, 2, 0, 2])不可以这么写
ic(x[[0, 0, 3, 3], [0, 2, 0, 2]]) #产生一个列表
rows = np.array([[0, 0], [3, 3]])
cols = np.array([[0, 2], [0, 2]])
ic(x[rows, cols]) #产生2行2列的矩阵
#结果
x[[0, 0, 3, 3], [0, 2, 0, 2]]: array([ 0, 2, 9, 11])
x[rows, cols]: array([[ 0, 2],
[ 9, 11]])
a = np.array([[1,2,3], [4,5,6],[7,8,9]])
ic(a[1:3, 1:3])
ic(a[1:3, [1, 2]]) #注意这里1:3和[1, 2]功能相同
ic(a[:, 1:])
ic(a[..., 1:]) #...和:作用相似
#得到结果为:
#ic| a[1:3, 1:3]: array([[5, 6],
# [8, 9]])
#ic| a[1:3, [1, 2]]: array([[5, 6],
# [8, 9]])
#ic| a[:, 1:]: array([[2, 3],
# [5, 6],
# [8, 9]])
#ic| a[..., 1:]: array([[2, 3],
# [5, 6],
# [8, 9]])
布尔索引(筛选得到特定的值)
x = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]])
ic(x)
ic(x[x > 5])
#ic| x: array([[ 0, 1, 2],
# [ 3, 4, 5],
# [ 6, 7, 8],
# [ 9, 10, 11]])
#ic| x[x > 5]: array([ 6, 7, 8, 9, 10, 11])
#利用取反运算符~
a = np.array([np.nan, 1, 2, np.nan, 3, 4, 5])
ic(a[~np.isnan(a)])
#array([1., 2., 3., 4., 5.])
花式索引
利用整数数组进行索引,每个数值作为目标数组的某个轴的下表来取值,
x = np.arange(32).reshape((8, 4))
y = np.arange(8)
index = [4, 3, 2, 1]
ic(x)
ic(y)
ic(x[index])#对二维数组进行一维索引 返回的是每一行的内容
ic(y[index])#对一维数组进行一维索引,返回的是对应每个元素
#x[index]: array([[16, 17, 18, 19],
# [12, 13, 14, 15],
# [ 8, 9, 10, 11],
# [ 4, 5, 6, 7]])
#y[index]: array([4, 3, 2, 1])
传入多个索引数组需要使用np.ix_
x=np.arange(32).reshape((8,4))
print (x[np.ix_([1,5,7,2],[0,3,1,2])])
#[[ 4 7 5 6]
#[20 23 21 22]
#[28 31 29 30]
#[ 8 11 9 10]]
广播
广播(Broadcast)是 numpy 对不同形状(shape)的数组进行数值计算的方式, 对数组的算术运算通常在相应的元素上进行。
如果两个数组 a 和 b 形状相同,即满足 a.shape == b.shape,那么 a*b 的结果就是 a 与 b 数组对应位相乘。这要求维数相同,且各维度的长度相同。
当运算中的 2 个数组的形状不同时,numpy 将自动触发广播机制。
a = np.array([[0, 0, 0],
[10, 10, 10],
[20, 20, 20],
[30, 30, 30]])
b = np.array([1, 2, 3])
#当运算中的 2 个数组的形状不同时,numpy 将自动触发广播机制
ic(a + b) #将a的每一行都与b这个一维数组相加,a和b的列数相同,行数不同且只有一行
#a + b: array([[ 1, 2, 3],
# [11, 12, 13],
# [21, 22, 23],
# [31, 32, 33]])
上述广播机制隐含进行了np.tile()的操作
#隐含了操作np.tile(b, (4, 1))
bb = np.tile(b, (4, 1))
ic(bb)
#bb: array([[1, 2, 3],
# [1, 2, 3],
# [1, 2, 3],
# [1, 2, 3]])
广播的规则:
- 让所有输入数组都向其中形状最长的数组看齐,形状中不足的部分都通过在前面加 1 补齐。
- 输出数组的形状是输入数组形状的各个维度上的最大值。
- 如果输入数组的某个维度和输出数组的对应维度的长度相同或者其长度为 1 时,这个数组能够用来计算,否则出错。
- 当输入数组的某个维度的长度为 1 时,沿着此维度运算时都用此维度上的第一组值。
**简单理解:**对两个数组,分别比较他们的每一个维度(若其中一个数组没有当前维度则忽略),满足:
- 数组拥有相同形状。
- 当前维度的值相等。
- 当前维度的值有一个是 1。
总结:两个数组从尾部索引开始比较要么相等要么其中之一为零
例1: (4, 4, 3)和 (1, 3) 可以使用广播机制因为(1, 3)可以被看作(1, 1, 3)从尾部索引开始,3相等,其余为1,那么(1,3)就会根据(4,4, 3)的前两维对自己进行维度的扩充(仅进行复制操作),然后再进行计算
例2: (3, 3, 4)和(1, 3)不可以使用广播机制,因为(1, 3)的尾部索引与4不等。
迭代数组
基础迭代
迭代器对象 numpy.nditer 提供了一种灵活访问一个或者多个数组元素的方式。
a = np.arange(12).reshape(3, 4)
ic(a)
for x in np.nditer(a):
print(x, end=', ')
#得到0 1 2 3 4 5 6 7 8 9 10 11
以上实例不是使用标准 C 或者 Fortran 顺序,选择的顺序是和数组内存布局一致的,这样做是为了提升访问的效率,默认是行序优先(row-major order,或者说是 C-order)。
这反映了默认情况下只需访问每个元素,而无需考虑其特定顺序。我们可以通过迭代上述数组的转置来看到这一点,并与以 C 顺序访问数组转置的 copy 方式做对比,如下实例:
a = np.arange(6).reshape(2,3)
for x in np.nditer(a.T):
print (x, end=", " )
print ('\n')
for x in np.nditer(a.T.copy(order='C')):
print (x, end=", " )
print ('\n')
#0, 1, 2, 3, 4, 5,
#0, 3, 1, 4, 2, 5,
从上述例子可以看出,a 和 a.T 的遍历顺序是一样的,也就是他们在内存中的存储顺序也是一样的,但是 a.T.copy(order = ‘C’) 的遍历结果是不同的,那是因为它和前两种的存储方式是不一样的,默认是按行访问。
控制遍历顺序
for x in np.nditer(a, order='F'):
Fortran order,即是列序优先;for x in np.nditer(a.T, order='C'):
C order,即是行序优先;
#控制遍历顺序
ic(a.T)
c = a.T.copy(order='C') #C按行,F按列存储元素
ic(c)
for x in np.nditer(c):
print(x, end=' ')
print('\n')
c = a.T.copy(order='F')
ic(c)
for x in np.nditer(c):
print(x, end=' ')
print('\n')
#强制使用某种风格进行排序
print('强制使用F')
for x in np.nditer(a, order= 'F'):
print(x, end=' ')
修改元素中的值
nditer 对象有另一个可选参数 op_flags。 默认情况下,nditer 将视待迭代遍历的数组为只读对象(read-only),为了在遍历数组的同时,实现对数组元素值得修改,必须指定 read-write 或者 write-only 的模式。
#修改元素中的值
a = np.arange(0, 60, 5).reshape(3, 4)
ic(a)
for x in np.nditer(a, op_flags=['readwrite']):
x[...] = 2 * x #也可以用...
ic(a)
#ic| a: array([[ 0, 5, 10, 15],
# [20, 25, 30, 35],
# [40, 45, 50, 55]])
#ic| a: array([[ 0, 10, 20, 30],
# [ 40, 50, 60, 70],
# [ 80, 90, 100, 110]])
使用外部循环
nditer 类的构造器拥有 flags 参数,它可以接受下列值:
参数 | 描述 |
---|---|
c_index | 可以跟踪 C 顺序的索引 |
f_index | 可以跟踪 Fortran 顺序的索引 |
multi_index | 每次迭代可以跟踪一种索引类型 |
external_loop | 给出的值是具有多个值的一维数组,而不是零维数组 |
在下面的实例中,迭代器遍历对应于每列,并组合为一维数组:
for x in np.nditer(a, flags=['external_loop'], order='F'): #按列每次取出来一个列表
print(x, end=' ')
#[ 0 40 80] [10 50 90] [ 20 60 100] [ 30 70 110]
广播迭代
如果两个数组是可广播的,nditer 组合对象能够同时迭代它们。 假设数组 a 的维度为 3X4,数组 b 的维度为 1X4 ,则使用以下迭代器(数组 b 被广播到 a 的大小)。
b = np.array([1, 2, 3, 4], dtype=int)
print(a)
print(b)
for x, y in np.nditer([a, b]):
print("%d:%d" % (x, y), end=' ')
#[[ 0 10 20 30]
# [ 40 50 60 70]
# [ 80 90 100 110]]
# [1 2 3 4]
# 0:1 10:2 20:3 30:4 40:1 50:2 60:3 70:4 80:1 90:2 100:3 110:4
数组操作
修改数组形状
函数 | 描述 |
---|---|
reshape | 不改变数据的条件下修改形状 |
flat | 数组元素迭代器 |
flatten | 返回一份数组拷贝,对拷贝所做的修改不会影响原始数组 |
ravel | 返回展开数组 |
numpy.reshape
numpy.reshape 函数可以在不改变数据的条件下修改形状,格式如下:
numpy.reshape(arr, newshape, order='C')
arr
:要修改形状的数组newshape
:整数或者整数数组,新的形状应当兼容原有形状- order:‘C’ – 按行,‘F’ – 按列,‘A’ – 原顺序,‘k’ – 元素在内存中的出现顺序。
a = np.arange(9)
b = a.reshape(3, 3)
ic(b)
for row in b: #遍历每一行
print(row)
#对数组中每个元素都进行处理,可以使用flat属性,该属性是一个数组元素迭代器:
print('迭代后的数组:')
for element in b.flat:
print(element)
#[0 1 2]
#[3 4 5]
#[6 7 8]
#略
flatten() 将二维数组展开成一维
np.ravel(与flatten功能相同,在修改ravel对象时,原数组也做了同样的修改!!!但是修改flatten对象则不会出现这种情况,所以平时尽量使用flatten)
numpy.ravel() 展平的数组元素,顺序通常是"C风格",返回的是数组视图,修改会影响原始数组。
numpy.ravel(a, order='C')
- order:‘C’ – 按行,‘F’ – 按列,‘A’ – 原顺序,‘K’ – 元素在内存中的出现顺序。
翻转数组
函数 | 描述 |
---|---|
transpose | 对换数组的维度 |
ndarray.T | 和 self.transpose() 相同 |
rollaxis | 向后滚动指定的轴 |
swapaxes | 对换数组的两个轴(多维的情况) |
numpy.transpose
numpy.transpose 函数用于对换数组的维度,格式如下:
numpy.transpose(arr, axes)
参数说明:
arr
:要操作的数组axes
:整数列表,对应维度,通常所有维度都会对换。
修改数组维度
连接数组
函数 | 描述 |
---|---|
concatenate | 连接沿现有轴的数组序列 |
stack | 沿着新的轴加入一系列数组。 |
hstack | 水平堆叠序列中的数组(列方向) |
vstack | 竖直堆叠序列中的数组(行方向) |
numpy.concatenate
numpy.concatenate 函数用于沿指定轴连接相同形状的两个或多个数组,格式如下:
numpy.concatenate((a1, a2, ...), axis)
参数说明:
a1, a2, ...
:相同类型的数组axis
:沿着它连接数组的轴,默认为 0
a = np.arange(4).reshape(2, 2)
b = np.arange(5, 9).reshape(2, 2)
ic(np.concatenate((a, b))) #axis=0,沿着竖轴(默认),且这里要套两个括号
ic(np.concatenate((a, b), axis=1))
#ic| np.concatenate((a, b)): array([[0, 1],
# [2, 3],
# [5, 6],
# [7, 8]])
#ic| np.concatenate((a, b), axis=1): array([[0, 1, 5, 6],
# [2, 3, 7, 8]])
numpy.stack
numpy.stack 函数用于沿新轴连接数组序列(两个二维数组合并的结果为三维数组),格式如下:
numpy.stack(arrays, axis)
沿着x, y ,z轴进行合并
np.hstack()和np.vstack() 合并后还是二维数组
ic(np.hstack((a, b))) #左右
ic(np.vstack((a, b))) #上下
#ic| np.hstack((a, b)): array([[0, 1, 5, 6],
# [2, 3, 7, 8]])
#ic| np.vstack((a, b)): array([[0, 1],
# [2, 3],
# [5, 6],
# [7, 8]])
分割数组
函数 | 数组及操作 |
---|---|
split | 将一个数组分割为多个子数组 |
hsplit | 将一个数组水平分割为多个子数组(按列) |
vsplit | 将一个数组垂直分割为多个子数组(按行) |
numpy.split
numpy.split 函数沿特定的轴将数组分割为子数组,格式如下:
numpy.split(ary, indices_or_sections, axis)
参数说明:
ary
:被分割的数组indices_or_sections
:如果是一个整数,就用该数平均切分,如果是一个数组,为沿轴切分的位置(左开右闭)axis
:设置沿着哪个方向进行切分,默认为 0,横向切分,即水平方向。为 1 时,纵向切分,即竖直方向。
a = np.arange(9)
b = np.split(a, 3) #等分成三份
c = np.split(a, [4, 7]) #在指定位置切分
ic(b)
ic(c)
d = np.arange(16).reshape(4, 4)
ic(np.hsplit(d, 2)) #垂直方向分割
#ic| b: [array([0, 1, 2]), array([3, 4, 5]), array([6, 7, 8])]
#ic| c: [array([0, 1, 2, 3]), array([4, 5, 6]), array([7, 8])]
#ic| np.hsplit(d ,2): [array([[ 0, 1],
# [ 4, 5],
# [ 8, 9],
# [12, 13]]),
# array([[ 2, 3],
# [ 6, 7],
# [10, 11],
# [14, 15]])]
元素的添加与删除
函数 | 元素及描述 |
---|---|
resize | 返回指定形状的新数组 |
append | 将值添加到数组末尾 |
insert | 沿指定轴将值插入到指定下标之前 |
delete | 删掉某个轴的子数组,并返回删除后的新数组 |
unique | 查找数组内的唯一元素 |
numpy.resize(一般用于缩减)
numpy.resize 函数返回指定大小的新数组。
如果新数组大小大于原始大小,则包含原始数组中的元素的副本。
numpy.resize(arr, shape)
参数说明:
arr
:要修改大小的数组shape
:返回数组的新形状
resize有两种使用方式,一种是没有返回值的,直接对原始的数据进行修改,还有一种用法是有返回值的,所以不会修改原有的数组值。
a = np.array([[1, 2, 3], [4, 5, 6]])
ic(np.resize(a, (3, 3))) #会将第一行复制 不改变原来的数组
a2 = a.resize((2, 2))
ic(a2) #这里不返回值为None
ic(a) #此时,a已经被修改
#ic| np.resize(a, (3, 3)): array([[1, 2, 3],
# [4, 5, 6],
# [1, 2, 3]])
#ic| a2: None
#ic| a: array([[1, 2],
# [3, 4]])
numpy.append
numpy.append 函数在数组的末尾添加值。 追加操作会分配整个数组,并把原来的数组复制到新数组中。 此外,输入数组的维度必须匹配否则将生成ValueError。
append 函数返回的始终是一个一维数组。
numpy.append(arr, values, axis=None)
参数说明:
arr
:输入数组values
:要向arr
添加的值,需要和arr
形状相同(除了要添加的轴)axis
:默认为 None。当axis无定义时,是横向加成,返回总是为一维数组!当axis有定义的时候,分别为0和1的时候。当axis有定义的时候,分别为0和1的时候(列数要相同)。当axis为1时,数组是加在右边(行数要相同)。
a = np.array([[1, 2, 3], [4, 5, 6]])
ic(a)
ic(np.append(a, [[7, 8, 9]], axis=0))
#沿轴 0 添加元素:
#[[1 2 3]
# [4 5 6]
# [7 8 9]]
numpy.insert
numpy.insert 函数在给定索引之前,沿给定轴在输入数组中插入值。
如果值的类型转换为要插入,则它与输入数组不同。 插入没有原地的,函数会返回一个新数组。 此外,如果未提供轴,则输入数组会被展开。
numpy.insert(arr, obj, values, axis)
参数说明:
arr
:输入数组obj
:在其之前插入值的索引values
:要插入的值axis
:沿着它插入的轴,如果未提供,则输入数组会被展开
a = np.array([[1, 2], [3, 4], [5, 6]])
ic(a)
ic(np.insert(a, 1, 11))
ic(np.insert(a, 1, 11, axis=0))
ic(np.insert(a, 1, 11, axis=1))
#ic| np.insert(a, 1, 11): array([ 1, 11, 2, 3, 4, 5, 6])
#ic| np.insert(a, 1, 11, axis=0): array([[ 1, 2],
# [11, 11],
# [ 3, 4],
# [ 5, 6]])
#ic| np.insert(a, 1, 11, axis=1): array([[ 1, 11, 2],
# [ 3, 11, 4],
# [ 5, 11, 6]])
numpy.delete
numpy.delete 函数返回从输入数组中删除指定子数组的新数组。 与 insert() 函数的情况一样,如果未提供轴参数,则输入数组将展开。
Numpy.delete(arr, obj, axis)
参数说明:
arr
:输入数组obj
:可以被切片,整数或者整数数组,表明要从输入数组删除的子数组axis
:沿着它删除给定子数组的轴,如果未提供,则输入数组会被展开
a = np.arange(12).reshape(3, 4)
ic(a)
ic(np.delete(a, 5)) #未传递axis参数,再插入之前数组会被展开
ic(np.delete(a, 1, axis=0)) #删除第二行
b = np.arange(1, 11)
ic(b)
ic(b[np.s_[::2]]) #np.s_可以当作索引
ic(np.delete(b, np.s_[::2])) #删去索引为2的倍数的元素
#ic| a: array([[ 0, 1, 2, 3],
# [ 4, 5, 6, 7],
# [ 8, 9, 10, 11]])
#ic| np.delete(a, 5): array([ 0, 1, 2, 3, 4, 6, 7, 8, 9, 10, 11])
#ic| np.delete(a, 1, axis=0): array([[ 0, 1, 2, 3],
# [ 8, 9, 10, 11]])
#ic| b: array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
#ic| b[np.s_[::2]]: array([1, 3, 5, 7, 9])
#ic| np.delete(b, np.s_[::2]): array([ 2, 4, 6, 8, 10])
numpy.unique
numpy.unique 函数用于去除数组中的重复元素。
numpy.unique(arr, return_index, return_inverse, return_counts)
arr
:输入数组,如果不是一维数组则会展开return_index
:如果为true
,返回新列表元素在旧列表中的位置(下标),并以列表形式储return_inverse
:如果为true
,返回旧列表元素在新列表中的位置(下标),并以列表形式储return_counts
:如果为true
,返回去重数组中的元素在原数组中的出现次数
a = np.array([5, 2, 6, 2, 7, 5, 6, 8, 2, 9])
ic(a)
u = np.unique(a)
ic(u)
u, indices = np.unique(a, return_index=True) #返回去重后元素在原数组中的索引
ic(indices)
u, indices2 = np.unique(a, return_inverse=True) #返回去重前元素,在去重后列表(长度与元数组相等)中的位置
ic(indices2)
ic(u[indices2]) #利用去重后的数组u和索引indices2重构原数组
#ic| a: array([5, 2, 6, 2, 7, 5, 6, 8, 2, 9])
#ic| u: array([2, 5, 6, 7, 8, 9])
#ic| indices: array([1, 0, 2, 4, 7, 9], dtype=int64)
#ic| indices2: array([1, 0, 2, 0, 3, 1, 2, 4, 0, 5], dtype=int64)
字符串函数
以下函数用于对 dtype 为 numpy.string_ 或 numpy.unicode_ 的数组执行向量化字符串操作。 它们基于 Python 内置库中的标准字符串函数。
这些函数在字符数组类(numpy.char)中定义。
函数 | 描述 |
---|---|
add() | 对两个数组的逐个字符串元素进行连接 |
multiply() | 返回按元素多重连接后的字符串 |
center() | 居中字符串 |
capitalize() | 将字符串第一个字母转换为大写 |
title() | 将字符串的每个单词的第一个字母转换为大写 |
lower() | 数组元素转换为小写 |
upper() | 数组元素转换为大写 |
split() | 指定分隔符对字符串进行分割,并返回数组列表 |
splitlines() | 返回元素中的行列表,以换行符分割 |
strip() | 移除元素开头或者结尾处的特定字符 |
join() | 通过指定分隔符来连接数组中的元素 |
replace() | 使用新字符串替换字符串中的所有子字符串 |
decode() | 数组元素依次调用str.decode |
encode() | 数组元素依次调用str.encode |
a = '我爱你 '
b = ' 也恨你'
ic(np.char.add(a, b))#连接两个字符串
ic((np.char.multiply('Runoob ', 3))) #多重连接
ic((np.char.center('Runoob', 20,fillchar = '*'))) #居中,左右填充*
ic((np.char.split('www.runoob.com', sep = '.'))) #以.分割字符串返回一个列表
# 移除数组元素头尾的 a 字符
ic(np.char.strip(['arunooba', 'admin', 'java'], 'a'))
ic(np.char.replace('i like runoob', 'oo', 'cc')) #用特定字符串代替指定字符串
数学函数
a = np.array([1.0, 5.55, 123, 0.567, 25.532])
#舍入, decimals为舍入的小数位数,默认为0,如果为负,整数将四舍五入到小数点左侧的位置
ic((np.around(a, decimals=1)))
ic(np.floor(a)) #向下取整
ic(np.ceil(a)) #向上取整
算数函数
NumPy 算术函数包含简单的加减乘除: add(),subtract(),multiply() 和 divide()。
需要注意的是数组必须具有相同的形状或符合数组广播规则。
a = np.arange(9, dtype = np.float_).reshape(3,3)
b = np.array([10,10,10])
ic(a, b)
ic(np.add(a, b))
ic(np.multiply(a, b))
numpy.reciprocal() 函数返回参数逐元素的倒数。如 1/4 倒数为 4/1。
a = np.array([0.25, 1.33, 1, 100])
ic(np.reciprocal(a))
numpy.power() 函数将第一个输入数组中的元素作为底数,计算它与第二个输入数组中相应元素的幂。
a = np.array([10,100,1000])
ic(np.power(a, 2))
b = np.array([1, 2, 3])
ic(np.power(a, b))
numpy.mod() 计算输入数组中相应元素的相除后的余数。 函数 numpy.remainder() 也产生相同的结果。
a = np.array([10,20,30])
b = np.array([3,5,7])
ic(np.mod(a,b))
统计函数
numpy.amin() 用于计算数组中的元素沿指定轴的最小值。
numpy.amax() 用于计算数组中的元素沿指定轴的最大值。
a = np.array([[3, 7, 5], [8, 4, 3], [2, 4, 9]])
ic(np.amin(a, axis=0)) #指定自上到下寻找最小值,求得的为每一列的最小值
ic(np.amin(a, 0))
ic(np.amin(a))
#ic| np.amin(a, axis=0): array([2, 4, 3])
#ic| np.amin(a, 0): array([2, 4, 3])
#ic| np.amin(a): 2
numpy.ptp()函数计算数组中元素最大值与最小值的差(最大值 - 最小值
用法与amin()一致
numpy.percentile()
百分位数是统计中使用的度量,表示小于这个值的观察值的百分比。 函数numpy.percentile()接受以下参数。
numpy.percentile(a, q, axis)
参数说明:
- a: 输入数组
- q: 要计算的百分位数,在 0 ~ 100 之间
- axis: 沿着它计算百分位数的轴
numpy.median() 函数用于计算数组 a 中元素的中位数(中值)
numpy.mean()
numpy.mean() 函数返回数组中元素的算术平均值。 如果提供了轴,则沿其计算。
算术平均值是沿轴的元素的总和除以元素的数量。
numpy.average()
函数根据在另一个数组中给出的各自的权重计算数组中元素的加权平均值。
该函数可以接受一个轴参数。 如果没有指定轴,则数组会被展开。
加权平均值即将各数值乘以相应的权数,然后加总求和得到总体值,再除以总的单位数。
考虑数组[1,2,3,4]和相应的权重[4,3,2,1],通过将相应元素的乘积相加,并将和除以权重的和,来计算加权平均值。
a = np.array([[1, 2, 3], [3, 4, 5], [4, 5, 6]])
#计算加权平均值
a = np.array([1, 2, 3, 4])
#不指定权重时相当于mean函数
wts = np.array([4, 3, 2, 1]) #并非直接相乘,而是做了归一化
ic(np.average(a, weights=wts))
#ic| np.average(a, weights=wts): 2.0
计算标准差np.std() 计算方差np.var()
Numpy排序、条件筛选函数
种类 | 速度 | 最坏情况 | 工作空间 | 稳定性 |
---|---|---|---|---|
'quicksort' (快速排序) | 1 | O(n^2) | 0 | 否 |
'mergesort' (归并排序) | 2 | O(n*log(n)) | ~n/2 | 是 |
'heapsort' (堆排序) | 3 | O(n*log(n)) | 0 | 否 |
numpy.sort()
numpy.sort() 函数返回输入数组的排序副本。函数格式如下:
numpy.sort(a, axis, kind, order)
参数说明:
- a: 要排序的数组
- axis: 沿着它排序数组的轴,如果没有数组会被展开,沿着最后的轴排序, axis=0 按列排序,axis=1 按行排序
- kind: 默认为’quicksort’(快速排序)
- order: 如果数组包含字段,则是要排序的字段
a = np.array([[3, 7], [9, 1]]) #相当与axis=1
ic(a)
ic(np.sort(a))
ic(np.sort(a, axis=0)) #把每一列进行排序
ic(np.sort(a, axis=1)) #把每一行进行排序
#ic| a: array([[3, 7],
# [9, 1]])
#ic| np.sort(a): array([[3, 7],
# [1, 9]])
#ic| np.sort(a, axis=0): array([[3, 1],
# [9, 7]])
#ic| np.sort(a, axis=1): array([[3, 7],
# [1, 9]])
# 在 sort 函数中排序字段
dt = np.dtype([('name', 'S10'), ('age', int)])
a = np.array([("raju", 21), ("anil", 25), ("ravi", 17), ("amar", 27)], dtype = dt)
ic(np.sort(a, order='name'))
#略
numpy.argsort()
numpy.argsort() 函数返回的是数组值从小到大的索引值。
x = np.array([3, 1, 2])
ic(x)
y = np.argsort(x) #返回的是数组从小到大的索引
ic(y)
ic(x[y]) #重构数组
#ic| x: array([3, 1, 2])
#ic| y: array([1, 2, 0], dtype=int64)
#ic| x[y]: array([1, 2, 3])
函数 | 描述 |
---|---|
msort(a) | 数组按第一个轴排序,返回排序后的数组副本。np.msort(a) 相等于 np.sort(a, axis=0)。 |
sort_complex(a) | 对复数按照先实部后虚部的顺序进行排序。 |
partition(a, kth[, axis, kind, order]) | 指定一个数,对数组进行分区 |
argpartition(a, kth[, axis, kind, order]) | 可以通过关键字 kind 指定算法沿着指定轴对数组进行分区 |
numpy.argmax() 和 numpy.argmin()函数分别沿给定轴返回最大和最小元素的索引。
numpy.nonzero() 函数返回输入数组中非零元素的索引。
numpy.where() 函数返回输入数组中满足给定条件的元素的索引。
#np,where() 返回的是满足条件的索引,如果需要得到元素值的话需要进行x[y]
x = np.arange(9.).reshape(3, 3)
ic(x)
y = np.where(x > 3)
ic(x[y])
#ic| x: array([[0., 1., 2.],
# [3., 4., 5.],
# [6., 7., 8.]])
#ic| x[y]: array([4., 5., 6., 7., 8.])
numpy.extract() 函数根据某个条件从数组中抽取元素,返回满条件的元素。
condition = np.mod(x, 2) == 0
ic(condition)
ic(np.extract(condition, x))
# or np.extract(np.mod(x, 2) == 0, x)
#ic| condition: array([[ True, False, True],
# [False, True, False],
# [ True, False, True]])
#ic| np.extract(condition, x): array([0., 2., 4., 6., 8.])
Numpy字节交换
- **大端模式:**指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;这和我们的阅读习惯一致。
- **小端模式:**指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低。
例如在 C 语言中,一个类型为 int 的变量 x 地址为 0x100,那么其对应地址表达式&x的值为 0x100。且x的四个字节将被存储在存储器的 0x100, 0x101, 0x102, 0x103位置
numpy.ndarray.byteswap() 函数将 ndarray 中每个元素中的字节进行大小端转换。
Numpy副本和视图
副本是一个数据的完整的拷贝,如果我们对副本进行修改,它不会影响到原始数据,物理内存不在同一位置。
视图是数据的一个别称或引用,通过该别称或引用亦便可访问、操作原有数据,但原有数据不会产生拷贝。如果我们对视图进行修改,它会影响到原始数据,物理内存在同一位置。
视图一般发生在:
- 1、numpy 的切片操作返回原数据的视图。
- 2、调用 ndarray 的 view() 函数产生一个视图。
副本一般发生在:
- Python 序列的切片操作,调用deepCopy()函数。
- 调用 ndarray 的 copy() 函数产生一个副本。
无复制
简单的赋值不会创建数组对象的副本。 相反,它使用原始数组的相同id()来访问它。 id()返回 Python 对象的通用标识符,类似于 C 中的指针。
此外,一个数组的任何变化都反映在另一个数组上。 例如,一个数组的形状改变也会改变另一个数组的形状。
a = np.arange(6)
ic(a, id(a))
b = a #简单的赋值不会产生副本
ic(b, id(b))
b.shape = 3, 2 #修改b后a也进行了相应的修改
ic(a, id(a))
#ic| a: array([0, 1, 2, 3, 4, 5]), id(a): 1642905961536
#ic| b: array([0, 1, 2, 3, 4, 5]), id(b): 1642905961536
#ic| a: array([[0, 1],
# [2, 3],
# [4, 5]])
# id(a): 1642905961536
视图或浅拷贝
ndarray.view() 方会创建一个新的数组对象,该方法创建的新数组的维数变化不会改变原始数据的维数
a = np.arange(6).reshape(3, 2)
ic(a, id(a))
b = a.view()
ic(b, id(b)) #两个数组的id不同,修改b也不会改变a
#ic| a: array([[0, 1],
# [2, 3],
# [4, 5]])
# id(a): 1444818129424
#ic| b: array([[0, 1],
# [2, 3],
# [4, 5]])
# id(b): 1444818155120
副本或深拷贝
ndarray.copy() 函数创建一个副本。 对副本数据进行修改,不会影响到原始数据,它们物理内存不在同一位置。
a = np.array([[10, 10], [2, 3], [4, 5]])
ic(a, id(a))
b = a.copy()
ic(b is a)
b[0, 0] = 100
ic(a) #修改b,a不变
#ic| a: array([[10, 10],
# [ 2, 3],
# [ 4, 5]])
# id(a): 1538007678208
#ic| b is a: False
#ic| a: array([[10, 10],
# [ 2, 3],
# [ 4, 5]])
Numpy矩阵库
矩阵求转置 :a.T
matlib.empty()
matlib.empty() 函数返回一个新的矩阵,语法格式为:
numpy.matlib.empty(shape, dtype, order)
参数说明:
- shape: 定义新矩阵形状的整数或整数元组
- Dtype: 可选,数据类型
- order: C(行序优先) 或者 F(列序优先)
ic(np.matlib.empty((2, 2))) #填充为随机数据
numpy.matlib.zeros() 函数创建一个以 0 填充的矩阵。
numpy.matlib.ones()函数创建一个以 1 填充的矩阵。
numpy.matlib.eye()
numpy.matlib.eye() 函数返回一个矩阵,对角线元素为 1,其他位置为零。
numpy.matlib.eye(n, M,k, dtype)
参数说明:
- n: 返回矩阵的行数
- M: 返回矩阵的列数,默认为 n
- k: 对角线的索引
- dtype: 数据类型
numpy.matlib.rand()
numpy.matlib.rand() 函数创建一个给定大小的矩阵,数据是随机填充的。
print (np.matlib.rand(3,3))
Numpy线性代数
NumPy 提供了线性代数函数库 linalg,该库包含了线性代数所需的所有功能,可以看看下面的说明:
函数 | 描述 |
---|---|
dot | 两个数组的点积,即元素对应相乘。 |
vdot | 两个向量的点积 |
inner | 两个数组的内积 |
matmul | 两个数组的矩阵积 |
determinant | 数组的行列式 |
solve | 求解线性矩阵方程 |
inv | 计算矩阵的乘法逆矩阵 |
numpy.dot()
numpy.dot() 对于两个一维的数组,计算的是这两个数组对应下标元素的乘积和(数学上称之为内积);对于二维数组,计算的是两个数组的矩阵乘积;对于多维数组,它的通用计算公式如下,即结果数组中的每个元素都是:数组a的最后一维上的所有元素与数组b的倒数第二位上的所有元素的乘积和: dot(a, b)[i,j,k,m] = sum(a[i,j,:] * b[k,:,m])。
numpy.dot(a, b, out=None)
参数说明:
- a : ndarray 数组
- b : ndarray 数组
- out : ndarray, 可选,用来保存dot()的计算结果
a = np.array([[1,2],[3,4]])
b = np.array([[11,12],[13,14]])
print(np.dot(a,b))
#[[37 40]
# [85 92]]
numpy.vdot()
numpy.vdot() 函数是两个向量的点积。 如果第一个参数是复数,那么它的共轭复数会用于计算。 如果参数是多维数组,它会被展开
a = np.array([[1,2],[3,4]])
b = np.array([[11,12],[13,14]])
# vdot 将数组展开计算内积
print (np.vdot(a,b))
#130
numpy.inner()
numpy.inner() 函数返回一维数组的向量内积。对于更高的维度,它返回最后一个轴上对应乘积的和。
print (np.inner(np.array([1,2,3]),np.array([0,1,0])))
# 等价于 1*0+2*1+3*0
numpy.matmul
numpy.matmul 函数返回两个数组的矩阵乘积。 虽然它返回二维数组的正常乘积,但如果任一参数的维数大于2,则将其视为存在于最后两个索引的矩阵的栈,并进行相应广播。
另一方面,如果任一参数是一维数组,则通过在其维度上附加 1 来将其提升为矩阵,并在乘法之后被去除。
对于二维数组,它就是矩阵乘法:
a = [[1,0],[0,1]]
b = [[4,1],[2,2]]
print (np.matmul(a,b))
#[[4 1]
# [2 2]]
numpy.linalg.det()
numpy.linalg.det() 函数计算输入矩阵的行列式。
行列式在线性代数中是非常有用的值。 它从方阵的对角元素计算。 对于 2×2 矩阵,它是左上和右下元素的乘积与其他两个的乘积的差。
换句话说,对于矩阵[[a,b],[c,d]],行列式计算为 ad-bc。 较大的方阵被认为是 2×2 矩阵的组合。
a = np.array([[1,2], [3,4]])
print (np.linalg.det(a))
#-2.0
numpy.linalg.solve() 函数给出了矩阵形式的线性方程的解。
numpy.linalg.inv() 函数计算矩阵的乘法逆矩阵。