参见:https://www.runoob.com/numpy/numpy-tutorial.html
一.简介
·NumPy代表Numeric Python,是1个由多维数组对象及用于处理数组的例程集合组成的库
例程:系统对外提供的功能接口/服务的集合
·主要用于数组计算,包含:
1.强大的n维数组对象Ndarray
2.广播功能函数
3.整合C/C++/Fortran代码的工具
4.傅里叶变换/线性代数/随机数生成等功能
·通常与SciPy和Matplotlib一起使用,广泛用于替代MATLAB
优势:Python是1种更为现代和完整的编程语言;NumPy是开源的
SciPy是个开源的Python算法库和数学工具包,包含最优化/线性代数/积分/插值/特殊函数/快速傅里叶变换/信号和图像处理/常微分方程求解和其他科学与工程中常用的计算
Matplotlib是Python及其数值数学扩展包NumPy的可视化操作界面,为利用通用的图形用户界面工具包,如Tkinter/wxPython/Qt/QTK+向应用程序嵌入式绘图提供了应用程序接口(API)
#通常导入为np:
import numpy as np
二.多维数组对象(Ndarray)
1.概念:
·NumPy中最重要的对象是被称为Ndarray的n维数组类型
·Ndarray是数学中张量的逻辑表达(0维是数,1维是向量,2维是矩阵)
·Ndarray对象由内存中的1维连续区域组成,带有将每个元素映射到内存块中某位置的索引
·每个元素都在内存中使用相同大小的块,是数据类型对象(Dtype)的对象
1.Header:信息头
·指向数据(内存或内存映射文件中的一块数据)的指针。
·数据类型,描述在数组中的固定大小值的格子
·表示数组形状(shape;各维度大小)的元组
·跨度元组(stride),其中的整数指为前进到当前维度下1个元素需要跨过的字节数
跨度可以是负数,这样会使数组在内存中后向移动,如obj[::-1]/obj[:,::-1]
2.data:数据块,一系列相同大小的内存块;存放的是实际的数据值
- 列表(List)与数组(Array)的异同:
同:①list与1维数组(1d array)都是用于表示1维数据的有序结构
异:①list中不同元素的数据类型可以不同,array中不同元素的数据类型必须相同
②array的存储效率和IO性能远优于嵌套list,且数据量越大优势越明显
③array的通用性能不及list,但在科学计算中可省掉很多循环语句,在代码使用方面比list简单得多
2.创建数组:
(1)创建一般数组:
类对象:np.array
实例化:np.array(<object>[,dtype=none,copy=True,order="K",subok=False,ndmin=0])
#参数说明:
object:用于生成Ndarray对象的对象
可为任何暴露数组接口的对象/嵌套的数列/返回数组的方法
dtype:返回的数组中元素的数据类型
默认为object中输入的数据类型
可以是变量,str,[("key",value),...]形式
copy:object是被复制还是被引用
order:指定阵列的内存布局
可为"C"(按行;C风格)
"F"(按列;Fortran或MATLAB风格)
"A"(原顺序)
"K"(按元素在内存中的出现顺序)
subok:为False,返回的数组被强制为基类类型;为True,返回的数组为子类类型
ndmin:返回的数组的最小维数
#实例:
>>> np.array
<built-in function array>
>>> a1=np.array([1,2,3])
>>> a1
array([1, 2, 3])
>>> print(a1)
[1 2 3]
>>> a2=np.array((1,2,3))
>>> print(a2)
[1 2 3]
>>> b=np.array([[1,2],[3,4],[5,6]])
>>> print(b)
[[1 2]
[3 4]
[5 6]]
>>> c=np.array([1,2,3],ndmin=2)
>>> print(c)
[[1 2 3]]
>>> d=np.array([1,2,3],dtype=complex)
>>> print(d)
[1.+0.j 2.+0.j 3.+0.j]
>>> a=np.array([[1,2,'asd'],['121',[1,'ww'],3],[3,2,1]])
>>> print(a)
[[1 2 'asd']
['121' list([1, 'ww']) 3]
[3 2 1]]
>>> f=np.array([1, 2, 3])
>>> g=np.array(a)#copy默认为True
>>> f[0]=0
>>> print(f,g)
[0 2 3] [1 2 3]#说明g和f指向不同对象
>>> g2=np.array(a,copy=False)
>>> f[1]=0
>>> print(f,g2)
[0 0 3] [0 0 3]#说明g和f指向同1个对象
>>> a=np.matrix('1 2 7;3 4 8;5 6 9')
>>> print(type(a),"\n",a)
<class 'numpy.matrix'>
[[1 2 7]
[3 4 8]
[5 6 9]]
>>> at=np.array(a,subok=True)
>>> af=np.array(a,subok=False)
>>> print(type(at),type(af))
<class 'numpy.matrix'> <class 'numpy.ndarray'>
(2)创建特殊数组:
np.empty(<shape>[,dtype=float,order="C"]):创建未初始化的数组
#由于数组元素未初始化,均为随机值
#参数说明:只有shape必选
shape:指定数组的形状;为数组或元组
dtype:指定数据类型;如果不指定占用字节数,无需加"";否则,需要引号
#其余见np.array();上述也适用于np.array()
order:功能同np.array;但只能为"C"或"F"
#实例:
>>> np.empty((2,3),dtype=int)
array([[ 49, 101, 49],
[ 50, 115, 97]])
>>> np.empty((2,3),dtype=int32)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'int32' is not defined
>>> np.empty((2,3),dtype="int32")
array([[ 49, 101, 49],
[ 50, 115, 97]])
##########################################################
np.zeros(<shape>[,dtype=float,order="C"]):创建1个所有元素均为0的数组
#参数说明:同np.empty
##########################################################
np.ones(<shape>[,dtype=float,order="C"]):创建1个所有元素均为1的数组
#参数说明:同np.empty
##########################################################
np.full(<shape>,<fill_value>[,dtype=None,order="C"]):创建1个所有元素均为指定值的数组
#参数说明:其他同np.empty()
fill_value:指定数组中的元素
#实例:
>>> np.full([1,2,1],9.9)
array([[[9.9],
[9.9]]])
##########################################################
np.eye(<N>[,M=None,k=0,dtype=float,order="C"]):返回对角线上为1,其余元素为0的矩阵
#同 Python.第三方模块.科学计算.NumPy模块.子模块.一.2.(2) 部分的np.matlib.eye();除了第1个参数为N外(但含义相同)均相同
##########################################################
np.identity(<n>[,dtype=None]):创建单位矩阵
#同 Python.第三方模块.科学计算.NumPy模块.子模块.一.2.(2) 部分的np.matlib.identity()
(3)从已有数组创建数组:
np.asarray(<a>[,dtype=None,order="C"]):根据a生成Ndarray对象,类似.array
#参数说明:除a均为关键字参数
a:可以是列表,列表的元组,元组,元组的元组,元组的列表,多维数组
dtype:数据类型;None表示从输入的数据中推断
order:内存中存储元素的顺序;可为"C"/"F"
#实例:
>>> a=np.asarray([1,2,3])
>>> print(a)
[1 2 3]
##########################################################
np.frombuffer(<buffer>[,dtype=float,count=-1,offset=0]):用于实现动态数组,以流的形式读入buffer并转化成Ndarray对象
#返回1维数组
#参数说明:除buffer,均为关键字参数
buffer:可以是任意对象,会以流的形式被读入
#注意:在Python3中str默认是Unicode类型,需要在前面加b转成Bytes类型;在Python2中不用
dtype:返回的数组的数据类型
count:读取的数据数量,即读取的结束位置;-1表示读取所有数据
offset:读取的起始位置
#实例:
>>> s= b'Hello World'#要转换成Bytes类型
>>> a=np.frombuffer(s,dtype='S1')
>>> print(a)
[b'H' b'e' b'l' b'l' b'o' b' ' b'W' b'o' b'r' b'l' b'd']
##########################################################
np.fromiter(<iterable>[,dtype,count=-1]):从可迭代对象中建立Ndarray对象
#返回1维数组
#参数说明:其他参数同np.frombuffer()
iterable:可迭代对象
##########################################################
np.ones_like(<a>[,dtype=None,order="K",subok=True,shape=None]):根据已有数组创建1个元素全为1的数组
#参数说明:
a:指定数组的性质/数据类型;为array-like
#生成的数组的形状/数据类型和该数组相同
order:内存中存储元素的顺序;可为"C"/"F"/"A"/"K"
shape:指定生成的数组的形状;为int/int sequence
#会覆盖<a>的形状
##########################################################
np.zeros_like(<a>[,dtype=None,order="K",subok=True,shape=None]):根据已有数组创建1个元素全为0的数组
#参数说明:同np.ones_like()
##########################################################
np.full_like(<a>,<fill_value>[,dtype=None,order="K",subok=True,shape=None]):根据已有数组创建1个元素全为指定元素的数组
#参数说明:<fill_value>同np.full(),其他同np.ones_like()
(4)从数值范围创建数组:
np.arange([start=0,stop,step=1,dtype]):创建等差数列构成的1维数组,指定差值
#参数说明:除dtype,均为位置参数;
start,stop,step:分别指定起始值(含)/终止值(不含)/步长;为int
dtype:返回的数组中的数据类型;默认为输入的类型
#实例:
>>> a=np.arange(1.1,2,0.1)
>>> print(a)
[1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9]
>>> a=np.arange(5,dtype=float)
>>> print(a)
[0. 1. 2. 3. 4.]
##########################################################
np.linspace(<start>,<stop>[,num=50,endpoint=True,retstep=False,dtype=None]):创建由等差数列构成的1维数组,指定元素数
#参数说明:dtype同.arange()
start:起始值(包含)
stop:终止值(默认包含)
num:数列中元素数
endpoint:是否包含stop值
retstep:如果为True,生成的数组中会显示间距;反之不显示
#实例:
>>> a=np.linspace(1,10,10,retstep= True)
>>> print(a)
(array([ 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.]), 1.0)
>>> b=np.linspace(1,10,10).reshape([10,1])
>>> print(b)
[[ 1.]
[ 2.]
[ 3.]
[ 4.]
[ 5.]
[ 6.]
[ 7.]
[ 8.]
[ 9.]
[10.]]
##########################################################
np.logspace(<start>,<stop>[,num=50,endpoint=True,base=10.0,dtype=None]):创建由等比数列构成的1维数组,指定元素数
#取对数后即为等差数列
#参数说明:endpoint,num,dtype同.linspace();前3个为位置参数
start:起始值为base**start(包含)
stop:终止值为base**stop(默认包含)
base:取对数时log的下标(底数)
#实例:
>>> a=np.logspace(1,10,10)
>>> print(a)
[1.e+01 1.e+02 1.e+03 1.e+04 1.e+05 1.e+06 1.e+07 1.e+08 1.e+09 1.e+10]
3.属性:
在NumPy中,每个线性的数组称为1个轴(Axis),也就是1个维度(Dimension),数组的轴的数量称为秩(Rank)
比如说,2维数组相当于2个1维数组,其中第1个1维数组中每个元素又是1个1维数组
所以1维数组就是NumPy中的轴,第1个轴相当于是底层数组,第2个轴是底层数组里的数组
而轴的数量即秩,就是数组的维数
轴的编号从0开始,输入时外层[ ]对应的轴的编号较小,即n,n-1...依次对应沿行的轴,沿列的轴,沿纵深的轴...
很多时候可以声明axis
axis=0,表示沿着第0轴进行操作;axis=1,表示沿着第1轴进行操作;axis=n-1表示对每列进行操作;axis=n表示对每行进行操作
#########################################################
.ndim:Ndarray对象的维数
>>> a=np.array([[[1],[1]],[[1],[2]],[[3],[4]]])
>>> a.ndim
3
>>> b=np.array([[[1],[1]],[[1],[2]],[[3],[4,2]]])
>>> b.ndim
2
.shape:Ndarray对象各维度的长度构成的元组
#可通过.reshape()进行调整
>>> a.shape
(3, 2, 1)
.size:Ndarray对象中元素总数
#相当于.shape的结果中的各元素的乘积
#即a.size=Π(a.shape[i])
>>> c=np.array([[1,1],[1,2],[3,4]])
>>> c.size
6
.dtype:Ndarray对象的元素类型
>>> c.dtype
dtype('int32')
>>> d=np.array([[1,"sd"],[["s",()],1]])
>>> d.dtype
dtype('O')#这是英文字母"O",代表Python对象
.itemsize:Ndarray对象中每个元素的大小
#以B为单位
>>> c.itemsize
4
>>> d.itemsize
8
.flags:Ndarray对象的内存信息
#包含以下信息:
C_CONTIGUOUS:数据是否在1个单一的C风格的连续段中
F_CONTIGUOUS:数据是在1个单一的Fortran风格的连续段中
OWNDATA:数组是否拥有它所使用的内存(False表示是引用了另1个对象)
WRITEABLE:数据区域是否可以被写入(False表示只读)
ALIGNED:数据和所有元素是否都适当地对齐到硬件上
UPDATEIFCOPY:这个数组是否是其它数组的副本
>>> c.flags
C_CONTIGUOUS : True
F_CONTIGUOUS : False
OWNDATA : True
WRITEABLE : True
ALIGNED : True
WRITEBACKIFCOPY : False
UPDATEIFCOPY : False
.real:Ndarray对象中元素的实部
#对字符串,列表等数据类型,实部就是数据本身
>>> e=np.array([1+2j,2])
>>> e.real
array([1., 2.])
>>> d.real
array([[1, 'sd'],
[list(['s', ()]), 1]], dtype=object)
.imag:Ndarray对象中元素的虚部
#对字符串,列表等数据类型,虚部就是0
>>> e.imag
array([2., 0.])
>>> d.imag
array([[0, 0],
[0, 0]], dtype=object)
.data:包含实际数组元素的缓冲区(1个内存地址)
#由于一般通过数组的索引获取元素,所以通常不需要使用该属性
>>> e.data
<memory at 0x000001E7F6F20D08>
4.方法
(1)修改元素的数据类型:
<ndarray>.as_type(<type>):将ndarray对象中的元素修改为指定数据类型
#参数说明:
ndarray:指定要修改的ndarray对象
type:指定修改后的数据类型
#实例:
>>> ns=np.array([1.23,2.34,3.45],dtype=np.string_)
>>> print(ns)
[b'1.23' b'2.34' b'3.45']
>>> nf=ns.astype(np.float)
>>> print(nf)
[1.23 2.34 3.45]
(2)修改多维数组的数据类型:
<ndarray>.tolist():转换为list
#实例:
>>> np.eye(N=3,k=1).tolist()
[[0.0, 1.0, 0.0], [0.0, 0.0, 1.0], [0.0, 0.0, 0.0]]
######################################################################################################################
<ndarray>.tofile("<fid>"[,sep="",format="%s"]):保存为无格式的二进制文件
#参数说明:
fid:指定保存到的文件;为str/file object
sep:指定分隔符;为str
format:指定保存数据的格式;为str
#实例:
>>> a=np.array([[[1,2],[3,4]],[[5,6],[7,8]]])
>>> a.tofile("E:\\1")
5.数组运算
"向量化计算"(Vectorization/Vectorized Operation/Array Programming)是1种特殊的并行计算方式,可在同一时间执行多次操作,通常是
对一批不同的数据执行1个相同的指令,或者说把1个指令应用于向量/数组中的每个元素.如ndarray的四则运算,比较和很多函数都是向量化计算.使
用向量化计算代替for循环可大幅提高性能
(1)数组与数组的运算:
<ndarray>+<ndarray>:相加
<ndarray>-<ndarray>:相减
<ndarray>*<ndarray>:相乘
<ndarray>/<ndarray>:相除
#实际上是让2个数组中的对应元素进行运算,因而支持所有该类型元素支持的运算
#实例:
>>> a=np.ones(2)
>>> b=np.ones(2)
>>> a+b
array([2., 2.])
>>> a-b
array([0., 0.])
>>> a*b
array([1., 1.])
>>> a/b
array([1., 1.])
(3)数组与标量的运算:
相加:<ndarray>+<scalar>
<scalar>+<ndarray>
相减:<ndarray>-<scalar>
<scalar>-<ndarray>
相乘:<ndarray>*<scalar>
<scalar>*<ndarray>
相除:<ndarray>/<scalar>
<scalar>/<ndarray>
乘方:<ndarray>**<scalar>
<scalar>**<ndarray>
#实际上是让标量与数组中的每个元素进行运算,因而支持所有该类型元素支持的运算
#实例:接上
>>> a+3
array([4., 4.])
>>> 3+a
array([4., 4.])
>>> a-3
array([-2., -2.])
>>> 3-a
array([2., 2.])
>>> a*3
array([3., 3.])
>>> 3*a
array([3., 3.])
>>> a/3
array([0.33333333, 0.33333333])
>>> 3/a
array([3., 3.])
>>> a**2
array([1., 1.])
>>> 2**a
array([2., 2.])
三.数据类型对象(Dtype)
1.数据类型
NumPy支持的数据类型远多于Python内置的类型
基本上可以和C的数据类型对应,其中部分与Python内置类型对应
NumPy的数据类型是Dtype对象的实例,并对应唯一的字符,如np.bool_/np.int32
2.数据类型对象:
数据类型对象用来描述与数组对应的内存区域如何使用,这取决于:
1.数据的类型(如整数/浮点数/Python对象)
2.数据的大小(如整数使用多少B存储)
3.数据的字节顺序(小端法或大端法)
字节顺序通过对数据类型预先设定"<"或">"决定
"<"表示小端法(最小值存储在最小的地址,即低位组放在最前面)
">"表示大端法(最重要的字节存储在最小的地址,即高位组放在最前面)
4.在结构化类型的情况下,字段的名称/每个字段的数据类型/每个字段所取的内存块的部分
5.如果数据类型是子数组,它的形状和数据类型
3.创建Dtype的对象
numpy.dtype(<object>,align=<bool>,copy=True)
#参数说明:
object:要转换为的数据类型对象
可为变量(如np.int32)或str(如'complex')
align:如果为True,填充字段使其类似C的结构体
copy:为True,复制Dtype对象;为False,引用内置数据类型对象
#实例:
>>> a=np.dtype('int32')
>>> a
dtype('int32')
>>> print(a)
int32
>>> a=np.dtype('complex')
>>> print(a)
complex128
>>> a=np.dtype('complex_')
>>> print(a)
complex128
#创建结构化数据类型,类型字段和对应的实际类型将被创建:
>>> a=np.dtype([('age',np.int8)])
>>> print(a)
[('age', 'i1')]
#将数据类型应用于Ndarray对象:
>>> b=np.array([(10,),(20,),(30,)],dtype=a)
>>> print(b)
[(10,) (20,) (30,)]
>>> a=np.dtype([('age',np.int8)])
>>> b=np.array([(10,),(20,),(30,)],dtype=a)
>>> print(b['age'])
[10 20 30]
>>> student=np.dtype([('name','S20'),('age','i1'),('marks','f4')])
>>> a=np.array([('abc',21,50),('xyz',18,75)],dtype=student)
>>> print(a)
[('abc',21,50.0),('xyz',18,75.0)]
4.数据类型的字符代码:
每个内建类型都有1个唯一定义它的字符代码.如果在字符代码后加1个int,该int表示占用的字节数,如int8/int16/int32/int64分别用'i1'/'i2'
/'i4'/'i8'来表示