一.字节交换
1.字节顺序:
在几乎所有机器上,多字节对象都被存储为连续的字节序列
字节顺序,指跨越多字节的程序对象的存储规则,包括:
1.大端模式:数据的高字节保存在内存的低地址中,低字节保存在高地址中
类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放,这和一般的阅读习惯一致
2.小端模式:数据的高字节保存在内存的高地址中,低字节保存在低地址中
将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低
2.变换字节顺序:
<a>.byteswap():将数组<a>中每个元素中的字节进行大小端转换
#实例:
>>> a=np.array([1,256,8755],dtype=np.int16)
>>> print(a)
[ 1 256 8755]
>>> print(map(hex,a))
<map object at 0x000002AF16F2C308>
>>> print(a.byteswap(True))#True表示原地交换
[ 256 1 13090]
>>> print(map(hex,a))
<map object at 0x000002AF16F2C388>
>>> print(a.byteswap(True))
[ 1 256 8755]
>>> print(map(hex,a))
<map object at 0x000002AF16F2C248>
二.副本和视图
1.概念:
副本:1个数据的完整的拷贝
如果对副本进行修改,不会影响到原始数据;物理内存不在同一位置
一般发生在:1.NumPy的切片操作返回原数据的视图 2.调用np.view()产生视图
视图:数据的1个别称/引用
通过该别称/引用可访问/操作原有数据,但原有数据不会产生拷贝
如果对视图进行修改,会影响到原始数据;物理内存在同一位置
一般发生在:1.Python的切片操作(调用deepCopy()) 2.调用np.copy()产生副本
2.无拷贝的情况:
简单的赋值不创建数组对象的副本,而是使用和原数组相同的id(通过id()获得)来访问
1个数组的任何变化都反映在另1个数组上;b is a为True
#实例:
>>> a=np.arange(6)
>>> id(a)
2444412702032
>>> b=a
>>> id(b)
2444412702032
>>> b is a
True
>>> a[3]=10
>>> print(a,b)
[ 0 1 2 10 4 5] [ 0 1 2 10 4 5]
>>> b.shape=3,2
>>> print(a)
[[ 0 1]
[ 2 10]
[ 4 5]]
3.浅拷贝(视图):
对视图/原数组形状的修改不影响对方
但对视图/原数组元素的修改会影响对方
二者的id也不同
b is a为False
##########################################################
<a>.view()会创建1个新数组对象
#实例:
>>> a=np.arange(6).reshape(3,2)
>>> b=a.view()
>>> print(a)
[[0 1]
[2 3]
[4 5]]
>>> id(a)
2444685922752
>>> id(b)
2444685922672
>>> b is a
False
>>> b.shape=2,3
>>> print(b)
[[0 1 2]
[3 4 5]]
>>> print(a)
[[0 1]
[2 3]
[4 5]]
>>> a.shape=1,6
>>> print(b)
[[0 1 2]
[3 4 5]]
>>> b[1,0]=0
>>> print(b)
[[0 1 2]
[0 4 5]]
>>> print(a)
[[0 1 2 0 4 5]]
>>> a[0]=10
>>> print(a)
[[10 10 10 10 10 10]]
>>> print(b)
[[10 10 10]
[10 10 10]]
##########################################################
使用切片赋值,被赋值的数组是被切片的数组的一部分视图
#实例:
>>> arr=np.arange(12)
>>> a=arr[3:]
>>> b=arr[3:]
>>> a[1]=123
>>> b[2]=234
>>> b is a
False
>>> a is arr
False
>>> print(a,b)
[ 3 123 234 6 7 8 9 10 11] [ 3 123 234 6 7 8 9 10 11]
>>> print(arr)
[ 0 1 2 3 123 234 6 7 8 9 10 11]
>>> print(id(a),id(b),id(arr),id(arr[3:]))
2552148577616 2552421650304 2552141974464 2552421667504
>>> print(a)
[[ 3 123 234]
[ 6 7 8]
[ 9 10 11]]
>>> print(b,arr)
[ 3 123 234 6 7 8 9 10 11] [ 0 1 2 3 123 234 6 7 8 9 10 11]
4.深拷贝(副本):
<a>.copy()创建1个副本
对副本的修改不会影响原数据;二者的id不同,物理内存也不在同一位置
#实例:
>>> a=np.array([[10,10],[2,3],[4,5]])
>>> b=a.copy()
>>> b is a
False
>>> b==a
array([[ True, True],
[ True, True],
[ True, True]])
>>> print(id(a),id(b))
2552421667504 2552148577616
>>> b[0,0]=100
>>> print(a)
[[10 10]
[ 2 3]
[ 4 5]]
>>> print(b)
[[100 10]
[ 2 3]
[ 4 5]]
三.切片和索引
- 对ndarray进行切片/索引是获得1个试图,而不复制数据,这点与普通的list不同;这是为了在处理大量数据时降低性能和内存的开销
1.基本索引和切片:
#索引从0开始
<ndarray>[index,...]
<ndarray>[start:stop:step,...]
使用","分隔用于不同维度的切片/索引;该语法不适用于Python
使用"..."使选择元组的长度与数组维度相同;1此只能用1个"..."
#参数说明:1个参数默认为index;2个默认为start和stop
start:开始位置(含);默认为0
stop:结束位置(不含);默认为-1(除最后1位)
step:步长;默认为1
#实例:
>>> import numpy as np
>>> a=np.arange(10)
>>> a[2]
2
>>> a[1:2]
array([1])
>>> a[:3]
array([0, 1, 2])
>>> a[5:]
array([5, 6, 7, 8, 9])
>>> a[3:7:2]
array([3, 5])
>>> b=np.array([[[i for i in range(10)],[i+1 for i in range(10)]],[[i+2 for i in range(10)],[i+3 for i in range(10)]],[[i+4 for i in range(10)],[i+5 for i in range(10)]]])
>>> print(b)
[[[ 0 1 2 3 4 5 6 7 8 9]
[ 1 2 3 4 5 6 7 8 9 10]]
[[ 2 3 4 5 6 7 8 9 10 11]
[ 3 4 5 6 7 8 9 10 11 12]]
[[ 4 5 6 7 8 9 10 11 12 13]
[ 5 6 7 8 9 10 11 12 13 14]]]
>>> b[2,1]
array([ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])
>>> b[0:2,1,3:9:2]
array([[ 4, 6, 8],
[ 6, 8, 10]])
>>> b[1,...,0,...]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: an index can only have a single ellipsis ('...')
>>> b[1,...,1,6]
array(9)
2.高级索引
(1)整数数组索引:
<ndarray>[[x1,x2,...],[y1,y2,...],...]:返回(x1,y1,...),(x2,y2,...)...处的元素
#也可以使用切片/索引/"..."
>>> a=np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> print(a)
[[1 2 3]
[4 5 6]
[7 8 9]]
>>> x=a[[0,0],[1,1]]
>>> print(x)
[2 2]
>>> y=a[[0,1],[2,1]]
>>> print(y)
[3 5]
>>> x=np.array([[0,1,2],[3,4,5],[6,7,8],[9,10,11]])
>>> print(x)
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]]
>>> rows=np.array([[0,0],[3,3]])
>>> cols=np.array([[0,2],[0,2]])
>>> y=x[rows,cols]
>>> print(y)#获得x四角的元素
[[ 0 2]
[ 9 11]]
>>> a=np.array([[1,2,3], [4,5,6],[7,8,9]])
>>> b=a[1:3,1:3]
>>> c=a[1:3,[1,2]]
>>> d=a[...,1:]
>>> print(b)
[[5 6]
[8 9]]
>>> print(c)
[[5 6]
[8 9]]
>>> print(d)
[[2 3]
[5 6]
[8 9]]
(2)布尔索引:
<ndarray>[条件]:通过布尔运算(如比较运算符)获取符合条件的元素
#在条件中用ndarray的变量名代表ndarray中的元素
>>> x=np.array([[0,1,2],[3,4,5],[6,7,8],[9,10,11]])
>>> print(x[x>5])#获得大于5的元素
[ 6 7 8 9 10 11]
>>> a=np.array([np.nan,1,2,np.nan,3,4,5])
>>> print(a[~np.isnan(a)])#过滤NaN
[1. 2. 3. 4. 5.]
>>> a=np.array([1,2+6j,5,3.5+5j])
>>> print(a[np.iscomplex(a)])
[2. +6.j 3.5+5.j]
(3)花式索引:
<ndarray>[[x1,x2,...]]:返回的数组中第x1,x2...个元素构成的数组
#索引xi,yi...可以为负数(倒叙索引)
<ndarray>[np.ix_([x1,x2...],[y1,y2...]...)]:返回(xi,yj...)处的元素构成的数组(i,j...=1,2...)
>>> x=np.arange(32).reshape((8,4))
>>> print(x[[4,2,1,7]])
[[16 17 18 19]
[ 8 9 10 11]
[ 4 5 6 7]
[28 29 30 31]]
>>> print(x[np.ix_([1,5,7,2],[0,3,1,2])])
[[ 4 7 5 6]
[20 23 21 22]
[28 31 29 30]
[ 8 11 9 10]]
四.广播(Broadcast)
1.功能:
NumPy对不同形状(shape)的数组进行数值计算的方式
对数组的算术运算通常在对应的元素上进行
但当运算中的2个数组的形状不同时,自动触发广播机制
2.规则:
·所有输入数组向其中维度最多的数组看齐,不存在的维度长度定为1
·输出数组的形状是所有输入数组形状在各个维度上的最大值
·当输入数组的某维度长度为1或输出数组对应维度的长度,该输入数组可以进行计算,否则报错
·当输入数组的某维度长度为1,沿此维度运算时都用此维度上的唯一1组值
#理解:
对2个数组,分别比较每个维度(若有1个数组没有该维度则忽略),要求满足:
数组拥有相同形状
当前维度的值相等
当前维度的值有1个是1
若条件不满足,抛出"ValueError: frames are not aligned"异常
3.实例:
#如果a.shape==b.shape
>>> a=np.array([1,2,3,4])
>>> b=np.array([10,20,30,40])
>>> c=a*b
>>> print (c)
[ 10 40 90 160]#对应元素相乘
#如果a.shape!=b.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]#b与a的各行分别相加
[11 12 13]
[21 22 23]
[31 32 33]]
#等效于:
>>> a=np.array([[0,0,0],[10,10,10],[20,20,20],[30,30,30]])
>>> b=np.array([1,2,3])
>>> bb=np.tile(b,(4,1))#重复b的各个维度
>>> print(a+bb)
五.I/O操作
NumPy可以读写磁盘上的文本/二进制数据
.npy文件用于存储重建Ndarray所需的数据/图形/dtype/其他信息
1个.npy文件只能存储1个Ndarray对象
而1个.npz文件可以存储多个数组(实际就是对.npy文件的打包)
1.npy/npz文件:
npy文件是NumPy专用的二进制文件;npz文件则是NumPy专用的二进制压缩文件
#########################################################
np.save("<file>",<arr>[,allow_pickle=True,fix_imports=True]):将数组arr保存到npy文件中
#数组以未压缩的原始二进制格式保存在npy文件中
#返回None
#参数说明:
file:要保存到的npy文件;为str/file object
#包括路径及文件名;如果没有加扩展名npy,会自动添加
#如果文件不存在,自动创建;如果已经存在,覆盖原有的数组
arr:要保存的数组
aloow_pickle:是否允许使用Python pickles保存对象数组;bool
#Python中的pickle用于在保存到磁盘文件或从磁盘文件读取之前,对对象进行序列化和反序列化
fix_import:为了方便用Pyhton3读取Python2保存的pickles
#实例:
>>> a=np.array([[1,2,3],[2,3,4],[3,4,5]])
>>> b=np.save("G:\\a.npy",a)
>>> print(b)
None
>>> b=np.array([[1,2],[2,3]])
>>> np.save("G:\\a2",b)
#########################################################
np.savez(<file>,*args,**kwds):将多个数组保存到npz文件中
#数组以未压缩的原始二进制格式保存在npz文件中
#返回None
#参数说明:
file:要保存到的npz文件;为str/file object
args:要保存的数组
格式:a1,a2...(解压后每个数组对应1个npy文件)
kwds:要保存的数组使用的关键字名称(对应的npy文件的名字)
#非关键字参数传递的数组会自动起名为arr_0,arr_1,…
格式:<name1>=<a1>,<name2>=<a2>...
#name都不需要""(非str)和.npz
#实例:
>>> a=np.array([[1,2,3],[2,3,4],[3,4,5]])
>>> b=[[1,2,3],[4,5,6]]
>>> c=[1,3,5,7,9]
>>> np.savez("G:\\a",a,b,c)#命名为arr_0.npy,...,arr_2.npy
>>> np.savez("G:\\a",a=a,b=b,c=c)#命名为a.npy,...,c.npy
#########################################################
np.load(<file>[,mmap_mode=None,allow_pickle=True,fix_imports=True,encoding='ASCII']):读取npy/npz文件
#参数说明:allow_pickle和fix_import同np.save()
file:要读取的文件;为str/file object
mmap_mode:读取模式;可为"r+"/"r"/"w+"/"c"(?什么模式)
encoding:编码方式;可为"latin1"/"ASCII"/"bytes"
#实例:
>>> a=np.array([[1,2,3],[2,3,4],[3,4,5]])
>>> np.save("G:\\a.npy",a)
>>> a=np.load("G:\\a.npy")
>>> print(a)
[[1 2 3]
[2 3 4]
[3 4 5]]
>>> b=[[1,2,3],[4,5,6]]
>>> c=[1,3,5,7,9]
>>> np.savez("G:\\a2",a=a,b=b,c=c)
>>> d=np.load("G:\\a2.npz")
>>> print(d)
<numpy.lib.npyio.NpzFile object at 0x0000020694093048>
>>> print(d["a"])
[[1 2 3]
[2 3 4]
[3 4 5]]
2.无格式的二进制文件:
将ndarray保存为无格式的二进制文件:<ndarray>.tofile("<fid>"[,sep="",format="%s")
#详情参见 Python.第三方模块.科学计算.NumPy模块.简介,多维数组,数据类型,矩阵库.二.4.(2) 部分
#########################################################
读取无格式的二进制文件:np.fromfile("<file>"[,dtype=None,count=-1,sep="",offset=0])
#参数说明:
file:指定要读取的文件;为str/file object
dtype:指定数据类型
count:指定要读取的元素数;为int,-1表示读取所有
sep:指定分隔符;为str
#实例:
>>> a=np.array([[[1,2],[3,4]],[[5,6],[7,8]]])
>>> a.tofile("E:\\1")
>>> np.fromfile("E:\\1",dtype=int)
array([1, 2, 3, 4, 5, 6, 7, 8])
3.txt/csv文件:
以文本文件格式(.txt)存储数组:np.savetxt("<fname>",<X>[,fmt='%.18e',delimiter=' ',newline='\n',header='',footer='',comments='# ',encoding=None])
#返回None
#参数说明:delimeter同np.loadtxt()
fname:要保存到的文件;为str/file object
#不会自动加上扩展名(但不加也能用)
X:要存储的数组;为1/2d array-like
fmt:写入数据的格式;为str/str sequence
delimiter:指定分隔符;为str
#实例:
>>> a=[[1,2],[3,4]]
>>> np.savetxt("G:\\a.txt",a)
>>> np.savetxt("E:\\1.csv",a)
#########################################################
读取.txt文件中的数组:np.loadtxt("<fname>"[,dtype=float,comments='#',delimiter=' ',converters=None,skiprows=0,usecols=None,unpack=False,ndmin=0,encoding='bytes',max_rows=None])
#参数说明:
fname:要读取的文件;str/file object
dtype:数据类型
#实例:接上
>>> b=np.loadtxt("G:\\a")
>>> print(b)
[[1. 2.]
[3. 4.]]
>>> np.loadtxt("E:\\1.csv")
array([[1., 2.],
[3., 4.]])
>>> np.savetxt("G:\\a.txt",a)
>>> b=np.loadtxt("G:\\a.txt")
>>> print(b)
[[1. 2.]
[3. 4.]]
六.一些特殊值
非数值:np.nan
np.NAN
np.NaN
无穷大:np.Inf
np.inf
np.infty
np.Infinity
np.PINF
np.bool_类型的真:np.True_
np.bool_类型的假:np.False_