1.numpy数组对象ndarray参数的测试
1.1 测试ndarray数组类型
import numpy as np
a = [1,2,3]
c = [1,2,3],[12,23,54]
b = np.array(a)#通过对象的创建方法
d = np.array(c)
print(b,type(b))#numpy数组的数据类型为:ndarray
print(d)#多个列表设成ndarray类型会变成多维数组形式[1 2 3] <class 'numpy.ndarray'>
[[ 1 2 3]
[12 23 54]]1.2 测试dtype
import numpy as np
a = [1, 2, 3]
b = np.array(a, dtype=float)
print(b,b.dtype,type(b[0]))[1. 2. 3.] float64 <class 'numpy.float64'>1.3 测试copy参数
import numpy as np
#a = [1,2,3]这是列表,不是对象,无法用array的参数方法
a = np.array([1,12,3])
b = np.array(a,copy = True)#这个首字母只能大写
c = np.array(a,copy = False)
a[0]=0
print(a,b,c)[ 0 12 3] [ 1 12 3] [ 0 12 3]1.4 测试ndmin参数
import numpy as np
a = np.array([1,2,3],ndmin=3)#设置成3维数组
print (a)[[[1 2 3]]]1.5 测试subok
import numpy as np
a = np.matrix('1 2 3;12 32 45;213 213 324' )#matrix为矩阵类型
print(a,type(a))
a1 = np.array(a,subok=True)#使用subok设为True时,类型还是原来的类型
a2 = np.array(a,subok=False)#默认用ndarray对象之后,类型变成ndarray类型
print(type(a1),type(a2))[[ 1 2 3]
[ 12 32 45]
[213 213 324]] <class 'numpy.matrix'>
<class 'numpy.matrix'> <class 'numpy.ndarray'>2.dtype参数的参数
numpy.dtype(object, align, copy)
object - 要转换为的数据类型对象
align - 如果为 true,填充字段使其类似 C 的结构体。
copy - 复制 dtype 对象 ,如果为 false,则是对内置数据类型对象的引用2.1 参数object测试
import numpy as np
a1 = np.dtype(np.int32)#把a1对象数据类型设置成int
a2 = np.dtype('i4')# int8, int16, int32, int64 四种数据类型可以使用字符串 'i1', 'i2','i4','i8' 代替,i代表int,数字*8(1B=8byte)=字节大小
a3 = np.dtype('<i4')#<代表小端法
print(a1,a2,a3)int32 int32 int322.2 结构化的使用
即dtype对象可以跟mysql创建数据结构一样,创建数据名称,数据类型,数据值并应用于ndarray数组import numpy as np
student =np.dtype([('name','S20'),('age','i1'),('mark','f4')])#用列表把对象名称,对象类型分别用括号括起来.,用于存取的列
a = np.array([('wang',12,56.6),('ming',13,78.8)])
print(student)
print(a)[('name', 'S20'), ('age', 'i1'), ('mark', '<f4')]
[['wang' '12' '56.6']
['ming' '13' '78.8']]3.Numpy数组属性
numpy数组类型为ndarray类型,所以使用方法为:ndarray.属性名3.1 ndarray.ndim属性
定义:返回数组维度,即秩大小import numpy as np
a = np.arange(24)#创建一维数组
b = a.reshape(2,4,3)#reshape为修改维度,层数、行数、列数
print(a)
print(b)
print(a.ndim,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]
[[[ 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 33.2 ndarray.shape属性
定义:返回一个包含数组维度的元组,对于矩阵,n 行 m 列,它也可以用于调整数组维度。
同时Numpy也提供reshape(array, newshape, order='C')来修改数组维度,方法一样,但是reshape属性更加多功能
该函数具体实现如下:
首先,根据newshape中的元素构建一个新的空数组,用于存储重排后的元素。
然后,按照order参数指定的顺序,将原数组中的元素逐个复制到新数组中。常用的存储顺序有’C’(按行存储)和’F’(按列存储)两种。
最后,返回新数组
只是 reshape() 通常返回的是非拷贝副本,即改变返回后数组的元素,原数组对应元素的值也会改变
在使用reshape函数时,需要注意保证newshape中的元素之积与原数组中的元素之积相等,以确保重排后的数组不会丢失元素。import numpy as np
a = np.array([[1,2,3],[321,56,643]])
print(a)
print(a.shape)#2*3的矩阵[[ 1 2 3]
[321 56 643]]
(2, 3)import numpy as np
a = np.array([[1,2,3],[321,56,643]])
a.shape=(3,2)#修改维度
print(a)
print(a.shape)
[[ 1 2]
[ 3 321]
[ 56 643]]
(3, 2)import numpy as np
a = np.array([[1,2,3],[321,56,643]])
a.reshape(3,2)#修改矩阵,
print(a)#返回原矩阵,会发现数组a不会改变维度,这是因为reshape是先复制再修改[[ 1 2 3]
[321 56 643]]import numpy as np
a = np.array([[1,2,3],[321,56,643]])
b = a.reshape(3,2)#接收reshape的副本
print(b)#这里就看到副本已经修改了维度[[ 1 2]
[ 3 321]
[ 56 643]]3.3ndarray.flags属性
定义:返回 ndarray 对象的内存信息
C_CONTIGUOUS 数据是在一个单一的C风格的连续段中
F_CONTIGUOUS 数据是在一个单一的Fortran风格的连续段中
OWNDATA 数组拥有它所使用的内存或从另一个对象中借用它
WRITEABLE 数据区域可以被写入,将该值设置为 False,则数据为只读
ALIGNED 数据和所有元素都适当地对齐到硬件上
WRITEBACKIFCOPY UPDATEIFCOPY 已弃用,由 WRITEBACKIFCOPY 取代;
UPDATEIFCOPY 这个数组是其它数组的一个副本,当这个数组被释放时,原数组的内容将被更新import numpy as np
a = np.array([[1,2,3],[321,56,643]])
print(a.flags) C_CONTIGUOUS : True
F_CONTIGUOUS : False
OWNDATA : True
WRITEABLE : True
ALIGNED : True
WRITEBACKIFCOPY : False
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6]])
b = a.reshape((3, 2))#修改a的维度
print(b)
a.flags.writeable = False#打开a只读
b[0][0] = 666#修改b的元素
print(b)
print(a)#反而影响到了a
print(a.flags)
'''
程序执行顺序:
1.先创建2*3的数组a
2.用reshape修改数组a并赋予b返回
3.数组a设为只读
4.修改数组b的元素
5.打印b,a,a的状态
原因:
虽然把 a.flags.writeable 改为了 False(只读),
但是在数组 b 上的操作仍然会影响数组 a,
因为数组 a 和数组 b 共享底层的数据缓冲区。
这是由于 reshape 操作不会创建新的数据副本,
而是使用相同的数据,只是以新的形状进行解释。
'''[[1 2]
[3 4]
[5 6]]
[[666 2]
[ 3 4]
[ 5 6]]
[[666 2 3]
[ 4 5 6]]
C_CONTIGUOUS : True
F_CONTIGUOUS : False
OWNDATA : True
WRITEABLE : False
ALIGNED : True
WRITEBACKIFCOPY : False
4.NumPy 创建数组
ndarray 数组除了可以使用底层 ndarray 构造器来创建外,也可以通过以下几种方式来创建。
属性方法有:
numpy.empty(shape, dtype = float, order = 'C')
numpy.zeros(shape, dtype = float, order = 'C')
numpy.ones(shape, dtype = None, order = 'C')
numpy.zeros_like(a, dtype=None, order='K', subok=True, shape=None)
numpy.ones_like(a, dtype=None, order='K', subok=True, shape=None)4.1 numpy.empty属性
numpy.empty(shape, dtype = float, order = 'C')
创建一个指定形状(shape)、数据类型(dtype)且未初始化的数组
参数说明:
shape以列表的形式表达,例[3,2]为3*2的矩阵
dtype默认为float类型,自己可以设置成其他类型
order参数:C代表行优先存储,F代表列优先存储import numpy as np
a1 = np.empty([2,3],dtype = int,order='C')
print(a1)
#注意 − 数组元素为随机值,因为它们未初始化。[[-1287102048 349 0]
[ 0 131075 1869182064]]4.2numpy.zeros
创建指定大小的数组,数组元素以 0 来填充:
numpy.zeros(shape, dtype = float, order = 'C')
参数说明:
参数 描述
shape 数组形状
dtype 数据类型,可选
order 'C' 用于 C 的行数组,或者 'F' 用于 FORTRAN 的列数组import numpy as np
a1 = np.zeros(5)#[0. 0. 0. 0. 0.]
a2 = np.zeros(5,)#[0. 0. 0. 0. 0.]
#a3 = np.zeros(5,0)#这个是错误的数组没有0列的
a4 = np.zeros((5,1))#5行1列,
a5 = np.zeros((5,),dtype=int)#修改类型为int
a6 = np.zeros((2,2),dtype=[('x','i4'),('y','i4')])
print(a1,a2,a4,a5,a6)
[0. 0. 0. 0. 0.] [0. 0. 0. 0. 0.] [[0.]
[0.]
[0.]
[0.]
[0.]] [0 0 0 0 0] [[(0, 0) (0, 0)]
[(0, 0) (0, 0)]]
总结:numpy.zeros属性
shape为定义数组形状,若定义1行n列则用(n,)即可,若zeros属性只有shape的话,可以只写列数(说明1行的数组,可以省略1不写)
dtype为定义数据结构,默认为float类型,开发人员可以定义其他数据结构和自定义结构4.3 numpy.ones
创建指定形状的数组,数组元素以 1 来填充:
numpy.ones(shape, dtype = None, order = 'C')
参数说明:
参数 描述
shape 数组形状
dtype 数据类型,可选
order 'C' 用于 C 的行数组,或者 'F' 用于 FORTRAN 的列数组
注意:不给例子,因为这个和zeros属性一样,只是填充数字不同而已4.4 numpy.zeros_like
numpy.zeros_like 用于创建一个与给定数组具有相同形状的数组,数组元素以 0 来填充。
numpy.zeros 和 numpy.zeros_like 都是用于创建一个指定形状的数组,其中所有元素都是 0。
它们之间的区别在于:numpy.zeros 可以直接指定要创建的数组的形状,而 numpy.zeros_like 则是创建一个与给定数组具有相同形状的数组。
numpy.zeros_like(a, dtype=None, order='K', subok=True, shape=None)
参数说明:
参数 描述
a 给定要创建相同形状的数组
dtype 创建的数组的数据类型
order 数组在内存中的存储顺序,可选值为 'C'(按行优先)或 'F'(按列优先),默认为 'K'(保留输入数组的存储顺序)
subok 是否允许返回子类,如果为 True,则返回一个子类对象,否则返回一个与 a 数组具有相同数据类型和存储顺序的数组
shape 创建的数组的形状,如果不指定,则默认为 a 数组的形状。
注意:这个参数相当于复制一个相同形状的数组,shape属性在这个方法有点多余import numpy as np
a1 = np.array([[1,3,4],[2,3,5],[23,432,124]])#注意array创建数组要用[]框住多个列表
a2 = np.zeros_like(a1)
print(a2)
#结果:
[[0 0 0]
[0 0 0]
[0 0 0]]
#其他属性不举例子,学过的[[0 0 0]
[0 0 0]
[0 0 0]]4.5 numpy.ones_like
numpy.ones_like 用于创建一个与给定数组具有相同形状的数组,数组元素以 1 来填充。
numpy.ones 和 numpy.ones_like 都是用于创建一个指定形状的数组,其中所有元素都是 1。
它们之间的区别在于:numpy.ones 可以直接指定要创建的数组的形状,而 numpy.ones_like 则是创建一个与给定数组具有相同形状的数组。
numpy.ones_like(a, dtype=None, order='K', subok=True, shape=None)
参数说明:
参数 描述
a 给定要创建相同形状的数组
dtype 创建的数组的数据类型
order 数组在内存中的存储顺序,可选值为 'C'(按行优先)或 'F'(按列优先),默认为 'K'(保留输入数组的存储顺序)
subok 是否允许返回子类,如果为 True,则返回一个子类对象,否则返回一个与 a 数组具有相同数据类型和存储顺序的数组
shape 创建的数组的形状,如果不指定,则默认为 a 数组的形状。
注意:这个和numpy.zeros_like属性一样,不举例子了5. NumPy 从已有的数组创建数组
属性方法有:
numpy.asarray(a, dtype = None, order = None)
numpy.frombuffer(buffer, dtype = float, count = -1, offset = 0)
numpy.fromiter(iterable, dtype, count=-1)
目的:
numpy.array数组对象可以使用很多方法,但是非array对象数组没有对应方法,所以要相互转化5.1 numpy.asarray
numpy.asarray 类似 numpy.array,但 numpy.asarray 参数只有三个,比 numpy.array 少两个。
numpy.asarray(a, dtype = None, order = None)
参数说明:
参数 描述
a 任意形式的输入参数,可以是,列表, 列表的元组, 元组, 元组的元组, 元组的列表,多维数组
dtype 数据类型,可选
order 可选,有"C"和"F"两个选项,分别代表,行优先和列优先,在计算机内存中的存储元素的顺序。import numpy as np
a1 = [1,5,6]#列表
a2 = (1,2,3)#元组
a3 = [(1,23,4),(5,6,3)]#元组列表
a4 = [(1,23,4),(5,6)]#元组列表
b1 = np.asarray(a1)
b2 = np.asarray(a2)
b3 = np.asarray(a3,dtype=float)
#b4 = np.asarray(a4)
print(b1)
print(b2)
print(b3)
print(b4)
'''
结果:
[1 5 6]
[1 2 3]
[[ 1. 23. 4.]
[ 5. 6. 3.]]
[[ 1. 23. 4.]
[ 5. 6. 3.]]
'''
#注意:a4转换成array类型,会报ValueError:用序列设置数组元素。请求的数组在1维之后具有不均匀的形状[1 5 6]
[1 2 3]
[[ 1. 23. 4.]
[ 5. 6. 3.]]
[[ 1. 23. 4.]
[ 5. 6. 3.]]5.2mpy.frombuffer
numpy.frombuffer 用于实现动态数组。
numpy.frombuffer 接受 buffer 输入参数,以流的形式读入转化成 ndarray 对象。
numpy.frombuffer(buffer, dtype = float, count = -1, offset = 0)
注意:buffer 是字符串的时候,Python3 默认 str 是 Unicode 类型,所以要转成 bytestring 在原 str 前加上 b。
参数说明:
参数 描述
buffer 可以是任意对象,会以流的形式读入。
dtype 返回数组的数据类型,可选
这是字符串切片的属性:
count 读取的数据数量,默认为-1,读取所有数据。
offset 读取的起始位置,默认为0。#python3.x的例子
import numpy as np
s = b'Hello World'
a =np.frombuffer(s,dtype='byte')#dtpye中byte用字符串表示就是'S1'
print(a)
#结果:
#[ 72 101 108 108 111 32 87 111 114 108 100][ 72 101 108 108 111 32 87 111 114 108 100]#python2.x的例子
import numpy as np
s = 'Hello World'
a = np.frombuffer(s, dtype = 'S1')
print (a)
#结果:注意:本人现在使用的是python3.x所以不能显示出结果,会报错
#['H' 'e' 'l' 'l' 'o' ' ' 'W' 'o' 'r' 'l' 'd']---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[36], line 4
2 import numpy as np
3 s = 'Hello World'
----> 4 a = np.frombuffer(s, dtype = 'S1')
5 print (a)
TypeError: a bytes-like object is required, not 'str'5.3 numpy.fromiter
numpy.fromiter 方法从可迭代对象中建立 ndarray 对象,返回一维数组。
numpy.fromiter(iterable, dtype, count=-1)
参数 描述
iterable 可迭代对象
dtype 返回数组的数据类型
count 读取的数据数量,默认为-1,读取所有数据
这个属性特别的点在于:要输入可迭代的对象import numpy as np
#创建列表对象,可迭代
list = range(5)
it = iter(list)
#用迭代器创建ndarray
a = np.fromiter(it,dtype=float)
print(a)
#结果:
#[0. 1. 2. 3. 4.][0. 1. 2. 3. 4.]6.NumPy 从数值范围创建数组
下面介绍三个函数,从数字中创建数组
numpy.arange(start, stop, step, dtype)
np.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)
np.logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None)6.1 numpy.arange
numpy 包中的使用 arange 函数创建数值范围并返回 ndarray 对象,函数格式如下:
numpy.arange(start, stop, step, dtype)
根据 start 与 stop 指定的范围以及 step 设定的步长,生成一个 ndarray。
参数说明:
参数 描述
start 起始值,默认为0
stop 终止值(不包含)
step 步长,默认为1
dtype 返回ndarray的数据类型,如果没有提供,则会使用输入数据的类型。
类比:range(start,stop,step),返回一个迭代对象import numpy as np
a1 = np.arange(5)#这个就是省略start,step,dtype都是默认值
a2 = np.arange(10,20,2)#等差数列,从[10,20)等差距离为2
print(a1)
print(a2)
#结果:
'''
[0 1 2 3 4]
[10 12 14 16 18]
'''
[0 1 2 3 4]
[10 12 14 16 18]6.2 numpy.linspace
numpy.linspace 函数用于创建一个一维数组,数组是一个等差数列构成的,格式如下:
np.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)
参数说明:
参数 描述
start 序列的起始值
stop 序列的终止值,如果endpoint为true,该值包含于数列中
num 要生成的等步长的样本数量,默认为50
endpoint 该值为 true 时,数列中包含stop值,反之不包含,默认是True。
retstep 如果为 True 时,生成的数组中会显示间距,反之不显示。默认为False
dtype ndarray 的数据类型,一般默认float
这个和range,arange的区别:
1.返回的类型不同,range返回的是可迭代对象,arange返回的ndarray数组对象,linspace返回的是一维数组
2.等差间距设置不同,range和arange可以设置步数,即等差距离,ellipsislinspace是根据num自己推出等差间距,但是可以显示间距
3.数值范围开闭不同,在rang和arange中只能左闭右开,即[),而linspace中可以设置全闭[]。#参数的调试
import numpy as np
a1 = np.linspace(0,50,25,endpoint=True,retstep=True,dtype='i1')
print(a1)(array([ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 25, 27, 29, 31, 33,
35, 37, 39, 41, 43, 45, 47, 50], dtype=int8), 2.0833333333333335)#和其他函数一起使用
import numpy as np
a1 = np.linspace(0,20,10,retstep = True)
print(a1)
print('---------------------------------------------------------------------------------------------------------------------------')
#b1 = a1.reshape([10,1])#AttributeError:元组类型不能被reshape,因为使用了retstep之后会显示间距,表示方式是用(arrat元组叠加列表,元组)
b2 = np.linspace(0,20,10)#不使用retstep参数
b3 = b2.reshape([10,1])#这样就可以使用
b4 = np.linspace(0,20,10).reshape([10,1])#同b3的方法
print(b2)
print('---------------------------------------------------------------------------------------------------------------------------')
print(b3)
print('---------------------------------------------------------------------------------------------------------------------------')
print(b4)(array([ 0. , 2.22222222, 4.44444444, 6.66666667, 8.88888889,
11.11111111, 13.33333333, 15.55555556, 17.77777778, 20. ]), 2.2222222222222223)
---------------------------------------------------------------------------------------------------------------------------
[ 0. 2.22222222 4.44444444 6.66666667 8.88888889 11.11111111
13.33333333 15.55555556 17.77777778 20. ]
---------------------------------------------------------------------------------------------------------------------------
[[ 0. ]
[ 2.22222222]
[ 4.44444444]
[ 6.66666667]
[ 8.88888889]
[11.11111111]
[13.33333333]
[15.55555556]
[17.77777778]
[20. ]]
---------------------------------------------------------------------------------------------------------------------------
[[ 0. ]
[ 2.22222222]
[ 4.44444444]
[ 6.66666667]
[ 8.88888889]
[11.11111111]
[13.33333333]
[15.55555556]
[17.77777778]
[20. ]]6.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 的底数。默认底数为10
dtype ndarray 的数据类型
和linspace很像,但是这个有个base参数,是设置对数的,即这个等比数列import numpy as np
a1 = np.logspace(0,9,10,base = 2)#在写实参的时候尽量参数名写好,不然编译器无法识别数字的含义
#与a1等价的方法:按序填入实参
a2 = np.logspace(0,9,10,True,2)#其中a1的结果与a2结果一样
print(a1)
print(a2)[ 1. 2. 4. 8. 16. 32. 64. 128. 256. 512.]
[ 1. 2. 4. 8. 16. 32. 64. 128. 256. 512.]7、 NumPy 切片和索引
ndarray对象的内容可以通过索引或切片来访问和修改,与 Python 中 list(列表) 的切片操作一样。
list切片操作:
列表名[start : end : step]
ndarray自带的内置函数slice:(和切片一个效果)
ndarray 数组可以基于 0 - n 的下标进行索引,切片对象可以通过内置的 slice 函数,
并设置 start, stop 及 step 参数进行,从原数组中切割出一个新数组(即复制一个新数组)。7.1、slice函数和切片法
#slice函数的用法
import numpy as np
a = np.arange(10)
s = slice(2,7,2)#[2,7),间隔为2和切片法一样
print(a[s])#相当与a[slice(2,7,2)]
print(a[slice(2,7,2)])[2 4 6]
[2 4 6]#列表list中切片法的应用
import numpy as np
a = np.arange(10)
s = a[2:7:2]
print(s)[2 4 6]'''
冒号 : 的解释:
如果只放置一个参数,如 [2],将返回与该索引相对应的单个元素。
如果为 [2:],表示从该索引开始以后的所有项都将被提取。
如果使用了两个参数,如 [2:7],那么则提取两个索引(不包括停止索引)之间的项。
'''
import numpy as np
a = np.arange(10)
s = a[2]
s1 = a[2:]
s2 = a[2:7]
print(s,s1,s2)2 [2 3 4 5 6 7 8 9] [2 3 4 5 6]7.2 多维数组的切片
1.使用 , 区分维数
2.从某个索引处开始切割,如果为 [2:],表示从该索引开始以后的所有项都将被提取。
3.省略号 …,来使选择元组的长度与数组的维度相同。 如果在行位置使用省略号,它将返回包含行中元素的 ndarray。可以用 : 代替 ...
4.a[0:2,1:3]可以把*冒号左边的数看成是横坐标,右边的数看成是纵坐标*,四个坐标做笛卡尔积,即取数组 a 下标是 (0,1),(0,2),(1,1),(1,2) 四个位置的数。
注意:冒号分隔切片不包含停止索引。#1.用,区分维数+4.a[0:2,1:3]
import numpy as np
a = np.arange(0,12)
a.shape=(3,4)#变成3*4的矩阵
print(a)
print(a[0:2,1:3])#[0:2]写在前面代表第一行的切片,[1:3]代表第二行的切片[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
[[1 2]
[5 6]]#2.只写开头,不写结尾则代表结束
import numpy as np
a = np.arange(0,12)
a.shape = (3,4)
print(a[2:])[[ 8 9 10 11]]#3.使用:或...去返回某行或某列,冒号左边的数看成是横坐标,右边的数看成是纵坐标
import numpy as np
a = np.array([[1,2,3],[3,4,5],[4,5,6]])
print(a[...,1])#冒号左边为...则代表行不要,右边为1,代表第2列(数组从0开始)
print(a[:,1])#冒号(:)和省略号(...)的效果一样
print(a[1,...])#获取第2行
print(a[1,:])#获取第2行
print(a[...,1:])#这是两个都使用,是获取第2列及剩下所有元素(第2列之后所有的列)
print(a[:,1:])#都使用:一样的效果
#print(a[...,1...])都使用...会报错,因为...只能单独存在,所以:的作用很大
[2 4 5]
[2 4 5]
[3 4 5]
[3 4 5]
[[2 3]
[4 5]
[5 6]]
[[2 3]
[4 5]
[5 6]]8.NumPy 高级索引
以前学的索引有:整数(a[数字]),切片([start,stop,step])
高级索引:整数数组索引、布尔索引及花式索引
这些高级索引的好处:可以访问到数组中的任意元素,并且可以用来对数组进行复杂的操作和修改。
1.整数数组索引
2.布尔索引
3.花式索引8.1 整数数组索引
定义:整数数组索引是指使用一个数组来访问另一个数组的元素。这个数组中的每个元素都是目标数组中某个维度上的索引值。
自己的理解:可以理解为数组为行列式,用整数数组索引时,会有一个对应行列式的索引
例如:3*4的数组,对应的整数数组索引为行列式的第0行第0列.....,具体看例子
注意:获取行列式的索引方法有很多,一般用逗号来左边的数看成是横坐标,右边的数看成是纵坐标。*区别多维数组的切边*#例1:获取具体的行列式索引
import numpy as np
a = np.arange(0,12)
a.shape = (3,4)#获取3*4的行列式
b = a[[0,1,2],[0,1,2]]#获取(0,0)(1,1)(2,2)的元素
'''
就是把行号,列号用列表分别框起来,用逗号分隔
'''
print(b)[ 0 5 10]#例2:格式化的获取元素
import numpy as np
a = np.arange(0,12)
a.shape = (4,3)
print(a)
#用rows和cols分别表示行,列
rows = np.array([[0,0],[3,3]])#获取第0行的两个元素,所以用一个列表单独框起来,同理[3,3]。有前后顺序
cols =np.array([[0,2],[0,2]])#获取第0列和第2列的元素,一一对应rows的框
b = a[rows,cols]#把两个列表放进去即可
print(b)[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]]
[[ 0 2]
[ 9 11]]#例3:可以借助切片 : 或 … 与索引数组组合。如下面例子:
import numpy as np
a = np.arange(0,9)
a.shape = (3,3)
print(a)
#正常的切片
b = a[1:3 , 1:3]#[start,end]包含start,不包含end
print(b)
#用高级索引去查
c = a[1:3,[1,2]]#相当于高级索引是切片加切片,这样可以对元素序号进行详细的查询。但是注意高级索引是全包含
print(c)[[0 1 2]
[3 4 5]
[6 7 8]]
[[4 5]
[7 8]]
[[4 5]
[7 8]]8.2 bool索引
当结果对象是布尔运算(例如比较运算符)的结果时,将使用此类型的高级索引。
就是用bool运算来对元素进行详细计算(可以理解为一些判定运算和判定函数来对元素进行计算)#例1:返回大于 5 的元素会作为布尔索引的结果。
import numpy as np
a = np.arange(0,10)
a.shape = (2,5)
print(a[a>5])[6 7 8 9]#例2:使用了~(取补运算符)来过滤NAN。
#注意:python中用numpy.nan来代表NAN。
import numpy as np
a = np.array([np.nan,1,2,np.nan,3,4,5])
print(a)
#清除nan值,用~np.isnan函数
print (a[~np.isnan(a)])[nan 1. 2. nan 3. 4. 5.]
[1. 2. 3. 4. 5.]# 例4:用iscomplx函数来过滤函数
import numpy as np
a = np.array([1, 2+6j, 5, 3.5+5j])
print (a[np.iscomplex(a)])#用iscomplex来去除a数组的非复数,[2. +6.j 3.5+5.j]#关于多条件的布尔索引
'''
使用 & 连接两个条件,输出大于 5 且小于 10 的元素 print(x[x>5 & x<10]):
在 numpy 中会报错:
The truth value of an array with more than one element is ambiguous
三个实用的解决方法:
1、条件加小括号
2、使用 np.logical_and 方法
3、使用 np.all 方法
'''
import numpy as np
x = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]])
print('原数组:\n', x)
print('大于5且小于10的元素:')
print('条件加小括号:')
print(x[(x > 5) & (x < 10)])
print('使用np.logical_and方法:')
print(x[np.logical_and(x > 5, x < 10)])
print('使用np.all方法:')
print(x[np.all([x > 5, x < 10],axis=0)])原数组:
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]]
大于5且小于10的元素:
条件加小括号:
[6 7 8 9]
使用np.logical_and方法:
[6 7 8 9]
使用np.all方法:
[6 7 8 9]8.3花式索引
花式索引指的是利用整数数组进行索引。
#花式索引根据索引数组的值作为目标数组的某个轴的下标来取值。#
对于使用一维整型数组作为索引,如果目标是一维数组,那么索引的结果就是对应位置的元素,如果目标是二维数组,那么就是对应下标的行。
花式索引跟切片不一样,它总是将数据复制到新数组中。#例1:一维数组,只有一个轴,axis = 0
import numpy as np
x = np.arange(9)#创建0~8的数组
x1 =x[[0,6]]#用列表来获取下标对应的元素
x2 =x[0]#获取单个元素
x3 =x[6]#获取单个元素
print(x)
print(x1)
print(x2)
print(x3)[0 1 2 3 4 5 6 7 8]
[0 6]
0
6#例2:二维数组,axis=1。
#用列表的方法来获取行元素
import numpy as np
x = np.arange(24).reshape(8,3)#建立二维数组
print(x)
print(x[[4,2,3,7]])#获取行元素。注意:数组下标从0开始[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]
[12 13 14]
[15 16 17]
[18 19 20]
[21 22 23]]
[[12 13 14]
[ 6 7 8]
[ 9 10 11]
[21 22 23]]#2、传入倒序索引数组,倒序从-1开始
import numpy as np
x = np.arange(24).reshape(8,3)#建立二维数组
print(x)
print(x[[-4,-2,-3,-7]])#获取行元素。注意:倒序数组下标从-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]]
[[12 13 14]
[18 19 20]
[15 16 17]
[ 3 4 5]]#np.ix_函数:np.ix_ 函数就是输入两个数组,产生笛卡尔积的映射关系。
#笛卡尔乘积是指在数学中,两个集合 X 和 Y 的笛卡尔积(Cartesian product),
#又称直积,表示为 X×Y,第一个对象是X的成员而第二个对象是 Y 的所有可能有序对的其中一个成员。
#例如:
x[np.ix_([1,5,7,2],[0,3,1,2])]这句话会输出一个4*4的矩阵,其中的元素分别是:
'''
x[1,0] x[1,3] x[1,1] x[1,2]
x[5,0] x[5,3] x[5,1] x[5,2]
x[7,0] x[7,3] x[7,1] x[7,2]
x[2,0] x[2,3] x[2,1] x[2,2]
就是说,如果 np.xi_ 中输入两个列表,则第一个列表存的是待提取元素的行标,
第二个列表存的是待提取元素的列标,第一个列表中的每个元素都会遍历第二个列表中的每个值,构成新矩阵的一行元素。
'''#所以用np.ix_函数的性质,用来获取下标
import numpy as np
x = np.arange(32).reshape(8,4)
print(x[np.ix_([1,2,3],[1,2,3])])#获取(1,1)(2,2)(3,3)元素,注意正序的下标都从0开始的[[ 5 6 7]
[ 9 10 11]
[13 14 15]]9. NumPy 广播(Broadcast)
广播(Broadcast)是 numpy 对不同形状(shape)的数组进行数值计算的方式, 对数组的算术运算通常在相应的元素上进行
1.两个shape一样就是行列式计算(a*b 为对应位相乘)
2.两个shape不一样,就是利用tile对行列进行计算#1. 如果两个数组 a 和 b 形状相同,即满足 a.shape == b.shape
import numpy as np
a = np.array([1,2,3,4])
b = np.array([10,20,30,40])
c = a*b
print(c)
d = a-b
print(d)[ 10 40 90 160]
[ -9 -18 -27 -36]#2. 当运算中的 2 个数组的形状不同时,numpy 将自动触发广播机制。
numpy.tile(A , reps)函数的运用: 这里的 A 就是数组,reps 可以是一个数,一个列表、元组或者数组等,就是类数组的类型。先要理解准确,先把 A 当作一个块 (看作一个整体,别分开研究每个元素)。 (1)如果 reps 是一个数,就是简单的将 A 向右复制 reps - 1 次形成新的数组,就是 reps 个 A 横向排列:
import numpy as np
a = np.array([[1,2],[3,4]],dtype='i1')
print(a,'\n')
b = np.tile(a,2)#数字2代表为复制2-1=1次,而且是复制数组放到列上
print(b,'\n')[[1 2]
[3 4]]
[[1 2 1 2]
[3 4 3 4]]
(2)如果 reps 是一个 array-like(类数组的,如列表,元组,数组)类型的, 它有两个元素,如 [m , n],实际上就是将 A 这个块变成 m * n 个 A 组成的新数组,有 m 行,n 列 A: 我的理解:如果是数组要进行计算,所以要用(m,n)复制m-1次放到行上,复制n-1次放到列上,如果m,n为1,则复制1-1=0次(不复制)
import numpy as np
a = np.array([[1,2],[3,4]],dtype='i1')
print(a,'\n')
b = np.tile(a,(2,2))
print(b)[[1 2]
[3 4]]
[[1 2 1 2]
[3 4 3 4]
[1 2 1 2]
[3 4 3 4]]10.NumPy 迭代数组
核心函数为:
numpy.nditer(数组名称,order='', op_flags = '',flags ='')
其中:order参数为C或F,默认为C(行)
op_flags(option_flag操作函数)为可选参数:
read-only(只读)
readwrite(读写)
writeonly(只写)
默认为read-only
flags参数:
c_index 可以跟踪 C 顺序的索引
f_index 可以跟踪 Fortran 顺序的索引
multi_index 每次迭代可以跟踪一种索引类型
external_loop 给出的值是具有多个值的一维数组,而不是零维数组
其中external_loop是遍历迭代,值显示为一维数组的形式
注意:order参数是拷贝数组再改变数组顺序,数组原顺序为内存的顺序,即order = ‘K’(这个不写例子)
external_loop参数:当数组的 order 与在循环中指定的 order 顺序不同时,打印为多个一维数组。当相同时,是整个一个一维数组。
#这个例子被误删
import numpy as np
a = np.arange(32).reshape(4,8)#0维数组
print(a)
#遍历修改数组a中的所有元素,其中x[...]代表x[一维起点:终点,二维起点:终点,三维起点:终点]就是切片的格式。
#当步长为1可以省略,冒号也就可以省略。
for x in np.nditer(a,op_flags=['readwrite']):
x[...]=3*x
print(a)<built-in method reshape of numpy.ndarray object at 0x000001CDC77003F0>
[[ 0 3 6 9 12 15 18 21]
[24 27 30 33 36 39 42 45]
[48 51 54 57 60 63 66 69]
[72 75 78 81 84 87 90 93]]#对[...]的本质进行#例1:遍历元素
import numpy as np
a = np.arange(0,60,5)
a = a.reshape(3,4)
print ('原始数组是:')
print (a)
print ('\n')
for x in np.nditer(a,order ='F', 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]]
#例2:用external_loop打印出一维数组。当order与for中的order一样时,打印整个一个数组。不同时,打印多个一维数组
import numpy as np
a = np.arange(0,60,5)
a = a.reshape(3,4)
print ('原始数组是:')
print (a)
print ('\n')
print ('修改并改变排序后的数组是:')
#当order与for中的order不同时,打印多个一维数组
for x in np.nditer(a, flags = ['external_loop'], order = 'F'):
print (x, end=", " )
print ('\n修改不改变排序后的数组是:')
#当order与for中的order一样时,打印整个一个数组
for x1 in np.nditer(a,flags = ['external_loop'],order ='C'):
print(x1)原始数组是:
[[ 0 5 10 15]
[20 25 30 35]
[40 45 50 55]]
修改并改变排序后的数组是:
[ 0 20 40], [ 5 25 45], [10 30 50], [15 35 55],
修改不改变排序后的数组是:
[ 0 5 10 15 20 25 30 35 40 45 50 55]
#例3:广播迭代,广播的意思对不同形状的数组进行计算
import numpy as np
a = np.arange(32).reshape(8,4)
b = np.array([1,2,3,4])
for x,y in np.nditer([a,b]):
print("%d:%d" % (x,y),end = ",")
'''
8行4列对应1行4列,一一匹配
'''0:1,1:2,2:3,3:4,4:1,5:2,6:3,7:4,8:1,9:2,10:3,11:4,12:1,13:2,14:3,15:4,16:1,17:2,18:3,19:4,20:1,21:2,22:3,23:4,24:1,25:2,26:3,27:4,28:1,29:2,30:3,31:4,11.numpy数组操作函数
分6大类
change shape改变数组形状
reverse 翻转数组
alter axis 改数组维度
union 连接数组
Split array 分割数组
add and delete andrray 添加和删除数组11.1 change shape改变数组形状
1. numpy.reshape(arr, newshape, order='C')不改变数据的条件下修改形状
arr:要修改形状的数组
newshape:整数或者整数数组,新的形状应当兼容原有形状
order:'C' -- 按行,'F' -- 按列,'A' -- 原顺序,'k' -- 元素在内存中的出现顺序。
2.numpy.ndarray.flat 是一个数组元素迭代器
3.ndarray.flatten(order='C')返回一份数组拷贝,对拷贝所做的修改不会影响原始数组
order:'C' -- 按行,'F' -- 按列,'A' -- 原顺序,'K' -- 元素在内存中的出现顺序。
4.numpy.ravel(a, order='C')展平的数组元素,顺序通常是"C风格",
返回的是数组视图(view,有点类似 C/C++引用reference的意味),修改会影响原始数组。
order:'C' -- 按行,'F' -- 按列,'A' -- 原顺序,'K' -- 元素在内存中的出现顺序。#例1:reshape的用法,不改变原数组
import numpy as np
a = np.arange(8)#这是创建一维数组函数
b = a.reshape(4,2)
print(a)
print(b)[0 1 2 3 4 5 6 7]
[[0 1]
[2 3]
[4 5]
[6 7]]#例2:flat属性,不会改变原始数组,返回新数组
import numpy as np
a = np.arange(9).reshape(3,3)
for row in a:#python 中的循环就是for 返回的值名称 in 遍历的数组:
print(row)
#而用flat属性可以对遍历中的每个元素进行处理
for b in a.flat:
print(b)#这里是简单的进行打印操作,实际中对这个遍历序列进行各种操作是flat是主要用处,注意flat是属性操作,用ndarray.flat方法使用
print(a)[0 1 2]
[3 4 5]
[6 7 8]
0
1
2
3
4
5
6
7
8
[[0 1 2]
[3 4 5]
[6 7 8]]#例3:flatten(),从英语角度看,是flatten的完成时。效果:返回一份数组拷贝,对拷贝所做的修改不会影响原始数组,
#反过来说这个会改变数组,但是会先copy一份数组,不会改变原始数组的
import numpy as np
a =np.arange(8).reshape(2,4)
print(a)
print('默认flatten展开为C形式')
print(a.flatten())
print('用flatten中展开的F形式')
print(a.flatten('F'))
#省略A(原顺序),K(元素在内存中的出现顺序)的形式[[0 1 2 3]
[4 5 6 7]]
默认flatten展开为C形式
[0 1 2 3 4 5 6 7]
用flatten中展开的F形式
[0 4 1 5 2 6 3 7]#例3:ravel函数
#numpy.ravel(a, order='C') 展平的数组元素,顺序通常是"C风格",
#返回的是数组视图(view,有点类似 C/C++引用reference的意味),修改会影响原始数组。
import numpy as np
a = np.arange(8).reshape(2,4)
print(a.ravel())#默认为C风格
print(a.ravel(order = 'F'))
print(a)[0 1 2 3 4 5 6 7]
[0 4 1 5 2 6 3 7]
[[0 1 2 3]
[4 5 6 7]]11.2翻转数组
1.numpy.transpose(arr, axes)
arr:要操作的数组
axes:整数列表,对应维度,通常所有维度都会对换。'
ndarray.T 和 self.transpose() 相同
2.numpy.rollaxis(arr, axis, start)
arr:数组
axis:要向后滚动的轴,其它轴的相对位置不会改变
start:默认为零,表示完整的滚动。会滚动到特定位置。
3.numpy.swapaxes(arr, axis1, axis2)
arr:输入的数组
axis1:对应第一个轴的整数
axis2:对应第二个轴的整数
【rollaxis和swapaxes的区别就是参数不同,本质方法一样。可以理解为rollaxis是向a后滚,而swapaxes是两个轴的交换】import numpy as np
a = np.arange(12).reshape(3,4)
print(a)#初始矩阵
print(np.transpose(a))#axes参数为列表,即二维矩阵为(0,1)转置为(1,0)
#同理三维数组为(高,行,列)对应可以将这三个下标打乱去转置[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
[[ 0 4 8]
[ 1 5 9]
[ 2 6 10]
[ 3 7 11]]import numpy as np
a = np.arange(12).reshape(3,4)
print(a)
print(a.T)#ndarray.T这个函数是ndarray的内置函数,而transpose是numpy库内置的函数,[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
[[ 0 4 8]
[ 1 5 9]
[ 2 6 10]
[ 3 7 11]]import numpy as np
# 创建了三维的 ndarray
a = np.arange(8).reshape(2,2,2)
#三维数组为(高,行,列)
# 将轴 2 滚动到轴 0(宽度到深度)
b = np.rollaxis(a,2,0)
print (b)
# 查看元素 a[1,1,0],即 6 的坐标,变成 [0, 1, 1]
# 最后一个 0 移动到最前面
print(np.where(b==6))
'''
三维逆转的原理:
1、三维数组axis为三个,对应下标为(0,1,2),所以在使用axis函数时,初始为(0,1,2)变成(0,2,1)就是把轴2滚到轴1,简写就是rollaxis(2,1)
2、滚动的规律(三维滚动很抽象):例如原始shape(7,7,2)可以自己脑子里搭建一个shape=(7,7,2)的全零数组,然后使用rollaxis(1,2,0)
,可以理解,把从下标(0,0,0)-(6,6,1)的元素每个都进行rollaxis(1,2,0)。例如(1,3,4)进行转置(1,2,0)就变成了(3,4,1),
然后对应(1,3,4,)的元素替换对应全0三维数组中下标(3,4,1)的0;【每个元素都这样替换】
'''原数组:
[[[0 1]
[2 3]]
[[4 5]
[6 7]]]
获取数组中一个值:
(array([0], dtype=int64), array([1], dtype=int64), array([0], dtype=int64))
6
调用 rollaxis 函数:
[[[0 2]
[4 6]]
[[1 3]
[5 7]]]
(array([0], dtype=int64), array([1], dtype=int64), array([1], dtype=int64))
import numpy as np
# 创建了三维的 ndarray
a = np.arange(8).reshape(2,2,2)
# 现在交换轴 0(深度方向)到轴 2(宽度方向)
print(a)
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]]]11.3修改数组维度
11.3.1 broadcast(产生模仿广播的对象)
手动模仿广播的机制a+b
numpy.broadcast(x,y)#例子:
import numpy as np
x = np.array([[1], [2], [3]])#3*1的矩阵
y = np.array([4, 5, 6]) #1*3的矩阵
# 手动使用 broadcast 将 x 与 y 相加为3*3的矩阵
b = np.broadcast(x,y)
print(b)#发现直接打印无法打出3*3矩阵,想用flat属性可以打印不行,因为flat为ndarray的属性,而broadcast为numpy的属性
print (b.shape)
#for b in b.flat:
# print(b)
c = np.empty(b.shape)
c.flat = [u + v for (u,v) in b]#这个是比较高级的迭代
print(c)<numpy.broadcast object at 0x000001F31722D600>
(3, 3)
[[5. 6. 7.]
[6. 7. 8.]
[7. 8. 9.]]11.3.2 numpy.broadcast_to
在NumPy这个强大的Python数值计算库中,broadcast_to方法是一个非常实用的工具,它允许我们将一个数组“广播”到指定的形状,而无需显式地复制数据。理解并掌握这一方法对于高效利用NumPy进行数组操作至关重要。本文将深入解析broadcast_to方法的原理、用法以及在实际应用中的案例。一、什么是广播(Broadcasting)?
在NumPy中,广播是一种强大的机制,它允许NumPy在算术运算中处理不同形状的数组。当对两个或多个数组进行算术运算时,NumPy会尝试使这些数组具有兼容的形状,以便进行元素级的运算。如果形状不兼容,NumPy会尝试通过扩展数组的维度来使它们兼容,这就是广播的过程。
广播的基本规则包括:
如果两个数组的维度数不同,那么在维度较小的数组前面填充1,直到两个数组的维度数相同。 对于每一维,如果两个数组的大小相同或者其中一个数组的大小为1,那么这两个数组在这一维上是兼容的。 如果两个数组在所有维度上都是兼容的,那么它们就可以进行广播。 二、broadcast_to方法的原理与用法
broadcast_to方法是NumPy中用于实现广播的一个函数。它接受两个参数:一个输入数组和一个目标形状。函数会返回一个新的数组,其形状与目标形状相同,但数据是原数组的广播版本。需要注意的是,broadcast_to并不会实际复制数据,而是返回一个新的数组对象,该对象在访问元素时会根据需要进行广播。
用法示例:
import numpy as np
# 创建一个形状为(3,)的数组
a = np.array([1, 2, 3])
# 使用broadcast_to将其广播到形状(3, 2)
b = np.broadcast_to(a, (3, 3))
print(b)[[1 2 3]
[1 2 3]
[1 2 3]]在这个例子中,我们创建了一个形状为(3,)的一维数组a,然后使用broadcast_to方法将其广播到形状(3, 2)的二维数组b。注意,在广播后的数组中,最后一行的最后一个元素是1,这是因为在原始数组a中只有一个元素3,而在广播后的数组中需要两个元素,所以NumPy将3复制到了第二列。
三、broadcast_to方法的应用场景
broadcast_to方法在很多场景下都非常有用,特别是在需要改变数组形状但又不希望实际复制数据时。以下是一些具体的应用场景:
1.扩展数组维度:当需要将一个一维数组扩展为多维数组时,可以使用broadcast_to方法。这在处理图像、矩阵运算等任务时非常有用。
2.与固定形状数组进行运算:当需要与具有固定形状的数组进行运算时,可以使用broadcast_to将输入数组广播到相应的形状。这样可以避免显式地调整数组形状,使代码更加简洁。
3.节省内存和计算资源:由于broadcast_to并不实际复制数据,因此它可以在不增加内存消耗的情况下扩展数组的形状。这在处理大规模数据集时尤为重要,可以显著提高计算效率。四、注意事项与最佳实践
在使用broadcast_to方法时,需要注意以下几点:
1.理解广播规则:在使用broadcast_to之前,确保理解NumPy的广播规则。这有助于避免由于形状不兼容而导致的错误。
2.检查目标形状:在调用broadcast_to时,确保目标形状与原始数组在广播规则下是兼容的。否则,NumPy将无法正确执行广播操作。
3.避免不必要的广播:虽然broadcast_to不会增加内存消耗,但过度使用广播可能会使代码难以理解和维护。因此,在可能的情况下,尽量使用具有明确形状的数组进行操作。
4.与其他NumPy函数结合使用:broadcast_to可以与其他NumPy函数(如算术运算、函数应用等)结合使用,以实现更复杂的操作。通过灵活运用这些函数,可以大大提高代码的效率和可读性。五、总结
broadcast_to方法是NumPy中一个非常实用的工具,它允许我们将一个数组广播到指定的形状,而无需显式地复制数据。通过理解广播规则和掌握broadcast_to的用法,我们可以更加高效地利用NumPy进行数组操作。在实际应用中,我们可以根据具体需求灵活运用这一方法,以实现更简洁、高效的代码。同时,我们也要注意避免不必要的广播操作,以保持代码的清晰和可维护性。11.3.3 expand_dims
expand_dims方法的主要作用是在数组的指定轴上增加一个维度,其大小为1。这在需要调整数组形状以适应特定运算或函数要求时非常有用。通过增加维度,我们可以更灵活地操作数组,比如进行广播运算或与其他形状的数组进行合并。
expand_dims方法接受两个参数:要增加维度的数组和指定轴的索引。轴索引可以是正数、负数或者一个包含多个轴索引的元组。正数索引从0开始,表示从左到右的轴;负数索引从-1开始,表示从右到左的轴。当指定一个轴索引时,expand_dims会在该轴之前插入一个新的维度。
numpy.expand_dims(arr, axis)注意axis相当于在指定轴插入import numpy as np
a = np.array([1,2,3])
a_expanded = np.expand_dims(a,axis=1)#a为(3,)
print(a.shape)
print(a_expanded)
print(a_expanded.shape)
#三维
x = np.array(([1,2],[3,4]))
print(x.shape)
y = np.expand_dims(x,axis=2)
print(y)
print(y.shape)(3,)
[[1]
[2]
[3]]
(3, 1)
(2, 2)
[[[1]
[2]]
[[3]
[4]]]
(2, 2, 1)11.3.4squeeze
squeeze方法的主要作用是移除数组中所有长度为1的维度。在NumPy中,维度长度为1的轴通常被视为冗余的,因为它们不增加数组的实际数据容量。
通过移除这些冗余维度,我们可以简化数组的形状,使其更易于进行后续操作。
squeeze方法接受一个数组作为输入,并返回一个新的数组,其中所有长度为1的维度都被移除。需要注意的是,squeeze方法不会改变数组中的数据,只是改变了数组的形状。
numpy.squeeze(arr, axis)axis为删除指定的一维数组,注意维度的下标是从0,1,2开始的,和n维数组一样#示例1:移除单个长度为1的维度
import numpy as np
# 创建一个形状为(1, 3, 1)的三维数组
a = np.array([[[1, 2, 3]]).reshape((1, 3, 1))
# 使用squeeze移除长度为1的维度
a_squeezed = np.squeeze(a)
print("原始数组形状:", a.shape)
print("移除维度后的数组形状:", a_squeezed.shape)
#示例2:选择性地移除特定轴上的长度为1的维度
# 创建一个形状为(1, 3, 1)的三维数组
b = np.array([[[1, 2, 3]]).reshape((1, 3, 1))
# 使用squeeze移除第一个和最后一个轴上的长度为1的维度
b_squeezed = np.squeeze(b, axis=(0, 2))
print("原始数组形状:", b.shape)
print("选择移除维度后的数组形状:", b_squeezed.shape)
squeeze方法的应用场景 squeeze方法在实际应用中有着广泛的用途,以下是一些常见的应用场景:
1.数据预处理:在机器学习和数据分析中,经常需要对数据进行预处理以满足模型的输入要求。通过squeeze方法移除数据中的冗余维度,可以使数据更加紧凑,并减少计算资源的浪费。
2.数组形状转换:有时我们需要将数组从一种形状转换为另一种形状,以适应特定的算法或函数要求。squeeze方法可以帮助我们快速实现这种形状转换,而无需手动进行复杂的切片和重塑操作。
3.简化数组操作:在某些情况下,数组中存在多个长度为1的维度可能会使操作变得复杂。通过使用squeeze方法移除这些维度,我们可以简化数组操作,提高代码的可读性和可维护性。在使用squeeze方法时,需要注意以下几点:
1.明确移除维度的目的:在调用squeeze方法之前,需要明确移除维度的目的和预期效果。避免无意义地移除维度导致数据结构的混乱或信息的丢失。
2.选择性移除维度:通过指定axis参数,我们可以选择性地移除特定轴上的长度为1的维度。这可以帮助我们更加精确地控制数组的形状变化。
3.与其他维度调整方法的比较:除了squeeze方法外,NumPy还提供了其他用于调整数组维度的方法(如reshape、expand_dims等)。在使用时,需要根据具体需求选择合适的方法。11.4 连接数组函数
concatenate 连接沿现有轴的数组序列
stack 沿着新的轴加入一系列数组。
hstack 水平堆叠序列中的数组(列方向)
vstack 竖直堆叠序列中的数组(行方向)11.4.1 numpy.concatenate
该函数用于沿指定轴连接相同形状的两个或多个数组,格式如下:
numpy.concatenate((a1, a2, ...), axis)
a1, a2, ...:相同类型的数组(这里不要求同行列,)
axis:沿着它连接数组的轴,默认为 0(在使用axis时要求对应行列等是同大小行列的)
out:一个可选参数,用于指定输出数组。如果提供了这个参数,那么连接后的结果将直接存放到这个数组中,而不是创建一个新的数组。这可以用于节省内存空间和提高性能。import numpy as np
#例1:默认axis=0下的情况
a = np.array([1,2,3])#1*3,在表示上为(3,),
b = np.array([4,5,6])
print(a.shape)
print(np.concatenate((a,b),axis=0))#默认axis=0
#用默认的方法会在原矩阵的基础上连接,如上(3,),会连接axis=0对应的3。
#这里的3为列,所以会按照列连接-》一定要连接行呢?-》修改矩阵的形状?
a_1 = np.array([[1,2,3]])
b_1 = np.array([[4,5,6]])
print(a_1.shape)
print(np.concatenate((a_1,b_1),axis=1))
#例2:指定axis参数
x = np.array([[1,2],[3,4]])#2*2
y = np.array([[5,6],[7,8]])#2*2
print(np.concatenate((x,y),axis=0))#这个是对应(3,)这个形状的
print(np.concatenate((x,y),axis=1))#指定按列连接(3,)
[1 2 3 4 5 6]
(1, 3)
[[1 2 3 4 5 6]]
[[1 2]
[3 4]
[5 6]
[7 8]]
[[1 2 5 6]
[3 4 7 8]]concatenate方法的应用场景
1.数据合并:当我们需要将多个数据集合并成一个完整的数据集时,可以使用concatenate方法。例如,在机器学习中,我们可能需要将多个训练集合并成一个大的训练集来进行模型训练。
2.图像拼接:在处理图像数据时,我们可以使用concatenate方法将多张图像拼接成一张更大的图像。这在图像处理、计算机视觉等领域中非常常见。
3.时间序列分析:在处理时间序列数据时,我们可能需要将多个时间段的数据连接起来形成一个完整的时间序列。这时,concatenate方法可以帮助我们轻松实现这一目标。在使用concatenate方法时,需要注意以下几点:
确保输入数组形状一致:除了指定轴以外的维度上,输入的数组必须具有相同的形状。否则,将会引发错误。
内存使用:当连接大型数组时,concatenate方法可能会消耗大量内存。因此,在处理大型数据集时,需要特别注意内存使用情况,并考虑使用其他内存优化策略。
替代方案:除了concatenate方法外,NumPy还提供了其他一些函数和方法用于数组的连接和组合,如stack、hstack、vstack等。在某些情况下,使用这些替代方案可能更加灵活和高效。
性能优化:在处理大型数据集时,连接操作可能会成为性能瓶颈。为了提高性能,可以考虑使用更高效的数据结构、算法或并行计算技术。除了基本的用法外,concatenate方法还有一些高级用法和技巧可以帮助我们更加灵活地处理数组连接问题。
连接多个数组:concatenate方法可以接受一个包含多个数组的元组作为输入,因此我们可以一次性连接多个数组。这在处理具有多个输入的数据集时非常有用。
自定义轴连接:通过指定不同的axis参数值,我们可以实现沿着不同轴的连接。这为我们提供了更大的灵活性,可以根据具体需求选择最合适的连接方式。
与广播机制结合使用:NumPy的广播机制允许我们在不同形状的数组之间进行数学运算。结合使用concatenate方法和广播机制,我们可以实现更复杂的数组操作和变换11.4.2 stack 沿着新的轴加入一系列数组。
stack方法的基本原理是将多个数组沿着一个新的轴进行堆叠。这个新的轴是在原始数组的维度之上添加的,因此堆叠后的数组将具有更高的维度。例如,如果我们有两个形状为(3,)的一维数组,使用stack方法将它们堆叠起来,将得到一个形状为(2, 3)的二维数组。
与concatenate方法不同的是,stack方法不会改变原始数组的形状,而是通过在它们之间插入一个新的轴来实现堆叠。这使得stack方法在处理具有不同形状的数组时更加灵活,只要它们在某些维度上具有相同的形状即可。
numpy.stack(arrays, axis,out)
arrays:一个序列,包含要堆叠的数组。这些数组应具有兼容的形状,以便能够沿着新的轴进行堆叠。
axis:一个整数,指定新轴的位置。默认为0,表示新轴将插入到最前面。如果设置为其他值,例如1,则表示新轴将插入到指定位置。
out:一个可选参数,用于指定输出数组。如果提供了这个参数,那么堆叠后的结果将直接存放到这个数组中,而不是创建一个新的数组。这可以用于节省内存空间和提高性能。import numpy as np
# 创建两个一维数组
array1 = np.array([1, 2, 3])
array2 = np.array([4, 5, 6])
# 使用stack方法将两个数组沿着第一个新轴堆叠起来
result = np.stack((array1, array2), axis=0)#沿着axis=0,即行轴,由两个一维变成一个二维的2*3
print(result)
result1 = np.stack((array1, array2), axis=1)#沿着axis=1,即列轴,由两个一维变成一个二维的3*2
print(result1)
# 输出:
# [[1 2 3]
# [4 5 6]]
[[1 2 3]
[4 5 6]]
[[1 4]
[2 5]
[3 6]]stack方法在数据处理和分析中有着广泛的应用。以下是一些可能的应用场景:
多通道图像处理:在图像处理中,我们经常需要处理具有多个通道的图像(如RGB图像)。每个通道可以表示为一个二维数组,而整个图像则可以通过将这些通道数组堆叠成一个三维数组来表示。使用stack方法可以方便地实现这一过程。
时间序列数据的处理:在处理时间序列数据时,我们可能需要将多个时间序列数据堆叠在一起,以便进行批量处理或比较。通过指定不同的堆叠轴,我们可以将时间序列数据组织成适合特定任务的形式。
多源数据的整合:当从多个来源获取数据时,这些数据可能具有不同的形状或结构。使用stack方法,我们可以根据需要在特定维度上将这些数据堆叠起来,形成一个统一的数据结构,方便后续的分析和处理。在使用stack方法时,需要注意以下几点:
数组形状兼容性:要确保要堆叠的数组在某些维度上具有相同的形状。如果数组的形状不兼容,将会引发错误。
内存使用:堆叠多个大型数组可能会消耗大量内存。因此,在处理大型数据集时,需要特别注意内存使用情况,并考虑使用其他内存优化策略。
选择适当的堆叠轴:根据具体需求和任务,选择适当的堆叠轴是非常重要的。不同的堆叠轴将导致不同的数据结构,并可能影响后续的数据处理和分析过程。除了基本的用法外,stack方法还有一些高级用法和技巧可以帮助我们更加灵活地处理数组堆叠问题。
与广播机制结合使用:类似于concatenate方法,stack方法也可以与NumPy的广播机制结合使用。广播机制允许我们在不同形状的数组之间进行数学运算,而stack方法则提供了在更高维度上组合这些数组的能力。通过将两者结合,我们可以创建更复杂的数据结构,并在其上执行各种操作。
嵌套堆叠:我们可以多次使用stack方法,将多个堆叠操作嵌套在一起。这允许我们构建具有任意维度和复杂结构的数据集。例如,我们可以首先将两个二维数组沿着新轴堆叠成一个三维数组,然后再将这个三维数组与其他三维数组进行堆叠,形成一个更高维度的数组。
与split方法配合使用:stack方法的逆操作是split方法,它可以将一个数组沿着指定的轴分割成多个子数组。通过先使用split方法将数组分割成多个部分,然后再使用stack方法将它们重新组合起来,我们可以实现数据的重新排列和组织。11.4.3 hstack和vstack 沿着水平/垂直的轴加入一系列数组。
这两个函数都是numpy.stack 函数的变体,这里的水平相当于按列排序,垂直相当于按行排序
numpy.hstack(arrays)
numpy.vstack(arrays)#例:hstack/vstack
import numpy as np
# 创建两个一维数组
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
# 使用hstack方法堆叠数组
c = np.hstack((a, b))
# 使用vstack方法堆叠数组
d = np.vstack((a, b))
# 输出结果
print(c) # 输出:[1 2 3 4 5 6]
print(d) #[[1 2 3]
#[4 5 6]]
[1 2 3 4 5 6]
[[1 2 3]
[4 5 6]]#例:结合条件语句进行选择性堆叠
#有时候,我们可能需要根据某些条件选择性地堆叠数组。这时,可以结合Python的条件语句来实现。例如:
import numpy as np
# 创建两个二维数组
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])
# 根据条件选择堆叠的数组
condition = True#填0或其他跳转到else
if condition:
result = np.hstack((a, b))
else:
result = np.vstack((a, b))
# 输出结果
print(result)
[[1 2 5 6]
[3 4 7 8]]#与reshape方法结合使用改变数组形状
#在堆叠数组之前,有时我们需要先改变数组的形状以满足堆叠条件。这时,可以使用NumPy的reshape方法。例如:
import numpy as np
# 创建一个一维数组
a = np.array([1, 2, 3, 4, 5, 6])
# 使用reshape方法改变数组形状
a_reshaped = a.reshape((2, 3))
# 创建另一个二维数组
b = np.array([[7, 8], [9, 10]])
# 使用hstack方法堆叠数组
c = np.hstack((a_reshaped, b))
# 输出结果
print(c)
# 使用vstack方法堆叠数组
d = np.hstack((a_reshaped, b))
# 输出结果
print(d)[[ 1 2 3 7 8]
[ 4 5 6 9 10]]
[[ 1 2 3 7 8]
[ 4 5 6 9 10]]在使用hstack/vsatck方法时,需要注意以下几点:
确保被堆叠的数组在对应维度上尺寸一致。如果尺寸不一致,将会引发错误。
hstack方法返回的是一个新的数组,原数组不会被修改。如果需要修改原数组,请确保将其赋值给一个新的变量。
对于大型数组,使用hstack方法进行堆叠可能会消耗较多的内存和计算资源。在实际应用中,需要根据具体情况权衡利弊常见问题及解决方案:
问题:尝试堆叠尺寸不一致的数组时,会抛出异常。
解决方案:在堆叠之前,确保所有数组的对应维度尺寸相同。如果需要,可以使用NumPy的reshape或resize方法来调整数组的形状。
问题:hstack/vstack方法返回的新数组占用过多内存。
解决方案:在处理大型数据集时,可以考虑使用NumPy的memmap功能或Dask等并行计算库来处理数据,以减少内存占用。此外,也可以尝试优化算法,减少不必要的数组操作。11.5 分割数组
split 将一个数组分割为多个子数组
hsplit 将一个数组水平分割为多个子数组(按列)
vsplit 将一个数组垂直分割为多个子数组(按行)11.5.1 split
split方法是NumPy中用于将数组拆分为多个子数组的函数。它基于指定的轴和索引或大小来拆分数组。基本用法如下:
numpy.split(ary, indices_or_sections, axis=0)
ary:需要拆分的数组。
indices_or_sections:可以是一个整数,表示将数组均匀拆分为多少份;也可以是一个整数序列,表示拆分后每个子数组的结束位置。(使用整数序列时,分割的分数=结束位置数+1;使用整数时,注意)
axis:沿哪个轴进行拆分,默认为0,即第一个轴。
疑问:split在分割时,如果不等分拆分会出现error: array split does not result in an equal division(即必须等分拆分)#例:
import numpy as np
# 创建一个一维数组
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
# 将数组拆分为3个子数组
split_arr = np.split(arr, 3)
# 打印拆分后的子数组
for sub_arr in split_arr:
print(sub_arr)
print('分割符')
#例:不均匀拆分
#通过指定一个整数序列作为indices_or_sections参数,我们可以实现不均匀拆分。例如:
split_arr = np.split(arr, [3, 5, 9])#指定3个结束位置树,则分成3+1份数组,
#数组下标默认为0开始,所以[3, 5, 9]等价于[0,3),[3,5),[5,9),[9,9)
#想到了“区间划分”这个方法
for sub_arr in split_arr:
print(sub_arr)
print('分割符')
#例:沿不同轴拆分
#通过指定axis参数,我们可以沿不同的轴进行拆分。这对于处理多维数组非常有用。例如:
arr_2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
split_arr_2d = np.split(arr_2d,3, axis=1)
print(arr_2d.shape)
for sub_arr in split_arr_2d:
print(sub_arr)
[1 2 3]
[4 5 6]
[7 8 9]
分割符
[1 2 3]
[4 5]
[6 7 8 9]
[]
分割符
(3, 3)
[[1]
[4]
[7]]
[[2]
[5]
[8]]
[[3]
[6]
[9]]在使用split方法时,需要注意以下几点:
确保指定的拆分方式(整数或整数序列)与数组的形状相匹配,否则可能会引发错误。
在处理多维数组时,要注意指定正确的轴进行拆分。
如果数组不能被均匀拆分,split方法会按照指定的拆分方式尽量平均分配元素,但最后一个子数组可能会包含较少的元素。11.5.2 hsplit/vsplit
hsplit 将一个数组水平分割为多个子数组(按列)
vsplit 将一个数组垂直分割为多个子数组(按行)
本质是在split(array,indices_or_sections,axis)其中axis这个参数上固定0(对应vsplit),固定1(对应hsplit),其他参数不变import numpy as np
#例:hsplit
arr_2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
split_arr_2d = np.hsplit(arr_2d,3)
print(arr_2d.shape)
for sub_arr in split_arr_2d:
print(sub_arr)
print('代码内分割符')
print('分割符')
#例:vsplit
arr_2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
split_arr_2d = np.vsplit(arr_2d,3)
print(arr_2d.shape)
for sub_arr in split_arr_2d:
print(sub_arr)
print('代码被内分割符')(3, 3)
[[1]
[4]
[7]]
代码内分割符
[[2]
[5]
[8]]
代码内分割符
[[3]
[6]
[9]]
代码内分割符
分割符
(3, 3)
[[1 2 3]]
代码被内分割符
[[4 5 6]]
代码被内分割符
[[7 8 9]]
代码被内分割符虽然vsplit方法在处理多维数组拆分时非常方便,但在实际应用中还需要注意一些性能优化和注意事项。
内存占用:拆分大型多维数组时,每个子数组都会占用独立的内存空间。因此,在拆分前需要评估内存使用情况,避免内存不足的问题。
避免不必要的拆分:尽量减少不必要的拆分操作,特别是在处理大型数据集时。如果可能的话,尝试通过其他方式组织或处理数据,以减少拆分的次数。
数据类型选择:选择适当的数据类型可以显著提高性能。例如,对于整数数据,使用整数类型而不是浮点类型可以节省内存并提高计算速度。
并行处理:对于非常大的数组,如果计算资源允许,可以考虑使用并行计算来加速拆分过程。这可以通过结合其他库(如Dask、Joblib等)来实现。11.6 数组元素的添加与删除
resize 返回指定形状的新数组
append 将值添加到数组末尾
insert 沿指定轴将值插入到指定下标之前
delete 删掉某个轴的子数组,并返回删除后的新数组
unique 查找数组内的唯一元素11.6.1 numpy.resize
数返回指定大小的新数组。
如果新数组大小大于原始大小,则使用原数组数据补齐。
numpy.resize(arr,shape)和ndarray.resize(shape, refcheck=False)区别:
numpy.resize(arr,shape),有返回值,返回复制内容.如果维度不够,会使用原数组数据补齐
ndarray.resize(shape, refcheck=False),修改原数组,不会返回数据,如果维度不够,会使用0补齐
注: reshape只能设置规定内的元素,假如超出或者减少会报错而 resize不会报错支持超出或者减少元素的操作import numpy as np
a=np.array([[1,2,3],[4,5,6]])
print(a)
print('------------')
#数组的形状
print(a.shape)
b=np.resize(a,(3,2))
c=np.resize(a,(3,3))
d=np.resize(a,(2,2))
print(b)
print('------------')
print(c)
print('------------')
print(d)
print('------------')
# 设置refcheck=False 后,不足的数值由0补上
e = a.resize((3,3),refcheck=True)
print(e)[[1 2 3]
[4 5 6]]
------------
(2, 3)
[[1 2]
[3 4]
[5 6]]
------------
[[1 2 3]
[4 5 6]
[1 2 3]]
------------
[[1 2]
[3 4]]
------------
None11.6.2 numpy.append()
在数组的末尾添加值,默认返回一个一维数组。
numpy. append (arr, values,axis=None)
参数说明:
. arr:输入的数组;
. values:向arr 数组中添加的值,需要和arr 数组的形状保持一致;
· axis:默认为None,返回的是一维数组;
当axis =0时,追加的值会被添加到行,而列数保持不变,若axis=1则与其恰好相反。import numpy as np
a=np.array([[1,2,3],[4,5,6]])
#向数组a添加元素
b=np.append(a,[[7,8,9]])#默认axis=None,返回一维数组
print(b)
print('------------')
#沿0轴添加元素
c=np.append(a,[[7,8,9]],axis=0)
print(c)
print('------------')
#沿1轴添加元素
print(np.append(a,[[7,8,9],[10,11,12]],axis=1))[1 2 3 4 5 6 7 8 9]
------------
[[1 2 3]
[4 5 6]
[7 8 9]]
------------
[[ 1 2 3 7 8 9]
[ 4 5 6 10 11 12]]11.6.3 numpy.insert()
表示沿指定的轴,在给定索引值的前一个位置插入相应的值,如果没有提供轴,则输入数组被展开为一维数组。
numpy.insert(arr,obj,values,axis)
参数说明:
· arr:要输入的数组
. obj:表示索引值,在该索引值之前插入values值;
. values:要插入的值或列表
. axis:指定的轴,如果未提供,则输入数组会被展开为一维数组import numpy as n
a=np.array([[1,2],[3,4],[5,6]])
print(a,a.shape)
print('------------')
#不提供axis的情况下,会将数组展开
print(np.insert(a,3,[11,12]))
print('------------')
#沿0轴垂直方向(行方向)插入元素
print(np.insert(a,1,[11,2],axis=0))
print('------------')
#沿1轴水平方向(列方向)插入元素
print(np.insert(a,1,1,axis=1)) [[1 2]
[3 4]
[5 6]] (3, 2)
------------
[ 1 2 3 11 12 4 5 6]
------------
[[ 1 2]
[11 2]
[ 3 4]
[ 5 6]]
------------
[[1 1 2]
[3 1 4]
[5 1 6]]11.6.3 numpy.delete()
该方法表示从输入数组中删除指定的子数组,并返回一个新数组。它与insert()函数相似,若不提供 axis参数,则输入数组被展开为一维数组。numpy.delete(arr,obj,axis)参数说明:
. arr:要输入的数组;
. obj:整数或者整数数组,表示要被删除数组元素或者子数组;.
. axis:沿着哪条轴删除子数组。import numpy as np
a=np.arange(12).reshape(3,4)
#不提供axis的情况,默认返回一维数组
print(np.delete(a,5))
print('--------------------------------')
#删除第二列
b=np.delete(a,1,axis=1)
print(b)
print('---------------------------------')
#删除多行,用列表的形式代表删除多个
print(np.delete(a,[1,2,],axis=0))--------------------------------
[ 0 1 2 3 4 6 7 8 9 10 11]
--------------------------------
[[ 0 2 3]
[ 4 6 7]
[ 8 10 11]]
---------------------------------
[[0 1 2 3]]### 11.6.4 numpy.unique
numpy.unique(ar, return_index=False, return_inverse=False, return_counts=False, axis=None)
该函数作用:找出数组中独一无二的元素值。
各个参数意义:
ar:输入数组,除非设定了下面介绍的axis参数,否则输入数组均会被自动扁平化成一个一维数组。
return_index:(可选参数,布尔类型),如果为True则结果会同时返回元素在未去重数组中的索引(index)。
return_inverse:(可选参数,布尔类型),如果为True则结果会同时返回元素在去重后的数组中的索引(index)。
return_counts:(可选参数,布尔类型),如果为True则结果会返回去重后的元素在原始数组中出现的次数。
axis:(可选参数),默认返回一维数组
有返回值,返回一个排好序列的独一无二的数组。import numpy as np
a = np.array([5,2,6,2,7,5,6,8,2,9])
print ('第一个数组的去重值:')
u = np.unique(a)
print (u)
print ('\n')
print('--------------------------------')
print ('去重数组的索引数组:')
u,indices = np.unique(a, return_index = True)
print (indices)
print ('\n')
print('--------------------------------')
print ('我们可以看到每个和原数组下标对应的数值:')
print (a)
print ('\n')
print('--------------------------------')
print ('去重数组的下标:')
u,indices = np.unique(a,return_inverse = True)
print (u)
print ('\n')
print('--------------------------------')
print ('下标为:')
print (indices)
print ('\n')
print('--------------------------------')
print ('使用下标重构原数组:')
print (u[indices])
print ('\n')
print('--------------------------------')
print ('返回去重元素的重复数量:')
u,indices = np.unique(a,return_counts = True)
print (u)
print (indices)第一个数组的去重值:
[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]
11.7 numpy.newaxis
np.newaxis 的功能是:增加新的维度。注意 np.newaxis 放的位置不同,产生的矩阵形状也不同。
x[:, np.newaxis] :放在后面,会给列上增加维度;
x[np.newaxis, :] :放在前面,会给行上增加维度;
用途: 通常用它将一维的数据转换成一个矩阵,这样就可以与其他矩阵进行相乘。import numpy as np
#列方向增加维度
x = np.array([5, 6, 7, 8])
print(x.shape)
x_add = x[:, np.newaxis]#在列上加一个维度
print(x_add.shape)
print(x_add)
print('------------')
#行方向增加维度
x_add = x[np.newaxis, :]
print(x_add.shape)
print(x_add)
print('------------')
#对矩阵增加维度
x = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
print(x.shape)
x_add = x[:, np.newaxis]
print(x_add)
print(x_add.shape)(4,)
(4, 1)
[[5]
[6]
[7]
[8]]
------------
(1, 4)
[[5 6 7 8]]
------------
(2, 4)
[[[1 2 3 4]]
[[5 6 7 8]]]
(2, 1, 4)12.NumPy 位运算
NumPy "bitwise_" 开头的函数是位运算函数。
NumPy 位运算包括以下几个函数:
| 函数 | 描述 |
|---|---|
bitwise_and |
按位与,对数组元素执行位与操作 |
bitwise_or |
按位或,对数组元素执行位或操作 |
bitwise_xor |
按位异或 |
bitwise_not |
按位取反 |
invert |
按位取反 |
left_shift |
左移位运算,向左移动二进制表示的位 |
right_shift |
右移位运算,向右移动二进制表示的位 |
也可以使用 "&"、 "~"、 "|" 和 "^" 等操作符进行计算:
13.NumPy 字符串函数
这些函数在字符数组类(numpy.char)中定义。所以在使用的时候都是numpy.char.xxx
| 函数 | 描述 |
|---|---|
add() |
对两个数组的逐个字符串元素进行连接 |
| multiply() | 返回按元素多重连接后的字符串 |
center() |
居中字符串 |
capitalize() |
将字符串第一个字母转换为大写 |
title() |
将字符串的每个单词的第一个字母转换为大写 |
lower() |
数组元素转换为小写 |
upper() |
数组元素转换为大写 |
split() |
指定分隔符对字符串进行分割,并返回数组列表 |
splitlines() |
返回元素中的行列表,以换行符分割 |
strip() |
移除元素开头或者结尾处的特定字符 |
join() |
通过指定分隔符来连接数组中的元素 |
replace() |
使用新字符串替换字符串中的所有子字符串 |
decode() |
数组元素依次调用str.decode |
encode() |
数组元素依次调用str.encode |
14.NumPy 数学函数
三角函数
NumPy 提供了标准的三角函数:sin()、cos()、tan()。
舍入函数
numpy.around() 函数返回指定数字的四舍五入值。
numpy.around(a,decimals)参数说明:
- a: 数组
- decimals: 舍入的小数位数。 默认值为0。 如果为负,整数将四舍五入到小数点左侧的位置
numpy.floor()
numpy.floor() 返回小于或者等于指定表达式的最大整数,即向下取整。
numpy.ceil()
numpy.ceil() 返回大于或者等于指定表达式的最小整数,即向上取整。
15.NumPy 算术函数
NumPy 算术函数包含简单的加减乘除: add(),subtract(),multiply() 和 divide()。
需要注意的是数组必须具有相同的形状或符合数组广播规则。
numpy.reciprocal()
numpy.reciprocal() 函数返回参数逐元素的倒数。如 1/4 倒数为 4/1。
numpy.power()
numpy.power() 函数将第一个输入数组中的元素作为底数,计算它与第二个输入数组中相应元素的幂。
numpy.mod()
numpy.mod() 计算输入数组中相应元素的相除后的余数。 函数 numpy.remainder() 也产生相同的结果。
16.NumPy 统计函数
NumPy 提供了很多统计函数,用于从数组中查找最小元素,最大元素,百分位标准差和方差等。
numpy.amin() 和 numpy.amax()
numpy.amin() 用于计算数组中的元素沿指定轴的最小值。
numpy.amin(a, axis=None, out=None, keepdims=<no value>, initial=<no value>, where=<no value>)参数说明:
a: 输入的数组,可以是一个NumPy数组或类似数组的对象。axis: 可选参数,用于指定在哪个轴上计算最小值。如果不提供此参数,则返回整个数组的最小值。可以是一个整数表示轴的索引,也可以是一个元组表示多个轴。out: 可选参数,用于指定结果的存储位置。keepdims: 可选参数,如果为True,将保持结果数组的维度数目与输入数组相同。如果为False(默认值),则会去除计算后维度为1的轴。initial: 可选参数,用于指定一个初始值,然后在数组的元素上计算最小值。where: 可选参数,一个布尔数组,用于指定仅考虑满足条件的元素。
numpy.amax() 用于计算数组中的元素沿指定轴的最大值。
numpy.amax(a, axis=None, out=None, keepdims=<no value>, initial=<no value>, where=<no value>)参数说明:
a: 输入的数组,可以是一个NumPy数组或类似数组的对象。axis: 可选参数,用于指定在哪个轴上计算最大值。如果不提供此参数,则返回整个数组的最大值。可以是一个整数表示轴的索引,也可以是一个元组表示多个轴。out: 可选参数,用于指定结果的存储位置。keepdims: 可选参数,如果为True,将保持结果数组的维度数目与输入数组相同。如果为False(默认值),则会去除计算后维度为1的轴。initial: 可选参数,用于指定一个初始值,然后在数组的元素上计算最大值。where: 可选参数,一个布尔数组,用于指定仅考虑满足条件的元素。
numpy.ptp()
numpy.ptp() 函数计算数组中元素最大值与最小值的差(最大值 - 最小值)。
numpy.ptp(a, axis=None, out=None, keepdims=<no value>, initial=<no value>, where=<no value>)参数说明:
a: 输入的数组,可以是一个 NumPy 数组或类似数组的对象。axis: 可选参数,用于指定在哪个轴上计算峰-峰值。如果不提供此参数,则返回整个数组的峰-峰值。可以是一个整数表示轴的索引,也可以是一个元组表示多个轴。out: 可选参数,用于指定结果的存储位置。keepdims: 可选参数,如果为 True,将保持结果数组的维度数目与输入数组相同。如果为 False(默认值),则会去除计算后维度为1的轴。initial: 可选参数,用于指定一个初始值,然后在数组的元素上计算峰-峰值。where: 可选参数,一个布尔数组,用于指定仅考虑满足条件的元素。
numpy.percentile()
百分位数是统计中使用的度量,表示小于这个值的观察值的百分比。 函数numpy.percentile()接受以下参数。
numpy.percentile(a, q, axis)参数说明:
- a: 输入数组
- q: 要计算的百分位数,在 0 ~ 100 之间
- axis: 沿着它计算百分位数的轴
首先明确百分位数:
第 p 个百分位数是这样一个值,它使得至少有 p% 的数据项小于或等于这个值,且至少有 (100-p)% 的数据项大于或等于这个值。
举个例子:高等院校的入学考试成绩经常以百分位数的形式报告。比如,假设某个考生在入学考试中的语文部分的原始分数为 54 分。相对于参加同一考试的其他学生来说,他的成绩如何并不容易知道。但是如果原始分数54分恰好对应的是第70百分位数,我们就能知道大约70%的学生的考分比他低,而约30%的学生考分比他高。
这里的 p = 70。
numpy.median()
numpy.median() 函数用于计算数组 a 中元素的中位数(中值)
numpy.median(a, axis=None, out=None, overwrite_input=False, keepdims=<no value>)参数说明:
a: 输入的数组,可以是一个 NumPy 数组或类似数组的对象。axis: 可选参数,用于指定在哪个轴上计算中位数。如果不提供此参数,则计算整个数组的中位数。可以是一个整数表示轴的索引,也可以是一个元组表示多个轴。out: 可选参数,用于指定结果的存储位置。overwrite_input: 可选参数,如果为True,则允许在计算中使用输入数组的内存。这可能会在某些情况下提高性能,但可能会修改输入数组的内容。keepdims: 可选参数,如果为True,将保持结果数组的维度数目与输入数组相同。如果为False(默认值),则会去除计算后维度为1的轴。
numpy.mean()
numpy.mean() 函数返回数组中元素的算术平均值,如果提供了轴,则沿其计算。
算术平均值是沿轴的元素的总和除以元素的数量。
numpy.mean(a, axis=None, dtype=None, out=None, keepdims=<no value>)参数说明:
a: 输入的数组,可以是一个 NumPy 数组或类似数组的对象。axis: 可选参数,用于指定在哪个轴上计算平均值。如果不提供此参数,则计算整个数组的平均值。可以是一个整数表示轴的索引,也可以是一个元组表示多个轴。dtype: 可选参数,用于指定输出的数据类型。如果不提供,则根据输入数据的类型选择合适的数据类型。out: 可选参数,用于指定结果的存储位置。keepdims: 可选参数,如果为True,将保持结果数组的维度数目与输入数组相同。如果为False(默认值),则会去除计算后维度为1的轴。
numpy.average()
numpy.average() 函数根据在另一个数组中给出的各自的权重计算数组中元素的加权平均值。
该函数可以接受一个轴参数。 如果没有指定轴,则数组会被展开。
加权平均值即将各数值乘以相应的权数,然后加总求和得到总体值,再除以总的单位数。
考虑数组[1,2,3,4]和相应的权重[4,3,2,1],通过将相应元素的乘积相加,并将和除以权重的和,来计算加权平均值。
加权平均值 = (1*4+2*3+3*2+4*1)/(4+3+2+1)函数语法:
numpy.average(a, axis=None, weights=None, returned=False)参数说明:
a: 输入的数组,可以是一个 NumPy 数组或类似数组的对象。axis: 可选参数,用于指定在哪个轴上计算加权平均值。如果不提供此参数,则计算整个数组的加权平均值。可以是一个整数表示轴的索引,也可以是一个元组表示多个轴。weights: 可选参数,用于指定对应数据点的权重。如果不提供权重数组,则默认为等权重。returned: 可选参数,如果为True,将同时返回加权平均值和权重总和。
标准差
标准差是一组数据平均值分散程度的一种度量。
标准差是方差的算术平方根。
标准差公式如下:
std = sqrt(mean((x - x.mean())**2))如果数组是 [1,2,3,4],则其平均值为 2.5。 因此,差的平方是 [2.25,0.25,0.25,2.25],并且再求其平均值的平方根除以 4,即 sqrt(5/4) ,结果为 1.1180339887498949。
方差
统计中的方差(样本方差)是每个样本值与全体样本值的平均数之差的平方值的平均数,即 mean((x - x.mean())** 2)。
换句话说,标准差是方差的平方根。