零之前言
因为后面机器学习需要使用到np,所以需要更高要求的了解Numpy这个包,我就根据菜鸟论坛上面的Numpy教程来学习并记录了。
参考:菜鸟教程-NumPy Ndarray 对象
一.创建Ndarray对象
1.概念
先看看创建ndaary对象的参数
numpy.array(object, dtype = None, copy = True, order = None, subok = False, ndmin = 0)
名称 | 描述 |
---|---|
object | 传入数组 |
dtype | 数据类型,可选 |
copy | 对象是否需要复制,可选 |
order | 创建数组的样式,C为行方向,F为列方向,A为任意方向(默认) |
subok | 默认返回一个与基类类型一致的数组 |
ndmin | 指定生成数组的最小维度 |
然后我们运行来看看效果
import numpy as np
2.返回类型
type(np.array([1,2,3]))
numpy.ndarray
3.传入数组
np.array([1,2,3])
array([1, 2, 3])
np.array([[1,2,3],[3,4,5]])
array([[1, 2, 3],
[3, 4, 5]])
4.最小维度
np.array([[1,2],[3,4]], ndmin = 3)
array([[[1, 2],
[3, 4]]])
5.类型
np.array([1,2],dtype=np.complex)
array([1.+0.j, 2.+0.j])
二.数据类型
数据类型 | 范围与说明 |
---|---|
bool_ | 布尔型数据类型(True 或者 False) |
int_ | 默认的整数类型(类似于 C 语言中的 long,int32 或 int64) |
intc | 与 C 的 int 类型一样,一般是 int32 或 int 64 |
intp | 用于索引的整数类型(类似于 C 的 ssize_t,一般情况下仍然是 int32 或 int64) |
int8 | 字节(-128 to 127) |
int16 | 整数(-32768 to 32767) |
int32 | 整数(-2147483648 to 2147483647) |
int64 | 整数(-9223372036854775808 to 9223372036854775807) |
uint8 | 无符号整数(0 to 255) |
uint16 | 无符号整数(0 to 65535) |
uint32 | 无符号整数(0 to 4294967295) |
uint64 | 无符号整数(0 to 18446744073709551615) |
float_ | float64 类型的简写 |
float16 | 半精度浮点数,包括:1 个符号位,5 个指数位,10 个尾数位 |
float32 | 单精度浮点数,包括:1 个符号位,8 个指数位,23 个尾数位 |
float64 | 双精度浮点数,包括:1 个符号位,11 个指数位,52 个尾数位 |
complex_ | complex128 类型的简写,即 128 位复数 |
complex64 | 复数,表示双 32 位浮点数(实数部分和虚数部分) |
complex128 | 复数,表示双 64 位浮点数(实数部分和虚数部分) |
当然,也可以自定义数据类型,详细请看:NumPy 数据类型
三.数组属性(ndaary的属性)
参数 | 说明 |
---|---|
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 | 包含实际数组元素的缓冲区,由于一般通过数组的索引获取元素,所以通常不需要使用这个属性。 |
1.秩ndim
a = np.arange(24)
b = a.reshape(2,4,3)
print(a,a.ndim)
print(b,b.ndim)
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23] 1
[[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]]
[[12 13 14]
[15 16 17]
[18 19 20]
[21 22 23]]] 3
2.维度shape
调用shape是这个数组的维度,而维度的长度和位秩,继续使用上面的a,b两个例子
print(a.shape)
print(b.shape)
(24,)
(2, 4, 3)
a.shape = (4,3,2)
print(a, a.ndim)
[[[ 0 1]
[ 2 3]
[ 4 5]]
[[ 6 7]
[ 8 9]
[10 11]]
[[12 13]
[14 15]
[16 17]]
[[18 19]
[20 21]
[22 23]]] 3
其他的属性,并没有什么好说的了。
四.创建数组
1.empty
创建一个指定形状(shape)、数据类型(dtype)且未初始化的数组:
numpy.empty(shape, dtype = float, order = 'C')
参数 | 描述 |
---|---|
shape | 数组形状 |
dtype | 数据类型,可选 |
order | 有"C"和"F"两个选项,分别代表,行优先和列优先,在计算机内存中的存储元素的顺序。 |
np.empty([3,2], dtype = int,order = "C")
array([[7022643874161258350, 6715465368541538412],
[3683993085686784044, 6716028318494960733],
[8746397786910107997, 7310305785200466728]])
2.zeros
创建指定大小的数组,数组元素以 0 来填充:
np.zeros([3,2], dtype = int, order = 'F')
array([[0, 0],
[0, 0],
[0, 0]])
3.ones
创建指定大小的数组,数组元素以 1 来填充:
np.ones([3,2], dtype = np.int8, order = 'C')
array([[1, 1],
[1, 1],
[1, 1]], dtype=int8)
4.asarray
numpy.asarray 类似 numpy.array,但 numpy.asarray 参数只有三个,比 numpy.array 少两个
numpy.asarray(a, dtype = None, order = None)
参数 | 描述 |
---|---|
a | 任意形式的输入参数,可以是,列表, 列表的元组, 元组, 元组的元组, 元组的列表,多维数组 |
dtype | 数据类型,可选 |
order | 可选,有"C"和"F"两个选项,分别代表,行优先和列优先,在计算机内存中的存储元素的顺序。 |
np.asarray([(1,2,3),(4,5)])
array([(1, 2, 3), (4, 5)], dtype=object)
但是这样就会报错,因为我们是列表里镶嵌元组,所以与int8类型是不匹配的
np.asarray([(1,2,3),(4,5)],dtype=np.int8)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-42-f73712c57ed0> in <module>()
----> 1 np.asarray([(1,2,3),(4,5)],dtype=np.int8)
~/anaconda3/lib/python3.7/site-packages/numpy/core/numeric.py in asarray(a, dtype, order)
499
500 """
--> 501 return array(a, dtype, copy=False, order=order)
502
503
ValueError: setting an array element with a sequence.
5.arange
numpy.arange(start, stop, step, dtype)
通过等差数列创建对象
参数 | 描述 |
---|---|
start | 起始值,默认为0 |
stop | 终止值(不包含) |
step | 步长,默认为1 |
dtype | 返回ndarray的数据类型,如果没有提供,则会使用输入数据的类型。 |
print(np.arange(5))
print(np.arange(0,12,2,dtype=np.complex))
[0 1 2 3 4]
[ 0.+0.j 2.+0.j 4.+0.j 6.+0.j 8.+0.j 10.+0.j]
6.linspace
类似于上面的, 函数用于创建一个一维数组,数组是一个等差数列构成的,格式如下:
参数 | 描述 |
---|---|
start | 序列的起始值 |
stop | 序列的终止值,如果endpoint为true,该值包含于数列中 |
num | 要生成的等步长的样本数量,默认为50 |
endpoint | 该值为 true 时,数列中中包含stop值,反之不包含,默认是True。 |
retstep | 如果为 True 时,生成的数组中会显示间距,反之不显示。 |
dtype | ndarray 的数据类型 |
print(np.linspace(1,10,10,dtype=np.int8))
[ 1 2 3 4 5 6 7 8 9 10]
7.其他
还有很多函数没记录,有些是在后面,和线性代数相关的,有些是感觉用处不多的,如frombuffer
fromiter
五.数据切片和索引
暂且可理解为提取有用数据。
例:
a = np.arange(10)
a[2:7:2]
array([2, 4])
其中,[2:7:2] 可以解释为从索引 2 开始到索引 7 停止,间隔为 2,而对于该冒号可以解释为成
如果只放置一个参数,如 [2],将返回与该索引相对应的单个元素。如果为 [2:],表示从该索引开始以后的所有项都将被提取。如果使用了两个参数,如 [2:7],那么则提取两个索引(不包括停止索引)之间的项。
那么,就可以理解为[2:5:1]=[{x|2<=x<5 ∩ x=N}[=[[2,3,4]],对,一个或一组冒号会多增加一个[]
多维数组也支持这种理解:
a = np.array([[1,2,3],[3,4,5],[4,5,6]])
print(a)
print('从数组索引 a[1:] 处开始切割')
print(a[1:])
[[1 2 3]
[3 4 5]
[4 5 6]]
从数组索引 a[1:] 处开始切割
[[3 4 5]
[4 5 6]]
切片还可以包括省略号 …,来使选择元组的长度与数组的维度相同。 如果在行位置使用省略号,它将返回包含行中元素的 ndarray
a = np.array([[1,2,3],[4,5,6],[7,8,9]])
print(a[...,1])
print(a[...,1:2])
print(a[...,2:3])
print(a[...,1:])
[2 5 8]
[[2]
[5]
[8]]
[[3]
[6]
[9]]
[[2 3]
[5 6]
[8 9]]
六.高级索引
1.整数数组索引
比如下图所示的就是取(0,0)(1,1)(2,0)
x = np.array([[1, 2], [3, 4], [5, 6]])
print(x[[0,1,2], [0,1,0]])
print(x[[0], [0,1,0]])
[1 4 5]
[1 2 1]
当我们知道以上这种方法后,我们可以还原: …表达式来看
这个是二维数组的切片方法:
a = np.array([[1,2,3],[4,5,6],[7,8,9]])
print(a[1:2,0:1])
print("-----------")
print(a[1:2,[0,1]])
print("-----------")
print(a[:2,1:])
print("-----------")
[[4]]
-----------
[[4 5]]
-----------
[[2 3]
[5 6]]
-----------
1:2 = [1]; 0:1 = [0]; a[1:2,0:1] = a[[1],[0]] = [[4]]
1:2 = [1]; a[1:2,[0,1]] = a[[1],[0,1]] = [[4 5]]
:2 = [0,1]; 1: = [1,2] = a[[0,1],[1,2]]
通过还原表达式,就可以具体知道其意思
2.布尔索引
简单明了
a = np.array([[1,2,3],[4,5,6],[7,8,9]])
a[a > 2]
array([3, 4, 5, 6, 7, 8, 9])
3.花式索引
花式索引指的是利用整数数组进行索引。
花式索引根据索引数组的值作为目标数组的某个轴的下标来取值。对于使用一维整型数组作为索引,如果目标是一维数组,那么索引的结果就是对应位置的元素;如果目标是二维数组,那么就是对应下标的行。
花式索引跟切片不一样,它总是将数据复制到新数组中。
a = np.array([[1,2,3],[4,5,6],[7,8,9]])
print(a[[0,2]])
print("---")
print(a[[2,1,0]])
[[1 2 3]
[7 8 9]]
---
[[7 8 9]
[4 5 6]
[1 2 3]]
七.广播
广播(Broadcast)是 numpy 对不同形状(shape)的数组进行数值计算的方式, 对数组的算术运算通常在相应的元素上进行。其方式大概像这样:
a = np.array([[ 0, 0, 0],
[10,10,10],
[20,20,20],
[30,30,30]])
b = np.array([1,2,3])
print(a + b)
[[ 1 2 3]
[11 12 13]
[21 22 23]
[31 32 33]]
广播的规则:
- 让所有输入数组都向其中形状最长的数组看齐,形状中不足的部分都通过在前面加 1 补齐。
- 输出数组的形状是输入数组形状的各个维度上的最大值。
- 如果输入数组的某个维度和输出数组的对应维度的长度相同或者其长度为 1 时,这个数组能够用来计算,否则出错。
- 当输入数组的某个维度的长度为 1 时,沿着此维度运算时都用此维度上的第一组值。
简单理解:对两个数组,分别比较他们的每一个维度(若其中一个数组没有当前维度则忽略),满足:
- 数组拥有相同形状。
- 当前维度的值相等。
- 当前维度的值有一个是 1。
若条件不满足,抛出 “ValueError: frames are not aligned” 异常。
八.迭代(遍历)
1.控制方向
for x in np.nditer(a, order='F')
:Fortran order,即是列序优先;
for x in np.nditer(a.T, order='C')
:C order,即是行序优先;
a = np.arange(0,60,5)
a = a.reshape(3,4)
print ('原始数组是:')
print (a)
print ('\n')
print ('原始数组的转置是:')
b = a.T
print (b)
print ('\n')
print ('以 C 风格顺序排序:')
c = b.copy(order='C')
print (c)
for x in np.nditer(c):
print (x, end=", " )
print ('\n')
print ('以 F 风格顺序排序:')
c = b.copy(order='F')
print (c)
for x in np.nditer(c):
print (x, end=", " )
原始数组是:
[[ 0 5 10 15]
[20 25 30 35]
[40 45 50 55]]
原始数组的转置是:
[[ 0 20 40]
[ 5 25 45]
[10 30 50]
[15 35 55]]
以 C 风格顺序排序:
[[ 0 20 40]
[ 5 25 45]
[10 30 50]
[15 35 55]]
0, 20, 40, 5, 25, 45, 10, 30, 50, 15, 35, 55,
以 F 风格顺序排序:
[[ 0 20 40]
[ 5 25 45]
[10 30 50]
[15 35 55]]
0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55,
2.修改元素的值
nditer 对象有另一个可选参数 op_flags。 默认情况下,nditer 将视待迭代遍历的数组为只读对象(read-only),为了在遍历数组的同时,实现对数组元素值得修改,必须指定 read-write
或者 write-only
的模式。
a = np.arange(0,60,5)
a = a.reshape(3,4)
print ('原始数组是:')
print (a)
print ('\n')
for x in np.nditer(a, op_flags=['readwrite']):
x[...]=2*x
print ('修改后的数组是:')
print (a)
原始数组是:
[[ 0 5 10 15]
[20 25 30 35]
[40 45 50 55]]
修改后的数组是:
[[ 0 10 20 30]
[ 40 50 60 70]
[ 80 90 100 110]]
3.其他
外部循环与广播循环看起来不常用,就不记了。
九.数组操作
1.修改数组形状
①reshape
numpy.reshape 函数可以在不改变数据的条件下修改形状,格式如下: numpy.reshape(arr, newshape, order=‘C’)
- arr:要修改形状的数组
- newshape:整数或者整数数组,新的形状应当兼容原有形状
- order:‘C’ – 按行,‘F’ – 按列,‘A’ – 原顺序,‘k’ – 元素在内存中的出现顺序。
a = np.arange(8)
a.reshape(4,2)
array([[0, 1],
[2, 3],
[4, 5],
[6, 7]])
②ndarray.flat
numpy.ndarray.flat 是一个数组元素迭代器,实例如下:
a = np.arange(9).reshape(3,3)
for element in a.flat:
print (element)
0
1
2
3
4
5
6
7
8
③ndarray.flatten
umpy.ndarray.flatten 返回一份数组拷贝,对拷贝所做的修改不会影响原始数组,格式如下:
ndarray.flatten(order='C')
- order:‘C’ – 按行,‘F’ – 按列,‘A’ – 原顺序,‘K’ – 元素在内存中的出现顺序。
a = np.arange(8).reshape(2,4)
print (a.flatten(order = 'A'))
print ('\n')
print (a.flatten(order = 'C'))
print ('\n')
print (a.flatten(order = 'F'))
[0 1 2 3 4 5 6 7]
[0 1 2 3 4 5 6 7]
[0 4 1 5 2 6 3 7]
④ravel
numpy.ravel() 展平的数组元素,顺序通常是"C风格",返回的是数组视图(view,有点类似 C/C++引用reference的意味),修改会影响原始数组。
numpy.ravel(a, order='C')
- order:‘C’ – 按行,‘F’ – 按列,‘A’ – 原顺序,‘K’ – 元素在内存中的出现顺序。
效果差不多同上,就不赘述
2.翻转数组
①transpose
`numpy.transpose(arr, axes)`
-
arr:要操作的数组
-
axes:整数列表,对应维度,通常所有维度都会对换。
a = np.arange(9).reshape(3,3)
print (np.transpose(a))
[[0 3 6]
[1 4 7]
[2 5 8]]
②.ndarray.T
numpy.ndarray.T 类似 numpy.transpose:
a = np.arange(9).reshape(3,3)
print (a.T)
[[0 3 6]
[1 4 7]
[2 5 8]]
③.rollaxis
numpy.rollaxis 函数向后滚动特定的轴到一个特定位置,格式如下:
numpy.rollaxis(arr, axis, start)
- arr:数组
- axis:要向后滚动的轴,其它轴的相对位置不会改变
- start:默认为零,表示完整的滚动。会滚动到特定位置。
对于轴数的理解,我理解为,假设二位数组a[0轴][1轴],三维数组就是a[0][1][2]轴。
下面例子是将2轴放到1轴前面,也就是1 2轴互换位置
a = np.arange(8).reshape(2,2,2)
print(a[0,0,1])
print(a[0,1,0])
b=np.rollaxis(a,2,1)
print(b[0,0,1])
print(b[0,1,0])
1
2
2
1
④swapaxes
numpy.swapaxes 函数用于交换数组的两个轴
a = np.arange(8).reshape(2,2,2)
print(a[0,0,1])
print(a[1,0,0])
b=np.swapaxes(a,2,0)
print(b[0,0,1])
print(b[1,0,0])
1
4
4
1
3.修改数组维度
①broadcast
numpy.broadcast 用于模仿广播的对象,它返回一个对象,该对象封装了将一个数组广播到另一个数组的结果
x = np.array([[1], [2], [3]])
y = np.array([4, 5, 6])
a = np.broadcast(x,y)
print(type(a))
b = np.zeros(a.shape,dtype=np.int8)
print(b)
print (x + y)
<class 'numpy.broadcast'>
[[0 0 0]
[0 0 0]
[0 0 0]]
[[5 6 7]
[6 7 8]
[7 8 9]]
②broadcast_to
broadcast_to 函数将数组广播到新形状。它在原始数组上返回只读视图。 它通常不连续。 如果新形状不符合 NumPy 的广播规则,该函数可能会抛出ValueError。
a = np.arange(4).reshape(1,4)
print (a)
print ('--------')
print (np.broadcast_to(a,(4,4)))
[[0 1 2 3]]
--------
[[0 1 2 3]
[0 1 2 3]
[0 1 2 3]
[0 1 2 3]]
③expand_dims
numpy.expand_dims 函数通过在指定位置插入新的轴来扩展数组形状。
x = np.array(([1,2],[3,4]))
print ('数组 x:')
print (x)
y = np.expand_dims(x, axis = 0)
print ('数组 y:')
print (y)
print ('数组 x 和 y 的形状:')
print (x.shape, y.shape)
# 在位置 1 插入轴
y = np.expand_dims(x, axis = 1)
print ('在位置 1 插入轴之后的数组 y:')
print (y)
print ('x.shape 和 y.shape:')
print (x.shape, y.shape)
数组 x:
[[1 2]
[3 4]]
数组 y:
[[[1 2]
[3 4]]]
数组 x 和 y 的形状:
(2, 2) (1, 2, 2)
在位置 1 插入轴之后的数组 y:
[[[1 2]]
[[3 4]]]
x.shape 和 y.shape:
(2, 2) (2, 1, 2)
④squeeze
numpy.squeeze 函数从给定数组的形状中删除一维的条目
- axis用于指定需要删除的维度,但是指定的维度必须为单维度,否则将会报错;
import numpy as np
x = np.arange(8).reshape(1,4,2)
print (x)
y = np.squeeze(x,0)
print ('数组 y:')
print (y)
print ('数组 x 和 y 的形状:')
print (x.shape, y.shape)
x = np.arange(8).reshape(1,8,1)
print (x)
y = np.squeeze(x,(0,2))
print ('数组 y:')
print (y)
print ('数组 x 和 y 的形状:')
print (x.shape, y.shape)
[[[0 1]
[2 3]
[4 5]
[6 7]]]
数组 y:
[[0 1]
[2 3]
[4 5]
[6 7]]
数组 x 和 y 的形状:
(1, 4, 2) (4, 2)
[[[0]
[1]
[2]
[3]
[4]
[5]
[6]
[7]]]
数组 y:
[0 1 2 3 4 5 6 7]
数组 x 和 y 的形状:
(1, 8, 1) (8,)
4.连接数组
①concatenate
numpy.concatenate 函数用于沿指定轴连接相同形状的两个或多个相同维度数组,格式如下:
numpy.concatenate((a1, a2, ...), axis)
a = np.array([[1,2],[3,4]])
print ('第一个数组:')
print (a)
print ('\n')
b = np.array([[5,6],[7,8]])
print ('第二个数组:')
print (b)
print ('\n')
# 两个数组的维度相同
print ('沿轴 0 连接两个数组:')
print (np.concatenate((a,b)))
print ('\n')
print ('沿轴 1 连接两个数组:')
print (np.concatenate((a,b),axis = 1))
第一个数组:
[[1 2]
[3 4]]
第二个数组:
[[5 6]
[7 8]]
沿轴 0 连接两个数组:
[[1 2]
[3 4]
[5 6]
[7 8]]
沿轴 1 连接两个数组:
[[1 2 5 6]
[3 4 7 8]]
②stack
numpy.stack(arrays, axis)
- arrays相同形状的数组序列
- axis:返回数组中的轴,输入数组沿着它来堆叠
这个函数待理解,操作后会升维
a = np.array([[1,2],[3,4]])
print ('第一个数组:')
print (a)
print ('\n')
b = np.array([[5,6],[7,8]])
print ('第二个数组:')
print (b)
print ('\n')
print ('沿轴 0 堆叠两个数组:')
d = np.stack((a,b),0)
print(d,d.shape)
print ('\n')
print ('沿轴 1 堆叠两个数组:')
c = np.stack((a,b),1)
print(c,c.shape)
第一个数组:
[[1 2]
[3 4]]
第二个数组:
[[5 6]
[7 8]]
沿轴 0 堆叠两个数组:
[[[1 2]
[3 4]]
[[5 6]
[7 8]]] (2, 2, 2)
沿轴 1 堆叠两个数组:
[[[1 2]
[5 6]]
[[3 4]
[7 8]]] (2, 2, 2)
③hstack与vstack
这两个函数是 numpy.stack 函数的变体。numpy.hstack它通过水平堆叠来生成数组;numpy.vstack它通过垂直堆叠来生成数组。
a = np.array([[1,2],[3,4]])
b = np.array([[5,6],[7,8]])
print ('水平堆叠:')
c = np.hstack((a,b))
print (c)
print ('\n')
print ('竖直堆叠:')
c = np.vstack((a,b))
print (c)
水平堆叠:
[[1 2 5 6]
[3 4 7 8]]
竖直堆叠:
[[1 2]
[3 4]
[5 6]
[7 8]]
5.分割数组
①split
numpy.split 函数沿特定的轴将数组分割为子数组,格式如下:
numpy.split(ary, indices_or_sections, axis)
- ary:被分割的数组
- indices_or_sections:果是一个整数,就用该数平均切分,如果是一个数组,为沿轴切分的位置(左开右闭)
- axis:沿着哪个维度进行切向,默认为0,横向切分。为1时,纵向切分
a = np.arange(9).reshape(3,3)
print ('第一个数组:')
print (a)
print ('\n')
print ('将数组分为三个大小相等的子数组:')
b = np.split(a,3)
print (b)
print ('\n')
print ('将数组在二数组中表明的位置分割:')
print(a[1,2])
b = np.split(a,[0,2],1) #如果是一个数组,为沿轴切分的位置(左开右闭)
print (b)
第一个数组:
[[0 1 2]
[3 4 5]
[6 7 8]]
将数组分为三个大小相等的子数组:
[array([[0, 1, 2]]), array([[3, 4, 5]]), array([[6, 7, 8]])]
将数组在二数组中表明的位置分割:
5
[array([], shape=(3, 0), dtype=int64), array([[0, 1],
[3, 4],
[6, 7]]), array([[2],
[5],
[8]])]
③hsplit与vsplit
numpy.hsplit 函数用于水平分割数组,通过指定要返回的相同形状的数组数量来拆分原数组。
numpy.vsplit 沿着垂直轴分割,其分割方式与hsplit用法相同。
a = np.arange(16).reshape(4,4)
print(np.hsplit(a, 4))
b = np.vsplit(a,2)
print (b)
[array([[ 0],
[ 4],
[ 8],
[12]]), array([[ 1],
[ 5],
[ 9],
[13]]), array([[ 2],
[ 6],
[10],
[14]]), array([[ 3],
[ 7],
[11],
[15]])]
[array([[0, 1, 2, 3],
[4, 5, 6, 7]]), array([[ 8, 9, 10, 11],
[12, 13, 14, 15]])]
6.数组元素的添加与删除
①resize
numpy.resize 函数返回指定大小的新数组。如果新数组大小大于原始大小,则包含原始数组中的元素的副本。
a = np.array([[1,2,3],[4,5,6]])
print(np.resize(a, (3,2)))
print(np.resize(a,(3,3)))
[[1 2]
[3 4]
[5 6]]
[[1 2 3]
[4 5 6]
[1 2 3]]
②append
numpy.append 函数在数组的末尾添加值。 追加操作会分配整个数组,并把原来的数组复制到新数组中。 此外,输入数组的维度必须匹配否则将生成ValueError。
numpy.append(arr, values, axis=None)
- arr:输入数组
- values:要向arr添加的值,需要和arr形状相同(除了要添加的轴)
- axis:默认为 None。当axis无定义时,是横向加成,返回总是为一维数组!当axis有定义的时候,分别为0和1的时候(列数要相同)。当axis为1时,数组是加在右边(行数要相同)。
a = np.array([[1,2,3],[4,5,6]])
print ('沿轴 0 添加元素:')
print (np.append(a, [[7,8,9]],axis = 0))
print ('沿轴 1 添加元素:')
print (np.append(a, [[5,5,5],[7,8,9]],axis = 1))
a = np.arange(8).reshape(2,2,2)
b = np.arange(8).reshape(2,2,2)
c = np.append(a, b, axis=1)
print (c,c.shape)
沿轴 0 添加元素:
[[1 2 3]
[4 5 6]
[7 8 9]]
沿轴 1 添加元素:
[[1 2 3 5 5 5]
[4 5 6 7 8 9]]
[[[0 1]
[2 3]
[0 1]
[2 3]]
[[4 5]
[6 7]
[4 5]
[6 7]]] (2, 4, 2)
③insert
numpy.insert 函数在给定索引之前,沿给定轴在输入数组中插入值。
如果值的类型转换为要插入,则它与输入数组不同。 插入没有原地的,函数会返回一个新数组。 此外,如果未提供轴,则输入数组会被展开(返回一维数组)。
a = np.array([[1,2],[3,4],[5,6]])
print ('第一个数组:')
print (a)
print ('\n')
print ('未传递 Axis 参数。 在插入之前输入数组会被展开。')
print (np.insert(a,3,[11,12]))
print ('\n')
print ('传递了 Axis 参数。 会广播值数组来配输入数组。')
print ('沿轴 0 广播:')
print (np.insert(a,3,[11],axis = 0))
print ('\n')
print ('沿轴 1 广播:')
print (np.insert(a,2,11,axis = 1))
第一个数组:
[[1 2]
[3 4]
[5 6]]
未传递 Axis 参数。 在插入之前输入数组会被展开。
[ 1 2 3 11 12 4 5 6]
传递了 Axis 参数。 会广播值数组来配输入数组。
沿轴 0 广播:
[[ 1 2]
[ 3 4]
[ 5 6]
[11 11]]
沿轴 1 广播:
[[ 1 2 11]
[ 3 4 11]
[ 5 6 11]]
④delete
numpy.delete 函数返回从输入数组中删除指定子数组的新数组。 与 insert() 函数的情况一样,如果未提供轴参数,则输入数组将展开。
a = np.arange(12).reshape(3,4)
print ('第一个数组:')
print (a)
print ('\n')
print ('未传递 Axis 参数。 在插入之前输入数组会被展开。')
print (np.delete(a,5))
print ('\n')
print ('删除第二列:')
print (np.delete(a,1,axis = 1))
print ('\n')
print ('删除第二行:')
print (np.delete(a,1,axis = 0))
print ('\n')
print ('删除第一、二行:')
print (np.delete(a,[0,1],axis = 0))
print ('\n')
print ('包含从数组中删除的替代值的切片:')
a = np.array([1,2,3,4,5,6,7,8,9,10])
print (np.delete(a, np.s_[::2]))
第一个数组:
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
未传递 Axis 参数。 在插入之前输入数组会被展开。
[ 0 1 2 3 4 6 7 8 9 10 11]
删除第二列:
[[ 0 2 3]
[ 4 6 7]
[ 8 10 11]]
删除第二行:
[[ 0 1 2 3]
[ 8 9 10 11]]
删除第一、二行:
[[ 8 9 10 11]]
包含从数组中删除的替代值的切片:
[ 2 4 6 8 10]
⑤unique
numpy.unique 函数用于去除数组中的重复元素。
umpy.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])
print ('第一个数组:')
print (a)
print ('\n')
print ('第一个数组的去重值:')
u = np.unique(a)
print (u)
print ('\n')
print ('去重数组的索引数组:')
u,indices = np.unique(a, return_index = True)
print (indices)
print ('\n')
print ('我们可以看到每个和原数组下标对应的数值:')
print (a)
print ('\n')
print ('去重数组的下标:')
u,indices = np.unique(a,return_inverse = True)
print (u)
print ('\n')
print ('下标为:')
print (indices)
print ('\n')
print ('使用下标重构原数组:')
print (u[indices])
print ('\n')
print ('返回去重元素的重复数量:')
u,indices = np.unique(a,return_counts = True)
print (u)
print (indices)
第一个数组:
[5 2 6 2 7 5 6 8 2 9]
第一个数组的去重值:
[2 5 6 7 8 9]
去重数组的索引数组:
[1 0 2 4 7 9]
我们可以看到每个和原数组下标对应的数值:
[5 2 6 2 7 5 6 8 2 9]
去重数组的下标:
[2 5 6 7 8 9]
下标为:
[1 0 2 0 3 1 2 4 0 5]
使用下标重构原数组:
[5 2 6 2 7 5 6 8 2 9]
返回去重元素的重复数量:
[2 5 6 7 8 9]
[3 2 2 1 1 1]
十.算术函数
1.加减乘除
加减乘除必须满足两者纬数相同或者能广播。
a = np.arange(9).reshape(3,3)
b = np.array([10,10,10])
print (np.add(a,b))
print (np.subtract(a,b))
print (np.multiply(a,b))
print (np.divide(a,b))
[[10 11 12]
[13 14 15]
[16 17 18]]
[[-10 -9 -8]
[ -7 -6 -5]
[ -4 -3 -2]]
[[ 0 10 20]
[30 40 50]
[60 70 80]]
[[0. 0.1 0.2]
[0.3 0.4 0.5]
[0.6 0.7 0.8]]
2.求倒数
(不是求矩阵的逆)
a = np.array([0.25, 1.33, 1, 100])
print (np.reciprocal(a))
[4. 0.7518797 1. 0.01 ]
3.求幂
a = np.array([10,100,1000])
b = np.array([1,2,3])
print (np.power(a,2),np.power(a,b))
[ 100 10000 1000000] [ 10 10000 1000000000]
4.取余
函数 numpy.remainder() 也产生相同的结果
a = np.array([10,20,30])
b = np.array([3,5,7])
print (np.mod(a,b))
print (np.remainder(a,b))
[1 0 2]
[1 0 2]
十一.统计函数
1.最值
np.amin(a, axis=None, out=None, keepdims=, initial=)
a = np.array([[3,7,5],[8,4,3],[2,4,9]])
print (a)
print('----')
print (np.amin(a))
print('----')
print (np.amin(a,0))
print('----')
print (np.amin(a,1))
[[3 7 5]
[8 4 3]
[2 4 9]]
----
2
----
[2 4 3]
----
[3 3 2]
2.极差(max - min)
也可以分轴
a = np.arange(8).reshape(2,2,2)
print ('我们的数组是:')
print (a)
print ('\n')
print ('调用 ptp() 函数:')
print (np.ptp(a))
print ('\n')
print (np.ptp(a, axis = 1))
print ('\n')
print (np.ptp(a, axis = 0))
我们的数组是:
[[[0 1]
[2 3]]
[[4 5]
[6 7]]]
调用 ptp() 函数:
7
沿轴 1 调用 ptp() 函数:
[[2 2]
[2 2]]
沿轴 0 调用 ptp() 函数:
[[4 4]
[4 4]]
3.百分位数
百分位数是统计中使用的度量,表示小于这个值的观察值的百分比。 函数numpy.percentile()接受以下参数:
numpy.percentile(a, q, axis)
- a: 输入数组
- q: 要计算的百分位数,在 0 ~ 100 之间
- axis: 沿着它计算百分位数的轴
首先明确百分位数:
第 p 个百分位数是这样一个值,它使得至少有 p% 的数据项小于或等于这个值,且至少有 (100-p)% 的数据项大于或等于这个值。
举个例子:高等院校的入学考试成绩经常以百分位数的形式报告。比如,假设某个考生在入学考试中的语文部分的原始分数为 54 分。相对于参加同一考试的其他学生来说,他的成绩如何并不容易知道。但是如果原始分数54分恰好对应的是第70百分位数,我们就能知道大约70%的学生的考分比他低,而约30%的学生考分比他高。
这里的 p = 70。
a = np.array([[10, 7, 4], [3, 2, 1]])
print ('我们的数组是:')
print (a)
print ('调用 percentile() 函数:')
# 50% 的分位数,就是 a 里排序之后的中位数
print (np.percentile(a, 50))
# axis 为 0,在纵列上求
print (np.percentile(a, 50, axis=0))
# axis 为 1,在横行上求
print (np.percentile(a, 50, axis=1))
# 保持维度不变
print (np.percentile(a, 50, axis=1, keepdims=True))
我们的数组是:
[[10 7 4]
[ 3 2 1]]
调用 percentile() 函数:
3.5
[6.5 4.5 2.5]
[7. 2.]
[[7.]
[2.]]
4.中位数
a = np.array([[30,65,70],[80,95,10],[50,90,60]])
print ('我们的数组是:')
print (a)
print ('\n')
print ('调用 median() 函数:')
print (np.median(a))
print ('\n')
print ('沿轴 0 调用 median() 函数:')
print (np.median(a, axis = 0))
print ('\n')
print ('沿轴 1 调用 median() 函数:')
print (np.median(a, axis = 1))
我们的数组是:
[[30 65 70]
[80 95 10]
[50 90 60]]
调用 median() 函数:
65.0
沿轴 0 调用 median() 函数:
[50. 90. 60.]
沿轴 1 调用 median() 函数:
[65. 80. 60.]
5.算术平均数
a = np.array([[1,2,3],[3,4,5],[4,5,6]])
print ('我们的数组是:')
print (a)
print ('\n')
print ('调用 mean() 函数:')
print (np.mean(a))
print ('\n')
print ('沿轴 0 调用 mean() 函数:')
print (np.mean(a, axis = 0))
print ('\n')
print ('沿轴 1 调用 mean() 函数:')
print (np.mean(a, axis = 1))
我们的数组是:
[[1 2 3]
[3 4 5]
[4 5 6]]
调用 mean() 函数:
3.6666666666666665
沿轴 0 调用 mean() 函数:
[2.66666667 3.66666667 4.66666667]
沿轴 1 调用 mean() 函数:
[2. 4. 5.]
6.加权平均数
在给定期权的时候,是加权平均数,如果没给定权重,那就是算术平均值
a = np.array([1,2,3,4])
print ('我们的数组是:')
print (a)
print ('\n')
print ('调用 average() 函数:')
print (np.average(a))
print ('\n')
# 不指定权重时相当于 mean 函数
wts = np.array([4,3,2,1])
print ('再次调用 average() 函数:')
print (np.average(a,weights = wts))
print ('\n')
# 如果 returned 参数设为 true,则返回权重的和
print ('权重的和:')
print (np.average([1,2,3, 4],weights = [4,3,2,1], returned = True))
print('-----')
a = np.arange(9).reshape(3,3)
wt = np.array([1,4,7])
print (np.average(a, axis = 1, weights = wt))
我们的数组是:
[1 2 3 4]
调用 average() 函数:
2.5
再次调用 average() 函数:
2.0
权重的和:
(2.0, 10.0)
-----
[1.5 4.5 7.5]
7.标准差
print (np.std([1,2,3,4]))
a = np.array([[1,2,3,4],[5,6,7,8]])
print (np.std(a, axis=1))
1.118033988749895
[1.11803399 1.11803399]
8.方差
print (np.var([1,2,3,4]))
a = np.array([[1,2,3,4],[5,6,7,8]])
print (np.var(a, axis=1))
1.25
[1.25 1.25]
十二.排序
1.快速排序
numpy.sort() 函数返回输入数组的排序副本。函数格式如下:
numpy.sort(a, axis, kind, order)
- a: 要排序的数组
- axis: 沿着它排序数组的轴,如果没有数组会被展开,沿着最后的轴排序, axis=0 按列排序,axis=1 按行排序
- kind: 默认为’quicksort’(快速排序)
- ‘quicksort’(快速排序)
- ‘mergesort’(归并排序)
- ‘heapsort’(堆排序)
- order: 如果数组包含字段,则是要排序的字段
a = np.arange(8).reshape(2,2,2)
print(np.sort(a, axis = 0))
a = np.array([[3,5,2],[1,7,4]])
print(np.sort(a, axis = 1))
print(np.sort(a, axis = 0))
[[[0 1]
[2 3]]
[[4 5]
[6 7]]]
[[2 3 5]
[1 4 7]]
[[1 5 2]
[3 7 4]]
2.argsort
numpy.argsort() 函数返回的是数组值从小到大的索引值。
a = np.array([[3,5,2],[1,7,4]])
print(np.argsort(a,axis=1))
print(np.argsort(a,axis=0))
[[2 0 1]
[0 2 1]]
[[1 0 0]
[0 1 1]]
3.exsort
numpy.lexsort() 用于对多个序列进行排序。把它想象成对电子表格进行排序,每一列代表一个序列,排序时优先照顾靠后的列。
这里举一个应用场景:小升初考试,重点班录取学生按照总成绩录取。在总成绩相同时,数学成绩高的优先录取,在总成绩和数学成绩都相同时,按照英语成绩录取…… 这里,总成绩排在电子表格的最后一列,数学成绩在倒数第二列,英语成绩在倒数第三列。
math = (10, 20, 50, 10)
chinese = (30, 50, 40, 60)
total = (40, 70, 90, 70)
# 将优先级高的项放在后面
ind = np.lexsort((math, chinese, total))
for i in ind:
print(total[i],chinese[i],math[i])
40 30 10
70 50 20
70 60 10
90 40 50
4.argmax和 argmin
numpy.argmax() 和 numpy.argmin()函数分别沿给定轴返回最大和最小元素的索引。
a = np.array([[3,5,2],[1,7,4]])
print(np.argmax(a,axis=1))
print(np.argmin(a,axis=0))
[1 1]
[1 0 0]
5.nonzero
函数返回输入数组中非零元素的索引
a = np.array([[30,40,0],[0,20,10],[0,0,1]])
b = np.nonzero (a)
print (b)
print(a[b])
(array([0, 0, 1, 1, 2]), array([0, 1, 1, 2, 2]))
[30 40 20 10 1]
6.where
numpy.where() 函数返回输入数组中满足给定条件的元素的索引。
x = np.arange(9).reshape(3, 3)
y = np.where(x > 3)
print (y)
print (x[y])
(array([1, 1, 2, 2, 2]), array([1, 2, 0, 1, 2]))
[4 5 6 7 8]
7.extract
numpy.extract() 函数根据某个条件从数组中抽取元素,返回满条件的元素。
x = np.arange(9).reshape(3, 3)
print ('我们的数组是:')
print (x)
# 定义条件, 选择偶数元素
condition = np.mod(x,2) == 0
print ('按元素的条件值:')
print (condition)
print ('使用条件提取元素:')
print (np.extract(condition, x))
我们的数组是:
[[0 1 2]
[3 4 5]
[6 7 8]]
按元素的条件值:
[[ True False True]
[False True False]
[ True False True]]
使用条件提取元素:
[0 2 4 6 8]
8.msort、sort_complex、partition、argpartition
详见网页:
NumPy 排序、条件刷选函数
十三.NumPy IO
说明:
Numpy 可以读写磁盘上的文本数据或二进制数据。
NumPy 为 ndarray 对象引入了一个简单的文件格式:npy。
npy 文件用于存储重建 ndarray 所需的数据、图形、dtype 和其他信息。
1.save
numpy.save() 函数将数组保存到以 .npy 为扩展名的文件中。
a = np.array([1,2,3,4,5])
# 保存到 outfile.npy 文件上
np.save('outfile.npy',a)
# 保存到 outfile2.npy 文件上,如果文件路径末尾没有扩展名 .npy,该扩展名会被自动加上
np.save('outfile2',a)
b = np.load('outfile.npy')
print(b)
[1 2 3 4 5]
2.savez
numpy.savez() 函数将多个数组保存到以 npz 为扩展名的文件中。
numpy.savez(file, *args, **kwds)
- file:要保存的文件,扩展名为 .npz,如果文件路径末尾没有扩展名 .npz,该扩展名会被自动加上。
- args: 要保存的数组,可以使用关键字参数为数组起一个名字,非关键字参数传递的数组会自动起名为 arr_0, arr_1, … 。
- kwds: 要保存的数组使用关键字名称。
a = np.array([[1,2,3],[4,5,6]])
b = np.arange(0, 1.0, 0.1)
c = np.sin(b)
# c 使用了关键字参数 sin_array
np.savez("runoob.npz", a, b, sin_array = c)
r = np.load("runoob.npz")
print(r.files) # 查看各个数组名称
print(r["arr_0"]) # 数组 a
print(r["arr_1"]) # 数组 b
print(r["sin_array"]) # 数组 c
['sin_array', 'arr_0', 'arr_1']
[[1 2 3]
[4 5 6]]
[0. 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9]
[0. 0.09983342 0.19866933 0.29552021 0.38941834 0.47942554
0.56464247 0.64421769 0.71735609 0.78332691]
3.savetxt
savetxt() 函数是以简单的文本文件格式存储数据,对应的使用 loadtxt() 函数来获取数据。
a = np.array([1,2,3,4,5])
np.savetxt('out.txt',a)
b = np.loadtxt('out.txt')
print(b)
a=np.arange(0,10,0.5).reshape(4,-1)
np.savetxt("out2.txt",a,fmt="%d",delimiter=",") # 改为保存为整数,以逗号分隔
b = np.loadtxt("out2.txt",delimiter=",",dtype=np.int8) # load 时也要指定为逗号分隔
print(b)
[1. 2. 3. 4. 5.]
[[0 0 1 1 2]
[2 3 3 4 4]
[5 5 6 6 7]
[7 8 8 9 9]]
后记
还有许多函数是没有记录的,因为我觉得可能用不到,先将就用这些函数吧,有需要的后面再添加与补充。然后文章是由jupyter导出的.md直接复制过来的。。。