Python中numpy的使用:
Numpy:
numpy
是python
的一个扩展库,支持大量的维度数组和矩阵计算,此外,也针对数组运算提供大量的数学函数库.numpy
可用来存储和处理大量矩阵,比python
自带列表结构要高效的多.
numpy是一个运行速度非常快的数学库,主要用于计算数组,包含:
- 一个强大的N组数组对象
ndarry
- 广播功能函数
- 整合
C/C++/Fortran
代码工具 - 线性代数,傅里叶变换,随机数生成等功能
ndarray:
numpy
最重要的一个对象是其N
维数组对象ndarray
,它是一系列同类型的数据集合,可以使用基于0的索引访问集合中项目.
ndarray
对象是用于存放同类型元素的多维数组.ndarray
中每个元素在内存中使用相同存储大小的区域,ndarray
中每个元素是数据类型对象的对象(dtype
)
创建一个ndarray只需要调用numpy的array函数,语法:
numpy.array(object,dtype = None,ndmin = 0,copy = True,order = None,subok = False)
一般只有object,dtype和ndmin参数常用
参数 | 描述 |
---|---|
object | 数组或嵌套的数列 |
dtype | 数组或元素的数据类型,可选 |
ndmin | 指定生成数组的最小维度 |
copy | 对象是否需要复制,可选 |
order | 创建数组的样式,C是行方向,F为列方向,A为任意方向(默认) |
subok | 默认返回一个与基类类型一致的数组 |
a = numpy.array([1,2,3]) b = numpy.array([[1,2,3],[4,5,6]]) c = numpy.array([1,2,3],dtype=complex) d = numpy.array([1,2,3],ndmin=2) e = numpy.array([1,2,3],ndmin=3) print(a,type(a)) print(b,type(b)) print(c,type(c)) print(d,type(d)) print(e,type(e)) ################## [1 2 3] <class 'numpy.ndarray'> [[1 2 3] [4 5 6]] <class 'numpy.ndarray'> [1.+0.j 2.+0.j 3.+0.j] <class 'numpy.ndarray'> [[1 2 3]] <class 'numpy.ndarray'> [[[1 2 3]]] <class 'numpy.ndarray'>
numpy数据类型:
numpy支持数据类型比python的内置的类型多得多,基本上可以和C语言的数据类型对应上,其中部分对应为python内置的类型.
名称 | 描述 |
---|---|
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 位浮点数(实数部分和虚数部分) |
数据类型对象:
数据类型对象是用来描述与数组对应的内存区域如何使用,这依赖如下几个方面:
- 数据的类型
- 数据的大小
- 数据的字节顺序
- 在结构化类型的情况下,字段的名称,每个字段的数据类型和每个字段所取内存块的部分.
- 如果数据类型是子数组,他的形状,数据类型
字节顺序是通过对数据类型预先设定"<"或">"来决定的。"<"意味着小端法(最小值存储在最小的地址,即低位组放在最前面)。">"意味着大端法(最重要的字节存储在最小的地址,即高位组放在最前面)。
dtype对象的语法:
numpy.dtype(object,align,copy)
- object:要转换的数据类型
- align:如果为true,填充字段使其类似C的结构体
- copy:复制dtype对象,如果是false,则对内置数据类型对象的引用.
import numpy as np a = np.dtype(np.int32) print('a:',a) # int8, int16, int32, int64 四种数据类型可以使用字符串 'i1', 'i2','i4','i8' 代替 b = np.dtype('i1') print('b:',b) c = np.dtype('<i2') print('c:',c) #创建结构化数据类型 d = np.dtype([('age',np.int8)]) print('d:',d) #将数据类型应用于 ndarray 对象 dt = np.dtype([('age',np.int8)]) a = np.array([(10,),(20,),(30,)], dtype = dt) print('a:',a) print('a["age"]:',a['age']) ################################# a: int32 b: int8 c: int16 d: [('age', 'i1')] a: [(10,) (20,) (30,)] a["age"]: [10 20 30]
numpy数组属性:
numpy
数组维数成为秩,一位数组的秩为1.
在numpy
中,每一个线性的数组称为一个轴(axis),也就是维度,比如二维数组相当于两个一维数组,其中第一个一维数组中的每个元素又是一个一维数组,所以说一维数组就是numpy
的轴,第一个轴相当于底层数组,第二个轴是底层数组里的数组.而轴的数量就是秩,就是数组的维数.
很多时候可以声明axis,axis=0,表示沿着第0轴进行操作,即对每一列进行操作;axis = 1,表示沿着第一轴进行操作,即对每一行进行操作.
ndarry
对象属性有:
属性 | 说明 |
---|---|
ndarry.ndim | 秩,即轴的数量或者维度的数量 |
ndarry.shape | 数组的维度,对于矩阵,n行m列 |
ndarry.size | 数组元素的总个数,相当于.shape中的n*m的值 |
ndarry.dtype | ndarry对象的元素类型 |
ndarry.itemsize | ndarry对象的每个元素的大小,以字节为单位 |
ndarry.flags | ndarry对象的内存信息 |
ndarry.real | ndarry元素的实部 |
ndarry.image | ndarry元素的虚部 |
ndarry.data | 包含实际数组的缓冲区,由于一般通过数组的索引获取元素,所以通常不需要使用这个属性 |
常见情形:
ndarray.shape
这一数组属性返回一个包含数组维度的元组,他可以用来调整数组大小
import numpy a = numpy.array([[1,2,3],[4,5,6],[7,8,9]]) print(a.shape) a.shape = (1,9) print(a) a.shape = (9,1) print(a) ########### (3, 3)#a.shape返回的是元组形式,表示3行3列 [[1 2 3 4 5 6 7 8 9]]#返回a的数据格式 [[1] [2] [3] [4] [5] [6] [7] [8] [9]]#返回a的数据格式
ndarray.ndim
:这一数组属性的返回数组的维度
import numpy a = numpy.arange(24)#声明一个一维数组.元素是0-23个列表数据 print('a:',a) print('a.ndim:',a.ndim) b = a.reshape((2,3,4))#分成2个部分,3个一组,1组里有4个元素 print('b:',b) print('b.ndim:',b.ndim)#判断维数可以看外层括号个数 c= numpy.array([1,2,3,4,5,6,7,8]) print('c.ndim:',c.ndim) d = c.reshape((2,4))#变成的新形状中所包含的元素个数必须符合原来元素个数2*4=8 print('d>>>',d) print('d.ndim:',d.ndim) e = c.reshape((2,2,2)) print('e>>>',e) print('e.ndim:',e.ndim) f = numpy.array([[1,1,1],[2,2,2]]) print('f.ndim:',f.ndim) ########################### a: [ 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.ndim: 1 b: [[[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11]] [[12 13 14 15] [16 17 18 19] [20 21 22 23]]] b.ndim: 3 c.ndim: 1 d>>> [[1 2 3 4] [5 6 7 8]] d.ndim: 2 e>>> [[[1 2] [3 4]] [[5 6] [7 8]]] e.ndim: 3 f.ndim: 2
ndarray.itemsize
:这一数组属性返回数组中每个元素的字节单位长度
a = numpy.array([1,2,3]) print(a.ndim) print(a.itemsize) ############ 1 4
ndarray.flags
返回ndarry
对象的内存信息,包含以下属性:
属性 | 描述 |
---|---|
C_CONTIGUOUS (C) | 数据是在一个单一的C风格的连续段中 |
F_CONTIGUOUS (F) | 数据是在一个单一的Fortran风格的连续段中 |
OWNDATA (O) | 数组拥有它所使用的内存或从另一个对象中借用它 |
WRITEABLE (W) | 数据区域可以被写入,将该值设置为 False,则数据为只读 |
ALIGNED (A) | 数据和所有元素都适当地对齐到硬件上 |
UPDATEIFCOPY (U) | 这个数组是其它数组的一个副本,当这个数组被释放时,原数组的内容将被更新 |
x = np.array([1,2,3,4,5]) print(x.flags) ########################## C_CONTIGUOUS : True F_CONTIGUOUS : True OWNDATA : True WRITEABLE : True ALIGNED : True WRITEBACKIFCOPY : False UPDATEIFCOPY : False
Numpy创建数组:
ndarray数组除了可以使用底层ndarray构造器来创建外,还可以通过如下的方式
numpy.empty
numpy.empty
方法用来创建一个指定形状(shape
),数据类型(dtype
),且未初始化的数组:
numpy.empty(shape,dtype=float,order = 'C')
参数 | 描述 |
---|---|
shape | 数组形状 |
dtype | 数据类型,可选(默认浮点) |
order | 有"C"和"F"两个选项,分别代表,行优先和列优先,在计算机内存中的存储元素的顺序。 |
x = np.empty([3,2],dtype=int) print(x) print(x.ndim) ########################## [[-1704306576 32766] [-1704301984 32766] [ 0 0]] 2 #注意:数组的元素为随机值,因为他们未初始化.
2.numpy.zeros
创建指定大小的数组,数组元素以0来填充:
参数 | 描述 |
---|---|
shape | 数组形状 |
dtype | 数据类型,可选(默认浮点) |
order | 'C' 用于 C 的行数组,或者 'F' 用于 FORTRAN 的列数组 |
# 默认为浮点数 x = np.zeros(5) print(x) # 设置类型为整数 y = np.zeros((5,), dtype = np.int) print(y) # 自定义类型,i4=int32 z = np.zeros((2, 2), dtype=[('x', 'i4'), ('y', 'f')]) print(z) ######################### [0. 0. 0. 0. 0.]#五个浮点数 [0 0 0 0 0]#五个整数 [[(0, 0.) (0, 0.)] [(0, 0.) (0, 0.)]]#2维数组,x坐标轴维整数int32,y坐标轴浮点型f
3.numpy.ones
创建指定形状的数组,数组元素以1来填充:
numpy.ones(shape,dtype = None,order = "C")
参数 | 描述 |
---|---|
shape | 数组形状 |
dtype | 描述数据类型,可选(默认浮点) |
order | 'C' 用于 C 的行数组,或者 'F' 用于 FORTRAN 的列数组 |
# 默认为浮点数 x = np.ones(5) print(x) # 自定义类型 x = np.ones([2,2], dtype = int) print(x) ############################# [1. 1. 1. 1. 1.] [[1 1] [1 1]]
numpy从已有的数组创建数组:
1.numpy.asarray
类似于numpy.array,
将现有的数组或者元组变成ndarray
对象
import numpy as np a = [[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]],[[13, 14, 15, 16], [17, 18, 19, 20], [21, 22, 23, 24]]] b = np.array(a,dtype=int) c = np.asarray(a,dtype=int) print('b:',b) print('c:',c) #################################### b: [[[ 1 2 3 4] [ 5 6 7 8] [ 9 10 11 12]] [[13 14 15 16] [17 18 19 20] [21 22 23 24]]] c: [[[ 1 2 3 4] [ 5 6 7 8] [ 9 10 11 12]] [[13 14 15 16] [17 18 19 20] [21 22 23 24]]]
numpy.asarray(a,dtype=None,order = None)
参数 | 描述 |
---|---|
a | 任意形式的输入参数,可以是,列表, 列表的元组, 元组, 元组的元组, 元组的列表,多维数组 |
dtype | 数据类型,可选 |
order | 可选,有"C"和"F"两个选项,分别代表,行优先和列优先,在计算机内存中的存储元素的顺序。 |
x = [1,2,3] a = np.asarray(x) print(a) x = (1,2,3) a = np.asarray(x) print(a) x = [(1,2,3),(4,5)] a = np.asarray(x) print(a) x = [1,2,3] a = np.asarray(x,dtype=float) print(a) ########################## [1 2 3] [1 2 3] [(1, 2, 3) (4, 5)] [1. 2. 3.]
2.numpy.frombuffer
用于实现动态数组,numpy.frombuffer
接收buffer输入参数,以流的形式读入转成ndarray
对象.
numpy.frombuffer(buffer,dtype=float,count = -1,offset=0)
参数 | 描述 |
---|---|
buffer | 可以是任何对象,会以流的形式读入 |
dtype | 返回数组的数据类型,可选 |
count | 读取的数据数量,默认为-1,读取所有数据 |
offset | 读取的起始位置,默认是0 |
s = b'hello miller' a = np.frombuffer(s,dtype='S1') b = np.frombuffer(s,dtype='S1',count=4) c = np.frombuffer(s,dtype='S1',count=3,offset=4) print(a) print(b) print(c) ########################### #count表示读取个数,默认为-1,是读取所有 #offset是从哪个索引开始去读 [b'h' b'e' b'l' b'l' b'o' b' ' b'm' b'i' b'l' b'l' b'e' b'r'] [b'h' b'e' b'l' b'l'] [b'o' b' ' b'm']
4.numpy.fromiter
从迭代对象中建立ndarray
对象,返回一维数组.
numpy.fromiter(iterable,dtype,count=-1)
参数 | 描述 |
---|---|
iterable | 可迭代对象 |
dtype | 返回数组的数据类型 |
count | 读取的数据数量,默认为-1,读取所有数据 |
lis = range(6) it = iter(lis) x = np.fromiter(it,dtype=float) print(x) lis = range(6) x = np.fromiter(lis,dtype=float) print(x) ######################### [0. 1. 2. 3. 4. 5.] [0. 1. 2. 3. 4. 5.]
numpy从数值范围创建数组:
1.numpy.arange
numpy包中的使用arrange函数创建数值范围并返回ndarray对象,函数格式如下:
numpy.arange(start,stop,step,dtype)
这里start
与stop
指定范围以及step
设定的步长,生成一个ndarray
参数 | 描述 |
---|---|
start | 起始值,默认是0 |
stop | 终止值 |
step | 步长,默认是1 |
dtype | 返回ndarray 的数据类型,如果没有提供,则会使用输入数据的类型。 |
x = np.arange(5) y = np.arange(5,dtype=float) z = np.arange(10,30,5) print(x) print(y) print(z) ################################ [0 1 2 3 4] [0. 1. 2. 3. 4.] [10 15 20 25]
2.numpy.linspace
numpy.linspace
函数用于创建一个一维数组,数组是一个等差数列构成的,格式如下:
np.linspace(start,stop,num=50,endpoint=True,retstep=False,dtype=None)
参数 | 描述 |
---|---|
start | 序列的起始值 |
stop | 序列的终止值,如果endpoint 为true ,该值包含于数列中 |
num | 要生成的等步长的样本数量,默认为50 |
endpoint | 该值为 ture 时,数列中中包含stop 值,反之不包含,默认是True。 |
retstep | 如果为 True 时,生成的数组中会显示间距,反之不显示。 |
dtype | ndarray 的数据类型 |
a = np.linspace(1,10,num=5,endpoint=True,retstep=True,dtype='i4') b = np.linspace(1,10,num=5,endpoint=False,retstep=True) print(a) print(b) ############################ (array([ 1, 3, 5, 7, 10]), 2.25)#步长是2.25,endpoint=True数列中包含stop值,数据类型是整型 (array([1. , 2.8, 4.6, 6.4, 8.2]), 1.8)#步长是1.8,endpoint=False数列中不包含stop值,默认是浮点型
3.numpy.logspace
numpy.logspace
函数用于创建一个等比数列,格式如下:
np.logspace(start,stop,num = 50,endpoint=True,base=10.0,dtype=None)
这里,base参数的意思是取对数的时候log下标.
参数 | 描述 |
---|---|
start | 序列的起始值是:base**start |
stop | 序列的终止值是:base**stop,如果endpoint为True,该数值包含于数列中 |
num | 要生成的等步长的样本数量,默认值是50 |
endpoint | 该值为true,数列中包含stop值,反之不包含,默认是true |
base | 对数log的底数 |
dtype | ndarray的数据类型 |
a = np.logspace(1.0,1.8,num=5,base=10.0) print(a) ############################# [10. 15.84893192 25.11886432 39.81071706 63.09573445] #15.84893192=10^1.2
numpy切片和索引:
ndarray
对象的内容可以通过索引或切片来访问和修改,与python
的list
切片操作一样.
ndarray
数组可以基于0-n``的下标进行索引,切片对象可以通过内置的
slice函数,并设置
start,stop及step
参数进行,从原数组中切割出新的一个数组.
import numpy as np a = np.arange(10) s = slice(2,7,2) t = a[2:7:2] print(a[s]) print(a[t]) ################################### # [2 4 6] [2 4 6]
多维数组同样适合上述索引提取方法:
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])#行是都取的,列是取索引为1的列 print(a[1,...])#行是取索引是1的,行是都取的 print(a[1,1:])#行是取索引是1的,列是取索引从1到末尾的. ########################## [2 5 8] [4 5 6] [5 6]
取数组中不相邻的元素:
import numpy as np a = np.array([[1,2,3],[4,5,6],[7,8,9]]) print(a) c = a[[0,2,1],[0,1,1]] print(c) ############################## [[1 2 3] [4 5 6] [7 8 9]] [1 8 5]#[0,2,1],[0,1,1]表示(0,0),(2,1),(1,1)
高级索引:
numpy比一般的python序列提供更多的索引方式,除了之前看到的用整数和切片的索引之外,数组可以由整数数组索引,布尔索引及花式索引.
整数数组索引:
这种机制有助于基于N维索引来获取组中的任意元素,每个整数数组表示该维度的下标值.当索引的元素个数就是目标ndarray
的维度时,会变得相当直接.
x=np.array([[0,1,2],[3,4,5],[6,7,8],[9,8,10]]) print('x:',x) rows = np.array([[0,0],[3,3]]) #行索引是(0,0)(3,3) cols = np.array([[0,2],[0,2]]) #列索引是(0,2)(0,2) y = x[rows,cols] print('y:',y) ####################### x: [[ 0 1 2] [ 3 4 5] [ 6 7 8] [ 9 8 10]] y: [[ 0 2] [ 9 10]]
布尔索引:
我们可以通过布尔数组来索引目标数组
布尔索引通过布尔运算来获取符合指定条件的元素的数组.
x = np.array([[ 0, 1, 2],[ 3, 4, 5],[ 6, 7, 8],[ 9, 10, 11]]) print ('我们的数组是:') print (x) print(x<5) print ('\n') # 现在我们会打印出大于 5 的元素 print ('大于 5 的元素是:') print (x[x > 5]) ##################### 我们的数组是: [[ 0 1 2] [ 3 4 5] [ 6 7 8] [ 9 10 11]] [[ True True True] [ True True False] [False False False] [False False False]] 大于 5 的元素是: [ 6 7 8 9 10 11]
~
(取补运算)过滤NaN
a = np.array([np.nan, 1,2,np.nan,3,4,5]) print (a[~np.isnan(a)]) a = np.array([1, 2+6j, 5, 3.5+5j]) print (a[np.iscomplex(a)]) ###################### [ 1. 2. 3. 4. 5.] [2.0+6.j 3.5+5.j]
我们可以通过一个布尔数组来索引目标数组,以此找出与布尔数组中值为True的对应的目标数组中的数据(后面通过实例可清晰的观察)。需要注意的是,布尔数组的长度必须与目标数组对应的轴的长度一致。下面通过几个例子来说明。
一维数组的索引
布尔数组中,下标为0,3,4的位置是True,因此将会取出目标数组中对应位置的元素。
import numpy as np a = np.arange(7) print('a:',a) bo = np.array([True,False,False,True,True,False,False]) print('a[bo]:',a[bo]) ######################## a: [0 1 2 3 4 5 6] a[bo]: [0 3 4]
二维数组的索引
布尔数组中,下标为0,3,4的位置是True,因此将会取出目标数组中第0,3,4行。
#二维数组的bool索引 arr = np.arange(28).reshape((7,4)) print('arr:',arr) booling1 = np.array([True,False,False,True,True,False,False]) print('arr[booling1]:',arr[booling1]) ############################ arr: [[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11] [12 13 14 15] [16 17 18 19] [20 21 22 23] [24 25 26 27]] arr[booling1]: [[ 0 1 2 3] [12 13 14 15] [16 17 18 19]]
通过逻辑运算把属于Ben的明细找了出来。那如果我们想查找不属于Ben的明细,则可以通过!=或者~运算。
arr = np.arange(28).reshape((7,4)) print('arr:',arr) names = np.array(['Ben','Tom','Ben','Jeremy','Jason','Michael','Ben']) print('>>',names == 'Ben') print('>>',arr[names == 'Ben']) print('>>',arr[names == 'Ben',3]) print('>>',arr[names == 'Ben',1:4]) ########################### arr: [[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11] [12 13 14 15] [16 17 18 19] [20 21 22 23] [24 25 26 27]] >> [ True False True False False False True] >> [[ 0 1 2 3] [ 8 9 10 11] [24 25 26 27]] >> [ 3 11 27] >> [[ 1 2 3] [ 9 10 11] [25 26 27]]
花式索引:
花式索引是NumPy用来描述使用整型数组(这里的数组,可以是NumPy的数组,也可以是python自带的list)作为索引的术语,其意义是根据索引数组的值作为目标数组的某个轴的下标来取值。对于使用一维整型数组作为索引,如果目标是一维数组,那么索引的结果就是对应位置的元素;如果目标是二维数组,那么就是对应下标的行。
arr = np.array(['zero', 'one', 'two', 'three', 'four']) print(arr[[1,4]]) arr = np.empty((8,4),dtype=np.int) for i in range(8): arr[i] = i print(arr) print(arr[[4,3,0,6]]) #拿取arr数组的第4(索引)行,第3(索引)行,第0(索引)行,第6(索引)行 print(arr[[-3,-5,-7]]) #拿取arr数组的第-3(索引)行,第-5(索引)行,第-7(索引)行 ########################### ['one' 'four'] [[0 0 0 0] [1 1 1 1] [2 2 2 2] [3 3 3 3] [4 4 4 4] [5 5 5 5] [6 6 6 6] [7 7 7 7]] [[4 4 4 4] [3 3 3 3] [0 0 0 0] [6 6 6 6]] [[5 5 5 5] [3 3 3 3] [1 1 1 1]]
a = np.arange(42).reshape(6,7) print('a:',a) print('a[[1,3,5]]:',a[[1,3,5]])#取得索引第1,3,5行 print('a[[1,3,5],[2,4,6]]:',a[[1,3,5],[2,4,6]])#针对不相邻的元素取值(1,2)(3,4)(5,6) ####################### a: [[ 0 1 2 3 4 5 6] [ 7 8 9 10 11 12 13] [14 15 16 17 18 19 20] [21 22 23 24 25 26 27] [28 29 30 31 32 33 34] [35 36 37 38 39 40 41]] a[[1,3,5]]: [[ 7 8 9 10 11 12 13] [21 22 23 24 25 26 27] [35 36 37 38 39 40 41]] a[[1,3,5],[2,4,6]]: [ 9 25 41]
numpy中的三元运算符:
import numpy as np t = np.arange(24).reshape(4,6) print('t:',t) s = np.where(t<10,0,11) #小于10的替换成0,大于等于替换成11 print('s:',s) ####################### t: [[ 0 1 2 3 4 5] [ 6 7 8 9 10 11] [12 13 14 15 16 17] [18 19 20 21 22 23]] s: [[ 0 0 0 0 0 0] [ 0 0 0 0 11 11] [11 11 11 11 11 11] [11 11 11 11 11 11]]
numpy中的clip(裁剪):
t = np.arange(24).reshape(4,6) print('t:',t) s = np.clip(t,10,12) print('s:',s) #################### t: [[ 0 1 2 3 4 5] [ 6 7 8 9 10 11] [12 13 14 15 16 17] [18 19 20 21 22 23]] s: [[10 10 10 10 10 10] [10 10 10 10 10 11] [12 12 12 12 12 12] [12 12 12 12 12 12]]
numpy广播:
形状相同:
广播是numpy对不同形状的数组进行数值计算,对数组的算术运算在相应的元素上进行.
如果两个数组a,b形状相同,既满足a.shape=b.shape,那么a*b的结果就是a与b数组对应位相乘,这要求维数相同,且各维度的长度相同
a = np.array([1,2,3,4]) b = np.array([6,6,6,6]) c = a*b print(c)#不是线性代数上的行列式运算规则 ####################### [ 6 12 18 24]
形状不同
当数组大小不一致时,就会触发广播机制:
1.让所有输入数组都向其中shape最长的数组看齐,shape中不足的部分都通过前面加1补齐.
2.输出的数组的shape是输入数组shape的各大轴上的最大值.
3.如果输入数组的某个轴和输出数组的对应轴的长度相同或者其长度为1时,这个数组能够用来计算,否则出错;
4.如果输入数组的某个轴和输出数组的对应轴的长度相同或者其长度为1时,这个数组能够用来计算,否则出错;
更通俗的解释:
将两个数组的维度大小右对齐,然后比较对应维度上的数值,如果数值相等或其中有一个为1或者为空,则能进行广播运算,并且输出的维度大小为去数值大的数值,否则不能进行数组运算
#违背数值相等,其中一个为1或者是空: #右对齐: #2 3 #2 2 a = np.arange(6).reshape(2,3) print('a:',a) print('a.shape:',a.shape) b = np.arange(4).reshape(2,2) print('b:',b) print('b.shape',b.shape) c = a * b print('c:',c) ############################## ValueError: operands could not be broadcast together with shapes (2,3) (2,2) #报错信息是不能触发广播机制,数组维度(2,3)(2,2)
#满足数组的对应轴长度相同: #2 3 #2 3(可以运算) a = np.arange(6).reshape(2,3) print('a:',a) print('a.shape:',a.shape) b = np.arange(6).reshape(2,3) print('b:',b) print('b.shape',b.shape) c = a * b print('c:',c) ######################### a: [[0 1 2] [3 4 5]] a.shape: (2, 3) b: [[0 1 2] [3 4 5]] b.shape (2, 3) c: [[ 0 1 4] [ 9 16 25]]
#满足其中一个数组的对应轴长度是1或者为空: #2 3 # 1(可以进行运算) a = np.arange(6).reshape(2,3) print('a:',a) print('a.shape:',a.shape) #b是一个轴是1,另一个是空 b = np.asarray([2,]) print('b:',b) print('b.shape',b.shape) c = a * b print('c:',c) ############################# a: [[0 1 2] [3 4 5]] a.shape: (2, 3) b: [2] b.shape (1,) c: [[ 0 2 4] [ 6 8 10]]
再实验一个例子:a数组大小是(2,1,3),b数组大小(4,1):
#首先右对齐: #2 1 3 # 4 1(可以进行运算) a = np.arange(6).reshape(2,1,3) print(a) b = np.arange(4).reshape(4,1) print(b) d = b+a print(d) ########################## a; [[[0 1 2]] [[3 4 5]]] b: [[0] [1] [2] [3]] d: [[[0 1 2] [1 2 3] [2 3 4] [3 4 5]] [[3 4 5] [4 5 6] [5 6 7] [6 7 8]]]
再实验一个例子:a数组大小是(2,1,3),b数组大小(4,2):
#首先右对齐: #2 1 3 # 4 2(不可以进行运算) a = np.arange(6).reshape(2,1,3) print('a;',a) c = np.arange(8).reshape(4,2) print(c) e = c+a print('e:',e) ########################### ValueError: operands could not be broadcast together with shapes (4,2) (2,1,3)
广播机制总结:
广播机制能够处理不同大小的数组,数组之间必须满足广播规则,否则会报错,事实上,相同大小的数组运算也遵循广播机制
numpy数组转置和轴对换:
数组转置transpose()
和T
,swapaxes
:
1.T
适合一,二维数组
a = np.arange(12).reshape(3, 4) print('a:',a) print('a.transpose():',a.transpose()) print('a.T:',a.T) ############################### a: [[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11]] a.transpose(): [[ 0 4 8] [ 1 5 9] [ 2 6 10] [ 3 7 11]] a.T: [[ 0 4 8] [ 1 5 9] [ 2 6 10] [ 3 7 11]]
2.高维数组:
对于高维数组,transpose()
需要用到一个周编号组成的元组,才能进行转置.
对于多维数组来说,确定最底层的一个基本元素位置需要用到的索引个数即是维度.
注意:对于二维ndarray.transpose()
在不指定参数的情况下,默认是矩阵转置,如果指定参数,有如下相应结果:
a = np.arange(4).reshape(2,2) print('a:',a) b = a.transpose() print('b:',b) c = a.transpose(0,1) print('c:',c) d = a.transpose(1,0) print('d:',d) ######################### a: [[0 1] [2 3]] b: [[0 2] [1 3]] c: [[0 1] [2 3]] d: [[0 2] [1 3]]
这里x\[0][0]==0,x\[0][1]==1,x\[1][0]==2,x\[1][1]==3
设置第一个[]为0轴,第二个[]为1轴:
a.transpose(0,1)表示按照原坐标轴改变顺序,也就是保持不变.
a.transpose(1,0)表示按照原坐标轴改变顺序,如图所示:
注意:任何时候都要保持清醒,告诉自己第一个方括号是0轴,第二个方括号是1轴.
再看看三维空间的:
a = np.arange(16).reshape(2,2,4) print('a:',a) #保持坐标轴不变 print('>>>',a.transpose(0,1,2)) #保持2轴不变,交换0和1轴 print('>>>',a.transpose(1,0,2)) ############################### a: [[[ 0 1 2 3] [ 4 5 6 7]] [[ 8 9 10 11] [12 13 14 15]]] >>> [[[ 0 1 2 3] [ 4 5 6 7]] [[ 8 9 10 11] [12 13 14 15]]] >>> [[[ 0 1 2 3] [ 8 9 10 11]] [[ 4 5 6 7] [12 13 14 15]]]
如图:
经变换后:
3.swapaxes
numpy.swapaxes函数用于交换数组的两个轴,格式如下:
numpy.swapaxes(arr,axis1,axis2)
arr:输入数组
axis1
:对应第一个轴的整数axis2
:对应第二个轴的整数
a = np.arange(8).reshape(2,2,2) print('原数组:') print(a) print('\n') print('调用swapaxes函数:') print(np.swapaxes(a,2,0)) ########################### 原数组: [[[0 1] [2 3]] [[4 5] [6 7]]] 调用swapaxes函数: [[[0 4] [2 6]] [[1 5] [3 7]]]
4.做矩阵的内积:.dot()
a = np.arange(12).reshape(3, 4) #矩阵的内积 print('内积:',np.dot(a.T,a)) print('内积:',np.dot(a,a.T)) ############################ 内积: [[ 80 92 104 116] [ 92 107 122 137] [104 122 140 158] [116 137 158 179]] 内积: [[ 14 38 62] [ 38 126 214] [ 62 214 366]]
numpy迭代数组:
1.NumPy 包包含一个迭代器对象numpy.nditer
。 它是一个有效的多维迭代器对象,可以用于在数组上进行迭代。 数组的每个元素可使用 Python 的标准Iterator
接口来访问。
让我们使用arange()
函数创建一个 3X4 数组,并使用nditer
对它进行迭代。
# numpy.nditer a = np.arange(6).reshape(2,3) print ('原始数组是:') print (a) print ('\n') print ('迭代输出元素:') for x in np.nditer(a):#对ndarray对象的迭代器 print (x, end=", " ) print ('\n') for x in np.nditer(a.T):#对ndarray对象的迭代器 print (x, end=", " ) print ('\n') ############################## 原始数组是: [[0 1 2] [3 4 5]] 迭代输出元素: 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5,
注意:输出顺序与数组的内存布局一致,这样做是为了提升访问效率,默认是行序优先.
从上面的实例可以看出,a
与a.T
的遍历顺序是一样的,也就是说他们在内存中存储顺序是一样的,那么我们如何控制输出顺序呢?
for x in np.nditer(a,order='F')
Fortran order即列序优先for x in np.nditer(a,order='C')
C order 即行序优先
a = np.arange(6).reshape(2,3) print ('原始数组是:') print (a) print ('\n') print('转置:',a.T) print ('a迭代输出元素:') for x in np.nditer(a):#对ndarray对象的迭代器 print (x, end=", " ) print ('\n') print ('a,order="C"') for x in np.nditer(a,order='C'):#对ndarray对象的迭代器 print (x, end=", " ) print ('\n') print ('a,order="F"') for x in np.nditer(a,order='F'):#对ndarray对象的迭代器 print (x, end=", " ) print ('\n') print ('a.T,order="C"') for x in np.nditer(a.T,order='C'):#对ndarray对象的迭代器 print (x, end=", " ) print ('\n') print ('a.T:') print ('a.T,order="F"') for x in np.nditer(a.T,order='F'):#对ndarray对象的迭代器 print (x, end=", " ) print ('\n') print ('a.T:') for x in np.nditer(a.T):#对ndarray对象的迭代器 print (x, end=", " ) print ('\n') ############################ 原始数组是: [[0 1 2] [3 4 5]] 转置: [[0 3] [1 4] [2 5]] a迭代输出元素: 0, 1, 2, 3, 4, 5, a,order="C" 0, 1, 2, 3, 4, 5, a,order="F" 0, 3, 1, 4, 2, 5, a.T,order="C" 0, 3, 1, 4, 2, 5, a.T: a.T,order="F" 0, 1, 2, 3, 4, 5, a.T: 0, 1, 2, 3, 4, 5, #循环出来的是单个元素,并非数组形式
修改数组中元素的顺序:
nditer 对象有另一个可选参数 op_flags。 默认情况下,nditer 将视待迭代遍历的数组为只读对象(read-only),为了在遍历数组的同时,实现对数组元素值得修改,必须指定 read-write 或者 write-only 的模式。
a = np.arange(0,60,5).reshape(3,4) print ('原始数组是:') print (a) print ('\n') for x in np.nditer(a,op_flags=['writeonly']): 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]]
这里readwrite与writeonly的区别:
flags参数:
flags
参数需要传入一个数组或元组,既然参数类型是数组,我原本以为可以传入多个值的,但是,就下面介绍的 4 种常用选项,我试了,不能传多个,例如 flags=['f_index', 'external_loop']
,运行报错。
1.使用外部循环:external_loop
简单来说,当指定 flags=['external_loop']
时,将返回一维数组而并非单个元素。具体来说,当ndarray
的顺序和遍历的顺序一致时,将所有元素组成一个一维数组返回;当 ndarray
的顺序和遍历的顺序不一致时,返回每次遍历的一维数组(这句话特别不好描述,看例子就清楚了)。
#b是C-order顺序 import numpy as np a = [[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]],[[13, 14, 15, 16], [17, 18, 19, 20], [21, 22, 23, 24]]] b = np.array(a,dtype=int) print('b:',b) print('普通循环:') for x in np.nditer(b): print(x) print('外部循环 c_order:') for x in np.nditer(b,flags=['external_loop'],order='C'): print(x) print('外部循环 f_order:') for x in np.nditer(b,flags=['external_loop'],order='F'): print(x) ################################## b: [[[ 1 2 3 4] [ 5 6 7 8] [ 9 10 11 12]] [[13 14 15 16] [17 18 19 20] [21 22 23 24]]] 普通循环: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 外部循环 c_order: [ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24] 外部循环 f_order: [ 1 13] [ 5 17] [ 9 21] [ 2 14] [ 6 18] [10 22] [ 3 15] [ 7 19] [11 23] [ 4 16] [ 8 20] [12 24]
#此时b的顺序是F-order import numpy as np a = [[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]],[[13, 14, 15, 16], [17, 18, 19, 20], [21, 22, 23, 24]]] b = np.array(a,dtype=int,order='F') print('b:',b) print('普通循环:') for x in np.nditer(b): print(x) print('外部循环 c_order:') for x in np.nditer(b,flags=['external_loop'],order='C'): print(x) print('外部循环 f_order:') for x in np.nditer(b,flags=['external_loop'],order='F'): print(x) ################################## b: [[[ 1 2 3 4] [ 5 6 7 8] [ 9 10 11 12]] [[13 14 15 16] [17 18 19 20] [21 22 23 24]]] 普通循环: 1 13 5 17 9 21 2 14 6 18 10 22 3 15 7 19 11 23 4 16 8 20 12 24 外部循环 c_order: [1 2 3 4] [5 6 7 8] [ 9 10 11 12] [13 14 15 16] [17 18 19 20] [21 22 23 24] 外部循环 f_order: [ 1 13 5 17 9 21 2 14 6 18 10 22 3 15 7 19 11 23 4 16 8 20 12 24]
2.追踪索引:c_index,f_index,multi_index
修改数组的形状:numpy.reshape()
翻转数组:numpy.transpose(),swapaxes(),T
分割数组:split,hsplit()按列分割多个子数组,vsplit()按行分割多个子数组